Coder Social home page Coder Social logo

vortico / flama Goto Github PK

View Code? Open in Web Editor NEW
254.0 9.0 15.0 6.11 MB

Fire up your models with the flame 🔥

Home Page: https://flama.dev

License: Apache License 2.0

Python 93.77% HTML 0.02% JavaScript 0.90% Dockerfile 0.06% Makefile 0.17% Jinja 0.05% Shell 0.91% TypeScript 3.89% CSS 0.24%
starlette dependency-injection api type-system openapi swagger components marshmallow apispec crud

flama's Introduction

Flama

Fire up your models with the flame 🔥

Test And Publish workflow status Docker Push workflow status Package version PyPI - Python Version


Flama

Flama is a python library which establishes a standard framework for development and deployment of APIs with special focus on machine learning (ML). The main aim of the framework is to make ridiculously simple the deployment of ML APIs, simplifying (when possible) the entire process to a single line of code.

The library builds on Starlette, and provides an easy-to-learn philosophy to speed up the building of highly performant GraphQL, REST and ML APIs. Besides, it comprises an ideal solution for the development of asynchronous and production-ready services, offering automatic deployment for ML models.

Some remarkable characteristics:

  • Generic classes for API resources with the convenience of standard CRUD methods over SQLAlchemy tables.
  • A schema system (based on Marshmallow or Typesystem) which allows the declaration of inputs and outputs of endpoints very easily, with the convenience of reliable and automatic data-type validation.
  • Dependency injection to make ease the process of managing parameters needed in endpoints via the use of Components. Flama ASGI objects like Request, Response, Session and so on are defined as Components ready to be injected in your endpoints.
  • Components as the base of the plugin ecosystem, allowing you to create custom or use those already defined in your endpoints, injected as parameters.
  • Auto generated API schema using OpenAPI standard.
  • Auto generated docs, and provides a Swagger UI and ReDoc endpoints.
  • Automatic handling of pagination, with several methods at your disposal such as limit-offset and page numbering, to name a few.

Installation

Flama is fully compatible with all supported versions of Python. We recommend you to use the latest version available.

For a detailed explanation on how to install flama visit: https://flama.dev/docs/getting-started/installation.

Getting Started

Visit https://flama.dev/docs/getting-started/quickstart to get started with Flama.

Documentation

Visit https://flama.dev/docs/ to view the full documentation.

Example

from flama import Flama

app = Flama(
    title="Hello-🔥",
    version="1.0",
    description="My first API",
)


@app.route("/")
def home():
    """
    tags:
        - Salute
    summary:
        Returns a warming message
    description:
        This is a more detailed description of the method itself.
        Here we can give all the details required and they will appear
        automatically in the auto-generated docs.
    responses:
        200:
            description: Warming hello message!
    """
    return {"message": "Hello 🔥"}

This example will build and run a Hello 🔥 API. To run it:

flama run examples.hello_flama:app

Authors

Contributing

This project is absolutely open to contributions so if you have a nice idea, please read our contributing docs before submitting a pull request.

flama's People

Contributors

ekohl avatar jsatt avatar matrixise avatar migduroli avatar perdy avatar rayrrr avatar semantic-release-bot avatar songww avatar wheresalice avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flama's Issues

Artifacts in flm model files

Currently FLM files include both the model binary and the metadata associated to such model. This is OK for ML projects where models are self-sufficient, i.e. there is no additional dependency on other resources. However, there are situations in which the models might need additional data to be loaded with them. Such data is typically referred to as artifacts. Thus, there is value in making possible the packing of the model along with the additional artifacts needed by them for their correct working.

PyYaml is a hard requirement

PyYAML is used for parsing route functions docstrings, so it's mandatory to install it along with flama as a proper python requirement.

Not compatible with authentication ?

Hi there,
I just try to plugin authentication from Starlette, but looks like this is not possible.
From Starlette doc

