question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't use custom field type

See original GitHub issue

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn’t find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google “How to X in FastAPI” and didn’t find any information.
  • I already read and followed all the tutorial in the docs and didn’t find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

from pydantic import BaseModel
from serial.tools.list_ports_linux import SysFS
from fastapi import FastAPI
from typing import List


class SysFSType(SysFS):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if not isinstance(v, SysFS):
            raise TypeError("SysFS required")
        return v

    def __repr__(self):
        return super().device


class Device(BaseModel):
    name: str
    port: SysFSType


app = FastAPI()

connected_devices = [Device(name="D1", port=SysFS("/dev/ttyACM1")), Device(name="D2", port=SysFS("/dev/ttyACM2"))]


@app.get("/devices/", response_model=List[Device])
async def get_devices():
    return connected_devices

Description

I’m trying to use the SysFS class (from pyserial) as a field type on a BaseModel class (through the SysFSType custom class, as explained here).

It all runs fine, even the GET route:

[
  {
    name: "D1",
    port: {
    device: "/dev/ttyACM1",
    name: "ttyACM1",
    description: "n/a",
    hwid: "n/a",
    vid: null,
    pid: null,
    serial_number: null,
    location: null,
    manufacturer: null,
    product: null,
    interface: null,
    usb_device_path: null,
    device_path: null,
    subsystem: null,
    usb_interface_path: null
  }
  },
  {
    name: "D2",
    port: {
    device: "/dev/ttyACM2",
    name: "ttyACM2",
    description: "n/a",
    hwid: "n/a",
    vid: null,
    pid: null,
    serial_number: null,
    location: null,
    manufacturer: null,
    product: null,
    interface: null,
    usb_device_path: null,
    device_path: null,
    subsystem: null,
    usb_interface_path: null
    }
  }
]

but as soon as I enter the swagger documentation, I get the following error:

rafael:~/rasp-home/dev/companion-docker$ uvicorn api:app --reload

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [10227] using statreload
INFO:     Started server process [10229]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     127.0.0.1:48246 - "GET /devices/ HTTP/1.1" 200 OK
INFO:     127.0.0.1:48252 - "GET /docs HTTP/1.1" 200 OK
INFO:     127.0.0.1:48252 - "GET /openapi.json HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/uvicorn-0.13.4-py3.8.egg/uvicorn/protocols/http/h11_impl.py", line 396, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/usr/local/lib/python3.8/dist-packages/uvicorn-0.13.4-py3.8.egg/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/usr/local/lib/python3.8/dist-packages/fastapi-0.63.0-py3.8.egg/fastapi/applications.py", line 199, in __call__
    await super().__call__(scope, receive, send)
  File "/usr/local/lib/python3.8/dist-packages/starlette-0.13.6-py3.8.egg/starlette/applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.8/dist-packages/starlette-0.13.6-py3.8.egg/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "/usr/local/lib/python3.8/dist-packages/starlette-0.13.6-py3.8.egg/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/usr/local/lib/python3.8/dist-packages/starlette-0.13.6-py3.8.egg/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "/usr/local/lib/python3.8/dist-packages/starlette-0.13.6-py3.8.egg/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/usr/local/lib/python3.8/dist-packages/starlette-0.13.6-py3.8.egg/starlette/routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.8/dist-packages/starlette-0.13.6-py3.8.egg/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.8/dist-packages/starlette-0.13.6-py3.8.egg/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/usr/local/lib/python3.8/dist-packages/fastapi-0.63.0-py3.8.egg/fastapi/applications.py", line 152, in openapi
    return JSONResponse(self.openapi())
  File "/usr/local/lib/python3.8/dist-packages/fastapi-0.63.0-py3.8.egg/fastapi/applications.py", line 130, in openapi
    self.openapi_schema = get_openapi(
  File "/usr/local/lib/python3.8/dist-packages/fastapi-0.63.0-py3.8.egg/fastapi/openapi/utils.py", line 354, in get_openapi
    definitions = get_model_definitions(
  File "/usr/local/lib/python3.8/dist-packages/fastapi-0.63.0-py3.8.egg/fastapi/utils.py", line 24, in get_model_definitions
    m_schema, m_definitions, m_nested_models = model_process_schema(
  File "/usr/local/lib/python3.8/dist-packages/pydantic-1.8.2-py3.8.egg/pydantic/schema.py", line 548, in model_process_schema
    m_schema, m_definitions, nested_models = model_type_schema(
  File "/usr/local/lib/python3.8/dist-packages/pydantic-1.8.2-py3.8.egg/pydantic/schema.py", line 589, in model_type_schema
    f_schema, f_definitions, f_nested_models = field_schema(
  File "/usr/local/lib/python3.8/dist-packages/pydantic-1.8.2-py3.8.egg/pydantic/schema.py", line 241, in field_schema
    f_schema, f_definitions, f_nested_models = field_type_schema(
  File "/usr/local/lib/python3.8/dist-packages/pydantic-1.8.2-py3.8.egg/pydantic/schema.py", line 495, in field_type_schema
    f_schema, f_definitions, f_nested_models = field_singleton_schema(
  File "/usr/local/lib/python3.8/dist-packages/pydantic-1.8.2-py3.8.egg/pydantic/schema.py", line 863, in field_singleton_schema
    raise ValueError(f'Value not declarable with JSON Schema, field: {field}')
ValueError: Value not declarable with JSON Schema, field: name='port' type=SysFSType required=True

Am I using the custom field correctly? I first assumed this was related to pydantic, but it’s part of the code seems to run fine. It somehow seems to be the connection between the types and the JSON schema generated for it.

Operating System

Linux

Operating System Details

No response

FastAPI Version

0.63.0

Python Version

3.8.10

Additional Context

No response

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:2
  • Comments:9

github_iconTop GitHub Comments

1reaction
marcelosiqueiracommented, Nov 18, 2022

Facing the exact same problem:

class OID(ObjectId):
    """Pydantic representation of ObjectId"""

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        try:
            return ObjectId(str(v))
        except InvalidId as error:
            raise ValueError("Not a valid ObjectId") from error
class Entity(BaseModel):
    id: Optional[OID]
ValueError: Value not declarable with JSON Schema, field: name='id' type=Optional[OID] required=False default=None

Add method

    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")
class OID(ObjectId):
    """Pydantic representation of ObjectId"""

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        try:
            return ObjectId(str(v))
        except InvalidId as error:
            raise ValueError("Not a valid ObjectId") from error
            
    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")
0reactions
Pacheco95commented, Nov 21, 2022

Facing the exact same problem:

class OID(ObjectId):
    """Pydantic representation of ObjectId"""

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        try:
            return ObjectId(str(v))
        except InvalidId as error:
            raise ValueError("Not a valid ObjectId") from error
class Entity(BaseModel):
    id: Optional[OID]
ValueError: Value not declarable with JSON Schema, field: name='id' type=Optional[OID] required=False default=None

Add method

    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")
class OID(ObjectId):
    """Pydantic representation of ObjectId"""

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        try:
            return ObjectId(str(v))
        except InvalidId as error:
            raise ValueError("Not a valid ObjectId") from error
            
    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema.update(type="string")

You don’t need that. Just inherit from str

Read more comments on GitHub >

github_iconTop Results From Across the Web

Unable to change Field type due to Lead Custom Field Mapping
Unable to change Field type due to Lead Custom Field Mapping · Click on Setup · Click on Customize · Click on Leads...
Read more >
custom issue edit/change field type - Atlassian Community
Solved: How can I change field type for the custom field? We have Target environment type that is a single choice and we...
Read more >
Cannot edit custom field - Salesforce Stack Exchange
1 Answer 1 · Check the FLS for Word Count Limit field for the profile from which you are trying to access the...
Read more >
Create a custom field in Project - Microsoft Support
Important: A custom field's type cannot be changed after it's created. If a custom field is the wrong type, delete the field, then...
Read more >
Why is no custom field visible in the Field settings?
1. The field-level security of the custom field isn't set up. If users don't have access to a custom field, it won't appear...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found