encode / apistar

The Web API toolkit. 🛠
https://docs.apistar.com
BSD 3-Clause "New" or "Revised" License
5.57k stars 411 forks source link

Schema generation fails with Exception: Cannot encode item <apistar.validators.Any object> #552

Closed danigosa closed 6 years ago

danigosa commented 6 years ago

Not generating schema on validators.Any Type?

apistar: 0.5.21 using ASYncApp

This is the piece of code (that works like a charm BTW):

from apistar import types, validators

class ClientQueryType(types.Type):
    sql = validators.String()
    args = validators.Array(validators.Any(), allow_null=True, default=[])

class ModelQueryType(types.Type):
    filters = validators.Object(allow_null=True, default={})
    columns = validators.Array(validators.String(), allow_null=True, default=["*"])
➜  /app git:(dev) ✗ curl -i http://localhost:8000/schema/
[04:15:12][CRITICAL] robbie.http_.microservice.hooks.error injector.py:run:106 | Error(Unknown): Request (GET http://127.0.0.1:8000/schema/) Headers ({'host': 'localhost:8000', 'user-agent': 'curl/7.59.0', 'accept': '*/*'})
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/apistar/server/app.py", line 334, in asgi_callable
    await self.injector.run_async(funcs, state)
  File "/usr/local/lib/python3.6/site-packages/apistar/server/injector.py", line 132, in run_async
    state[output_name] = func(**func_kwargs)
  File "/usr/local/lib/python3.6/site-packages/apistar/server/app.py", line 325, in asgi_callable
    await self.injector.run_async(funcs, state)
  File "/usr/local/lib/python3.6/site-packages/apistar/server/injector.py", line 132, in run_async
    state[output_name] = func(**func_kwargs)
  File "/usr/local/lib/python3.6/site-packages/apistar/server/handlers.py", line 10, in serve_schema
    content = codec.encode(app.document)
  File "/usr/local/lib/python3.6/site-packages/apistar/codecs/openapi.py", line 506, in encode
    paths = self.get_paths(document, schema_defs=schema_defs)
  File "/usr/local/lib/python3.6/site-packages/apistar/codecs/openapi.py", line 544, in get_paths
    paths[path][method] = self.get_operation(link, operation_id, tag=tag, schema_defs=schema_defs)
  File "/usr/local/lib/python3.6/site-packages/apistar/codecs/openapi.py", line 572, in get_operation
    '#/components/schemas/'
  File "/usr/local/lib/python3.6/site-packages/apistar/codecs/jsonschema.py", line 229, in encode_to_data_structure
    item, defs, def_prefix, is_def=True
  File "/usr/local/lib/python3.6/site-packages/apistar/codecs/jsonschema.py", line 284, in encode_to_data_structure
    for key, value in item.properties.items()
  File "/usr/local/lib/python3.6/site-packages/apistar/codecs/jsonschema.py", line 284, in <listcomp>
    for key, value in item.properties.items()
  File "/usr/local/lib/python3.6/site-packages/apistar/codecs/jsonschema.py", line 293, in encode_to_data_structure
    value['items'] = self.encode_to_data_structure(item.items, defs, def_prefix)
  File "/usr/local/lib/python3.6/site-packages/apistar/codecs/jsonschema.py", line 304, in encode_to_data_structure
    raise Exception('Cannot encode item %s' % item)
Exception: Cannot encode item <apistar.validators.Any object at 0x7f64f0a7e470>
freakabcd commented 6 years ago

see PR #561

from apistar import Route, App, types, validators

class ClientQueryType(types.Type):
    sql = validators.String()
    args = validators.Array(validators.Any(), allow_null=True, default=[])

class ModelQueryType(types.Type):
    filters = validators.Object(allow_null=True, default={})
    columns = validators.Array(validators.String(), allow_null=True, default=["*"])

def client(c: ClientQueryType):
    pass

def model(m: ModelQueryType):
    pass

routes = [
    Route('/client/', method='POST', handler=client),
    Route('/model/', method='POST', handler=model)
]
app = App(routes=routes)

app.serve('', 8000, debug=True)

generates this output:

$ curl http://localhost:8000/schema/
{
    "openapi": "3.0.0",
    "info": {
        "title": "",
        "description": "",
        "version": ""
    },
    "paths": {
        "/client/": {
            "post": {
                "operationId": "client",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ClientQueryType"
                            }
                        }
                    }
                }
            }
        },
        "/model/": {
            "post": {
                "operationId": "model",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ModelQueryType"
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "ClientQueryType": {
                "type": "object",
                "properties": {
                    "sql": {
                        "type": "string"
                    },
                    "args": {
                        "default": [],
                        "nullable": true,
                        "type": "array",
                        "items": {}
                    }
                },
                "required": [
                    "sql"
                ]
            },
            "ModelQueryType": {
                "type": "object",
                "properties": {
                    "filters": {
                        "default": {},
                        "nullable": true,
                        "type": "object"
                    },
                    "columns": {
                        "default": [
                            "*"
                        ],
                        "nullable": true,
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                }
            }
        }
    }
}
danigosa commented 6 years ago

Ok then already referenced on #561

freakabcd commented 6 years ago

@danigosa that was my take on supporting Any. I'm not sure yet if @tomchristie wanted to do it in this manner or he had other implementation ideas. I would recommend to keep this issue open until there are actual code changes and your tests verify functionality.