from starlette.authentication import requires

@requires('authenticated')
async def foobar(request, schema: Schema):
    pass

This will raise error AttributeError: 'OpenAPIConverter' object has no attribute 'field2parameter' from flama/schemas.py
Can't omit first parameter request cause that is required from the requires decorator for authentication.
Any work around?
Thanks

Shortcuts for generating routes based on http verbs

It would be desirable to allow creating routes like this:

@app.get("/foo/")
def foo():
    return {"message": "foo"}

as a shortcut for:

@app.route("/foo/", methods=["GET"])
def foo():
    return {"message": "foo"}

request syntax in flama

objective
can have api from cli
e.g.
request.headers['api_key']
curl -X GET -i http://localhost:8000/api/http_api_key/instrument/ -H 'api_key: stifix'
request.query_params
curl -X PUT -i "http://localhost:8000/api/put/instrument/2?name=name0&strings=0"
request.form()
curl -X PUT -d "name=name1&strings=1" -i http://localhost:8000/api/put/instrument/2
request.json()
curl -X PUT -d '{"name": "name2", "strings": 2}' -i http://localhost:8000/api/put_json/instrument/2

in starlette we can use request
e.g.

def test(request):
    request.headers['api_key']
    request.query_params
    request.form()
    request.json()

since flama is base on starlette, what is equivalent of starlette request above ?

thanks

Cannot import name 'ASGIInstance'

Hi there,

when trying out the example in the README, I get a strange import error for the typing module:

Traceback (most recent call last):
  File "D:/projects/autogram/autogram/api/registrations.py", line 3, in <module>
    from flama.applications import Flama
  File "C:\Users\joscha.goetzer\.virtualenvs\autogram-PRYPx28t\lib\site-packages\flama\applications.py", line 12, in <module>
    from flama.injection import Injector
  File "C:\Users\joscha.goetzer\.virtualenvs\autogram-PRYPx28t\lib\site-packages\flama\injection.py", line 8, in <module>
    from flama.components.validation import VALIDATION_COMPONENTS
  File "C:\Users\joscha.goetzer\.virtualenvs\autogram-PRYPx28t\lib\site-packages\flama\components\validation.py", line 13, in <module>
    from flama.routing import Route
  File "C:\Users\joscha.goetzer\.virtualenvs\autogram-PRYPx28t\lib\site-packages\flama\routing.py", line 10, in <module>
    from starlette.types import ASGIApp, ASGIInstance, Receive, Scope, Send
ImportError: cannot import name 'ASGIInstance'

Am I missing something?

Improve README.md with examples on how to run it

Hey, folks! :]

It would be great if we had a basic example on how to run this, so it's easier to jump into and contribute as well.
If I have the time, I can do it, but if someone had that already set up, it would be nice!

Thanks!

Availability to use multiple schema libs

In order to allow Flama to use multiple schema libs it's necessary to:

  • Remove marshmallow from flama's core.
  • Create an adapter layer to allow plug any lib that implements its interface.
  • Rework on tests to use all available libs.

Enhanced model serialisation

At the moment, the model serialisation builds a binary which contains:

  • lib: ModelFormat
  • model: typing.Any

Whilst this is OK, and it's allowed us keep making progress, we might highly benefit from having a much richer structure. Our previous discussion seems to point at something like:

{
	"data": {
		"binary": b"...",
	},
	"meta": {
		"id": ...,
		"timestamp": ...,
		"framework": {
			"lib": "...",
			"version": "...",
		},
		"model": {
				"class": "...",
				"info": {**info},
				"params": {**hyperparams},
				"metrics": {**metrics},
		},
		"extra": {
			**free_info
		},
	},
}

This will change the current implementation in model.py. Essentially, it will have to extend the dataclass:

@dataclasses.dataclass(frozen=True)
class Model:
    """ML Model wrapper to provide mechanisms for serialization and deserialization using Flama format."""

    lib: ModelFormat
    model: typing.Any

to accomodate the previous JSON structure.

Helpful links:

Provide additional extras

Currently there's the extra full which installs all dependencies. It would nice if I could choose just apispec and pyyaml with the correct versions. Would it be possible to provide all optional dependencies as extras?

Class-based endpoints produce an error on schema generation

When using class-based endpoints, if no methods are explicitly passed to add_route, this will raise an error when generating the schema. (using starlette==0.11.4, starlette-api==0.6.2)

from starlette.requests import Request
from starlette.responses import Response
from starlette_api.applications import Starlette
from starlette_api.endpoints import HTTPEndpoint

app = Starlette(
    title="Test",
    version="1.0",
    description="Test",
    schema="/schema/",
    docs="/docs/",
    redoc="/redoc/",
)

class FooEndpoint(HTTPEndpoint):
    async def get(self, request: Request):
        return Response()

    async def post(self, request: Request):
        return Response()

app.add_route("/", FooEndpoint, name="foo")

Traceback:

INFO: ('127.0.0.1', 53618) - "GET /schema/ HTTP/1.1" 500
ERROR: Exception in ASGI application
Traceback (most recent call last):
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 372, in run_asgi
    result = await asgi(self.receive, self.send)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/uvicorn/middleware/debug.py", line 83, in __call__
    raise exc from None
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/uvicorn/middleware/debug.py", line 80, in __call__
    await asgi(receive, self.send)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette/middleware/errors.py", line 125, in asgi
    raise exc from None
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette/middleware/errors.py", line 103, in asgi
    await asgi(receive, _send)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette/exceptions.py", line 74, in app
    raise exc from None
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette/exceptions.py", line 63, in app
    await instance(receive, sender)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette_api/routing.py", line 174, in awaitable
    response = await run_in_threadpool(injected_func)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette/concurrency.py", line 24, in run_in_threadpool
    return await loop.run_in_executor(None, func, *args)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette_api/schemas.py", line 223, in schema
    return OpenAPIResponse(self.schema)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette_api/schemas.py", line 219, in schema
    return self.schema_generator.get_schema(self.routes)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette_api/schemas.py", line 175, in get_schema
    self.spec.add_path(path=path, operations={e.method: self.get_endpoint_schema(e) for e in endpoints})
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette_api/schemas.py", line 175, in <dictcomp>
    self.spec.add_path(path=path, operations={e.method: self.get_endpoint_schema(e) for e in endpoints})
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette_api/schemas.py", line 156, in get_endpoint_schema
    self.get_endpoint_parameters_schema(endpoint, schema)
  File "/Users/test/.virtualenvs/play/lib/python3.7/site-packages/starlette_api/schemas.py", line 114, in get_endpoint_parameters_schema
    for field in itertools.chain(endpoint.query_fields.values(), endpoint.path_fields.values())
AttributeError: 'NoneType' object has no attribute 'values'

[Question] Documenting additional responses

Do you have a way or have a way planned on how to document multiple responses from an endpoint?

I would like to be able to document, for example, error responses from an endpoint such as BadRequest or validation errors and have that openapi information show up in the schema served to the swagger/redoc ui. It would also be nice to allow the @output_validation decorator could "validate" these as well if possible.

For reference, another somewhat similar framework has the same open question: tiangolo/fastapi#16

Thanks for any info!

Channels?

@perdy do you use a communication channel? IRC or whatever, I have some questions for you

Readme example is not working

Copy-pasting the example from readme produces this:

INFO: ('127.0.0.1', 33118) - "GET / HTTP/1.1" 500
ERROR: Exception in ASGI application
Traceback (most recent call last):
  File "<venv>/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 372, in run_asgi
    result = await asgi(self.receive, self.send)
  File "<venv>/lib/python3.7/site-packages/starlette/middleware/errors.py", line 125, in asgi
    raise exc from None
  File "<venv>/lib/python3.7/site-packages/starlette/middleware/errors.py", line 103, in asgi
    await asgi(receive, _send)
  File "<venv>/lib/python3.7/site-packages/starlette/exceptions.py", line 74, in app
    raise exc from None
  File "<venv>/lib/python3.7/site-packages/starlette/exceptions.py", line 63, in app
    await instance(receive, sender)
  File "<venv>/lib/python3.7/site-packages/starlette_api/routing.py", line 168, in awaitable
    injected_func = await app.injector.inject(endpoint, state)
  File "<venv>/lib/python3.7/site-packages/starlette_api/injection.py", line 173, in inject
    state[output_name] = resolver(**kw)
  File "<venv>/lib/python3.7/site-packages/starlette_api/components/validation.py", line 79, in resolve
    query_params = validator().load(dict(query_params), unknown=marshmallow.EXCLUDE)
AttributeError: module 'marshmallow' has no attribute 'EXCLUDE'

UPD: I used starlette-api[full] for install

Integrate mypy

Integrate mypy with Flama, fix all typing errors and modify the github actions flow to include it.

Branding: remove "with this flamethrower" tagline

The branding/logo of this project is great and "Flama" is a nicer name than its FastAPI competitor. However, the "with this flamethrower" tagline is overly narrow. Why is an API like a flamethrower? Just ends up sounding weird.

I suggest you just make the tagline "Fire up your API". Simple.

Allow Schema definitions via decorator

Using type annotations to define the schema messes with IDEs in cases where the schema's post_load returns a different object.

Example:

import marshmallow as ma
import marshmallow.fields as mf

@dataclass
class Foo:
    foo: str
    bar: int


class FooSchema(ma.Schema):
    foo = mf.String()
    bar = mf.Integer(missing=2)

    @ma.post_load
    def make_object(self, data, **kwargs):
        return Foo(**data)
        
@app.route('/', methods=['GET'])
def endpoint(data: FooSchema) -> FooSchema:
    logger.info(f'{type(data)} - {data}')
    return data

In this case, data would be and instance of Foo, but the IDE would give type hints for FooSchema.
The same would be true for the response. I'd like to be able to return the instance of Foo, and it be automatically serialized using FooSchema.
Additionally, marshmallow-dataclass allows us to create a dataclass that has an additional Schema field that we can use to automatically get the schema.

I suggest something like the following:

import logging
from dataclasses import dataclass
from typing import Dict

import marshmallow as ma
import marshmallow.fields as mf
from flama import Flama
from marshmallow_dataclass import dataclass as ma_dataclass

logger = logging.getLogger(__name__)

# Application
app = Flama(
    components=[],      # Without custom components
    title="Foo",        # API title
    version="0.1",      # API version
    description="Bar",  # API description
    schema="/schema/",  # Path to expose OpenAPI schema
    docs="/docs/",      # Path to expose Swagger UI docs
    redoc="/redoc/",    # Path to expose ReDoc docs
)


@ma_dataclass
class Foo2:
    foo: str
    bar: int


@dataclass
class Foo:
    foo: str
    bar: int


class FooSchema(ma.Schema):
    foo = mf.String()
    bar = mf.Integer(missing=2)

    @ma.post_load
    def make_object(self, data, **kwargs):
        return Foo(**data)


# Add decorator to add the schemas to the function, we can then use this during doc generation and data serialization.
def schemas(
    response_schema: ma.Schema = None,
    **request_schemas: Dict[str, ma.Schema]
):
    def decorator(fn):
        fn._request_schemas = request_schemas
        fn._response_schema = response_schema
        return fn

    return decorator


@app.route('/1', methods=['GET'])
def endpoint(data: FooSchema) -> FooSchema:
    logger.info(f'{type(data)} - {data}')
    return data


@app.route('/2', methods=['GET'])
@schemas(data=FooSchema, response_schema=FooSchema)
def endpoint2(data: Foo) -> Foo:
    logger.info(f'{type(data)} - {data}')
    return data


@app.route('/3', methods=['GET'])
def endpoint3(data: Foo2) -> Foo2:
    logger.info(f'{type(data)} - {data}')
    return data

JSON API support?

Hi, I'm investigating the feasibility of implementing the JSON API specification with Flama.

It's probably easy to add a JSON API codec to Flama using marshmallow-jsonapi.

The other parts, like which status codes to return and what query parameters should look like, are possibly harder to achieve without messing with Flama internals.

Would you agree with this quick assessment or do you think it would be easier than I'm currently thinking?

Remove dependency with databases

Currently encode/databases is a dependency for using Resources. The same behavior could be achieved using SQLAlchemy core instead of databases, reducing the number of dependencies. It could allow the user to choice it own database lib.

Encode uuid objects as part of json encoding process

The response serialization process (converting it to json) is not allowing to encode uuid objects. It could be desirable to add a transformation of those uuid objects to their string representation as part of the json encoding process.

Flama start config handles debug mode

It's not possible to run a Flama application in debug mode using flama start command. It could be a good addition to allow flama config files to specify debug mode for applications.

Allow declarative routing

Modify how Routes and Routers are initialized and how are handling the main application to allow declarative routing for all Routes types.

An example of the goal syntax:

class PuppyResource(BaseResource, metaclass=CRUDResource):
    name = "puppy"
    model = puppy_model
    schema = puppy_schema

routes = [
    Route("/", root_mock),
    ResourceRoute("/", PuppyResource),
    Mount("/foo", routes=[
        Route("/", foo_mock, methods=["GET"]),
        Route("/view", foo_view_mock, methods=["GET"])
    ])
]

app = Flama(routes=routes)

Support / test newer versions of dependencies

Because the following version constraints are defined:

apispec = {version = "^1.0",optional = true}
pyyaml = {version = "^3.13",optional = true}

Only apispec 1.x and pyyaml 3.13.x will be used/tested when flama[schema] is installed.

apispec is on version 3 and pyyaml is at 5 now. There are numerous useful changes in those projects that can be integrated into flama.

AttributeError when bootstrapping Flama without apispec installed

Presumably relates to #12 but it looks like SchemaRegistry ultimately has a hard dependency on apispec?

https://github.com/perdy/flama/blob/789d140d5ffebcd779c7cbe017ecbf84bdcdaf42/flama/schemas.py#L41

> pip install flama
> pip install uvicorn
> pip freeze
Click==7.0
flama==0.8.0
h11==0.8.1
httptools==0.0.13
marshmallow==3.0.0rc6
starlette==0.11.4
uvicorn==0.7.1
uvloop==0.12.2
websockets==7.0

example file:

from flama.applications import Flama
app = Flama(
    components=[],      # Without custom components
    title="Foo",        # API title
    version="0.1",      # API version
    description="Bar",  # API description
    schema="/schema/",  # Path to expose OpenAPI schema
    docs="/docs/",      # Path to expose Swagger UI docs
    redoc="/redoc/",    # Path to expose ReDoc docs
)

Run with:

[...]
  File "/path/to/python3.6//site-packages/flama/applications.py", line 15, in <module>
    from flama.schemas import SchemaMixin
  File "/path/to/python3.6//site-packages/flama/schemas.py", line 40, in <module>
    class SchemaRegistry(dict):
  File "/path/to/python3.6//site-packages/flama/schemas.py", line 41, in SchemaRegistry
    def __init__(self, spec: apispec.APISpec, *args, **kwargs):
AttributeError: 'NoneType' object has no attribute 'APISpec'

TypeError with route_scope in endpoints.py

Hi,

Here is a very small example when I try to construct an API with starlette-api but I get an error, could you tell me where my error is?

Thank you

import pytest
from marshmallow import Schema
from marshmallow import fields
from starlette.testclient import TestClient
from starlette_api.applications import Starlette
from starlette_api.endpoints import HTTPEndpoint
from starlette_api.routing import Router

class RunnerSchema(Schema):
    id = fields.Integer()
    name = fields.String()
    token = fields.String()

class RunnerEndpoint(HTTPEndpoint):
    async def get(self) -> RunnerSchema():
        return {"id": 1, "name": "name", "token": "token"}

def create_app():
    app = Starlette(
        components=[],
        title="Foo",
        version="0.1",
        description="Foo",
        schema=False,
        docs=False,
        debug=False,
    )

    api = Router()
    api.add_route("/runners", RunnerEndpoint, methods=["GET"])
    app.mount("/api/v4", api)

    return app

@pytest.fixture(scope="function")
def app():
    return create_app()


@pytest.fixture(scope="function")
def client(app):
    return TestClient(app)

def test_get_runners(client):
    response = client.get("/api/v4/runners")

    assert response.status_code == 200
    assert response.json() == {"id": 1, "name": "name", "token": "token"}

Result of pytest

self = <test_app.RunnerEndpoint object at 0x7f5dcb6c5588>, receive = <function _ASGIAdapter.send.<locals>.receive at 0x7f5dcb16d8c8>
send = <function ExceptionMiddleware.__call__.<locals>.app.<locals>.sender at 0x7f5dcb6c7620>

    async def __call__(self, receive: Receive, send: Send):
        request = Request(self.scope, receive=receive)
        app = self.scope["app"]
        kwargs = self.scope.get("kwargs", {})
    
        route, route_scope = app.router.get_route_from_scope(self.scope)
    
        state = {
            "scope": self.scope,
            "receive": receive,
            "send": send,
            "exc": None,
            "app": app,
>           "path_params": route_scope["path_params"],
            "route": route,
            "request": request,
        }
E       TypeError: 'NoneType' object is not subscriptable

app        = <starlette_api.applications.Starlette object at 0x7f5dcb6ab860>
kwargs     = {}
receive    = <function _ASGIAdapter.send.<locals>.receive at 0x7f5dcb16d8c8>
request    = <starlette.requests.Request object at 0x7f5dcb702a90>
route      = <bound method Router.not_found of <starlette_api.routing.Router object at 0x7f5dcb6ab978>>
route_scope = None
self       = <test_app.RunnerEndpoint object at 0x7f5dcb6c5588>
send       = <function ExceptionMiddleware.__call__.<locals>.app.<locals>.sender at 0x7f5dcb6c7620>

Version of starlette

starlette==0.11.3
starlette-api==0.5.0

Resource(many=True) and issubclass

I have added this test in tests/test_endpoints
You can check here:

master...matrixise:test_resources_many

    def test_nested_api(self, app, client):
        class Resource(marshmallow.Schema):
            name = marshmallow.fields.String()

        @app.route('/resources', methods=['GET'])
        class ResourcesHTTPEndpoint(HTTPEndpoint):
            async def get(self) -> Resource(many=True):
                return [{'name': 'Name'}]
        response = client.get('/resources')
        assert response.status_code == 200

but I get this exception because you are waiting for a class and not an instance, but in the case of Resource(many=True) it's an instance.

Do you know why?

tests/test_endpoints.py:92: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/requests/sessions.py:546: in get
    return self.request('GET', url, **kwargs)
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/starlette/testclient.py:382: in request
    json=json,
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/requests/sessions.py:533: in request
    resp = self.send(prep, **send_kwargs)
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/requests/sessions.py:646: in send
    r = adapter.send(request, **kwargs)
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/starlette/testclient.py:211: in send
    raise exc from None
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/starlette/testclient.py:208: in send
    loop.run_until_complete(connection(receive, send))
/usr/lib64/python3.7/asyncio/base_events.py:584: in run_until_complete
    return future.result()
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/starlette/middleware/errors.py:125: in asgi
    raise exc from None
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/starlette/middleware/errors.py:103: in asgi
    await asgi(receive, _send)
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/starlette/exceptions.py:74: in app
    raise exc from None
../../../../.virtualenvs/tempenv-713715370977/lib/python3.7/site-packages/starlette/exceptions.py:63: in app
    await instance(receive, sender)
starlette_api/endpoints.py:37: in __call__
    response = await self.dispatch(request, state, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <tests.test_endpoints.TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint object at 0x7f0193c775c0>, request = <starlette.requests.Request object at 0x7f0193c776a0>
state = {'app': <starlette_api.applications.Starlette object at 0x7f0193c52cf8>, 'exc': None, 'path_params': {}, 'receive': <function _ASGIAdapter.send.<locals>.receive at 0x7f0193ca7bf8>, ...}
kwargs = {}, handler_name = 'get'
handler = <bound method TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint.get of <tests.test_endpoints.TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint object at 0x7f0193c775c0>>
app = <starlette_api.applications.Starlette object at 0x7f0193c52cf8>
injected_func = functools.partial(<bound method TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint.get of <tests.test_endpoints.TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint object at 0x7f0193c775c0>>)
response = [{'name': 'Name'}], return_annotation = <Resource(many=True)>

    async def dispatch(self, request: Request, state: typing.Dict, **kwargs) -> Response:
        handler_name = "get" if request.method == "HEAD" else request.method.lower()
        handler = getattr(self, handler_name, self.method_not_allowed)
    
        app = state["app"]
        injected_func = await app.injector.inject(handler, state)
    
        if asyncio.iscoroutinefunction(handler):
            response = await injected_func()
        else:
            response = injected_func()
    
        return_annotation = inspect.signature(handler).return_annotation
>       if issubclass(return_annotation, marshmallow.Schema):
E       TypeError: issubclass() arg 1 must be a class

app        = <starlette_api.applications.Starlette object at 0x7f0193c52cf8>
handler    = <bound method TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint.get of <tests.test_endpoints.TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint object at 0x7f0193c775c0>>
handler_name = 'get'
injected_func = functools.partial(<bound method TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint.get of <tests.test_endpoints.TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint object at 0x7f0193c775c0>>)
kwargs     = {}
request    = <starlette.requests.Request object at 0x7f0193c776a0>
response   = [{'name': 'Name'}]
return_annotation = <Resource(many=True)>
self       = <tests.test_endpoints.TestCaseHTTPEndpoint.test_nested_api.<locals>.ResourcesHTTPEndpoint object at 0x7f0193c775c0>
state      = {'app': <starlette_api.applications.Starlette object at 0x7f0193c52cf8>, 'exc': None, 'path_params': {}, 'receive': <function _ASGIAdapter.send.<locals>.receive at 0x7f0193ca7bf8>, ...}

starlette_api/endpoints.py:54: TypeError

Thank you,

marshmallow 3.0.0rc4 is not stable ?

Sorry, but I can't fix one issue because there is an issue with the dependencies and I don't know why.

  1. when I use poetry install for the installation of the dependencies, it tries to install marshmallow 3.0.0rc4, but in the pyproject.toml file, it's 2.19.0.
    But this is not the case in the poetry.lock file.

and because I don't know poetry I have to learn the project and try to fix the issue with the dependency.
Which version of marshmallow do you want to use? 3.0.0rc4 or 2.19.0 ?

Thanks you

HTTPException types are too specific

Current HTTPException init method is too specific for it s detail parameter types:

def __init__(
        self,
        status_code: int,
        detail: t.Optional[t.Union[str, t.Dict[str, t.List[str]]]] = None,
        headers: t.Optional[dict] = None,
    ) -> None:
   ...

It could be the more generic t.Optional[t.Union[str, t.Dict[str, t.Any]]].

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.