Hello I am using Python 3.8
And I am implementing a dataclass with a fix list in order to do this I have the following code:
from dataclasses import dataclass
from typing import Annotated, List, ValueRange
from pydantic import validate_arguments
#validate_arguments
#dataclass
class WorldArea:
...
data: Annotated[List[float], ValueRange(1, 3)]
...
The idea is that data will be a list with 1, 2 or 3 elements, as you can see I am using Annotated and ValueRange, but when I execute I get the following error:
File "a.py", line 2, in
from typing import List, ValueRange ImportError: cannot import name 'Annotated' from 'typing'
File "a.py", line 2, in
from typing import List, ValueRange ImportError: cannot import name 'ValueRange' from 'typing'
Annotated has been introduced in Python 3.9 (see last line in the linked section).
ValueRange (and MaxLen) in the linked section appear to be example classes.
They are not part of the typing package.
Related
When working with modular imports with FastAPI and SQLModel, I am getting the following error if I open /docs:
TypeError: issubclass() arg 1 must be a class
Python 3.10.6
pydantic 1.10.2
fastapi 0.85.2
sqlmodel 0.0.8
macOS 12.6
Here is a reproducible example.
user.py
from typing import List, TYPE_CHECKING, Optional
from sqlmodel import SQLModel, Field
if TYPE_CHECKING:
from item import Item
class User(SQLModel):
id: int = Field(default=None, primary_key=True)
age: Optional[int]
bought_items: List["Item"] = []
item.py
from sqlmodel import SQLModel, Field
class Item(SQLModel):
id: int = Field(default=None, primary_key=True)
price: float
name: str
main.py
from fastapi import FastAPI
from user import User
app = FastAPI()
#app.get("/", response_model=User)
def main():
return {"message": "working just fine"}
I followed along the tutorial from sqlmodel https://sqlmodel.tiangolo.com/tutorial/code-structure/#make-circular-imports-work.
If I would put the models in the same file, it all works fine. As my actual models are quite complex, I need to rely on the modular imports though.
Traceback:
Traceback (most recent call last):
File "/Users/felix/opt/anaconda3/envs/fastapi_test/lib/python3.10/site-packages/fastapi/utils.py", line 45, in get_model_definitions
m_schema, m_definitions, m_nested_models = model_process_schema(
File "pydantic/schema.py", line 580, in pydantic.schema.model_process_schema
File "pydantic/schema.py", line 621, in pydantic.schema.model_type_schema
File "pydantic/schema.py", line 254, in pydantic.schema.field_schema
File "pydantic/schema.py", line 461, in pydantic.schema.field_type_schema
File "pydantic/schema.py", line 847, in pydantic.schema.field_singleton_schema
File "pydantic/schema.py", line 698, in pydantic.schema.field_singleton_sub_fields_schema
File "pydantic/schema.py", line 526, in pydantic.schema.field_type_schema
File "pydantic/schema.py", line 921, in pydantic.schema.field_singleton_schema
File "/Users/felix/opt/anaconda3/envs/fastapi_test/lib/python3.10/abc.py", line 123, in __subclasscheck__
return _abc_subclasscheck(cls, subclass)
TypeError: issubclass() arg 1 must be a class
TL;DR
You need to call User.update_forward_refs(Item=Item) before the OpenAPI setup.
Explanation
So, this is actually quite a bit trickier and I am not quite sure yet, why this is not mentioned in the docs. Maybe I am missing something. Anyway...
If you follow the traceback, you'll see that the error occurs because in line 921 of pydantic.schema in the field_singleton_schema function a check is performed to see if issubclass(field_type, BaseModel) and at that point field_type is not in fact a type instance.
A bit of debugging reveals that this occurs, when the schema for the User model is being generated and the bought_items field is being processed. At that point the annotation is processed and the type argument for List is still a forward reference to Item. Meaning it is not the actual Item class itself. And that is what is passed to issubclass and causes the error.
This is a fairly common problem, when dealing with recursive or circular relationships between Pydantic models, which is why they were so kind to provide a special method just for that. It is explained in the Postponed annotations section of the documentation. The method is update_forward_refs and as the name suggests, it is there to resolve forward references.
What is tricky in this case, is that you need to provide it with an updated namespace to resolve the Item reference. To do that you need to actually have the real Item class in scope because that is what needs to be in that namespace. Where you do it does not really matter. You could for example import User model into your item module and call it there (obviously below the definition of Item):
from sqlmodel import SQLModel, Field
from .user import User
class Item(SQLModel):
id: int = Field(default=None, primary_key=True)
price: float
name: str
User.update_forward_refs(Item=Item)
But that call needs to happen before an attempt is made to set up that schema. Thus you'll at least need to import the item module in your main module:
from fastapi import FastAPI
from .user import User
from . import item
api = FastAPI()
#api.get("/", response_model=User)
def main():
return {"message": "working just fine"}
At that point it is probably simpler to have a sub-package with just the model modules and import all of them in the __init__.py of that sub-package.
The reason I gave the example of putting the User.update_forward_refs call in below your Item definition is that these situations typically occur, when you actually have a circular relationship, i.e. if your Item class had a users field for example, which was typed as list[User]. Then you'd have to import User there anyway and might as well just update the references there.
In your specific example, you don't actually have any circular dependencies, so there is strictly speaking no need for the TYPE_CHECKING escape. You can simply do from .item import Item inside user.py and put the actual class in your annotation as bought_items: list[Item]. But I assume you simplified the actual use case and simply forgot to include the circular dependency.
Maybe I am missing something and someone else here can find a way to call update_forward_refs without the need to provide Item explicitly, but this way should definitely work.
For anyone ending up here who (just like me) got the same error but couldn't resolve it using the solution above, my script looked like this. It seems that SQLModel relies on the pydantic.BaseModel so this solution also applies here.
from pydantic import BaseModel
class Model(BaseModel):
values: list[int, ...]
class SubModel(Model):
values = list[int, int, int]
It took me a long time to realize what my mistake was, but in SubModel I used = (assignment) whereas I should have used : (type hint).
The strangest thing was that it did work in a docker container (Linux) but not locally (Windows). Also, mypy did not pick up on this.
I want to have deafult values for Base class variables while not having default values for derived class variables.
I have read about 'kw_only' at:
https://medium.com/#aniscampos/python-dataclass-inheritance-finally-686eaf60fbb5
And tried it on my code:
from dataclasses import dataclass, field
#dataclass(kw_only=True)
class Base:
c:int = field(default=8, compare=False)
def printBVars(self):
print("Base:", self.c)
#dataclass(kw_only=True)
class Derive(Base):
cc:int = field()
def printDVars(self):
super().printBVars()
print("Derive:", self.cc)
a = Derive()
a.printDVars()
But Python is givving this error:
File "<string>", line 8, in <module> TypeError: dataclass() got an unexpected keyword argument 'kw_only'
What am I doing wrong?
Im using python 3.9
I have read about some solution suggestions from google, tried some but did not help. such as running:
pip install attrs --upgrade
I'm using FastAPI to build a data API. I want the clients to post 2 lists of 24 floats that later I will save into a database.
When I try to create the Pydantic model:
from pydantic import BaseModel
class Prices(BaseModel):
buying_price: list(float)=[]
selling_price: list(float)=[]
I get the following error:
File "c:/Users/Amin y Lubna/FastAPI-InfluxDB/test.py", line 3, in <module>
class Prices(BaseModel):
File "c:/Users/Amin y Lubna/FastAPI-InfluxDB/test.py", line 4, in Prices
buying_price: list(float)=[]
TypeError: 'type' object is not iterable
Even though the error is self-explanatory, I don't understand it.
Then, looking at the documentation I found the following way:
from pydantic import BaseModel
from typing import List
class Prices(BaseModel):
buying_price: List(float)=[]
selling_price: List(float)=[]
But I got the following error.
File "c:/Users/Amin y Lubna/FastAPI-InfluxDB/test.py", line 4, in <module>
class Prices(BaseModel):
File "c:/Users/Amin y Lubna/FastAPI-InfluxDB/test.py", line 5, in Prices
buying_price: List(float)=[]
File "C:\Users\Amin y Lubna\anaconda3\lib\typing.py", line 727, in __call__
raise TypeError(f"Type {self._name} cannot be instantiated; "
TypeError: Type List cannot be instantiated; use list() instead
I've been struggling with the error a couple days and I'm not able to find a solution to the issues.
You need to use list[float], not list(float)
I'm trying to use a work-around for the problems described in this GitHub issue ("Class with function fields incorrectly thinks the first argument is self").
from dataclasses import dataclass
from typing import TypeVar, Generic, Any, Iterable, List
T = TypeVar("T")
# See https://github.com/python/mypy/issues/5485
#dataclass
class Box(Generic[T]):
inner: T
#property
def unboxed(self) -> T:
return self.inner
I run into a traceback like this, though:
However, upon importing (only(!) ) the code above from another module I run into a traceback like this:
(py) sugarline:~/src/oss/ormsnack write-compile-eval
Traceback (most recent call last):
[.....]
File "/Users/jacob/src/oss/ormsnack/ormsnack/ng_desc.py", line 8, in <module>
from kingston.kind import Box # type: ignore
File "kingston/kind.py", line 12, in <module>
AttributeError: attribute '__dict__' of 'type' objects is not writable
Googling only lands me in old bugs that seem to have gone stale, though (https://bugs.python.org/issue38099, https://github.com/man-group/arctic/issues/17), etc.
Is anyone able to figure out a work-around?
I don't know if this logic is correct,
I'm trying to import a Django view in 2 different views.
I have an import chain like this:
the
a.views import b.views
b.views import c.views
c.views import d.views
and
d.views import b.views
but when I reach the last step I get an ImportError.
If I put a comment in d.views avoiding the import of b.views, it works.
I'm new with Django, can somebody help me?
If I use in a.views and in d.views the syntax
from b.views import *
it works, but.. the code is not so readable.
If I use
from b.views import my_func
it doesn't work!
This is the error from django shell:
>>> import maps.views
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/save/sites/myblog/maps/views.py", line 19, in <module>
from places.views import *
File "/Users/save/sites/myblog/places/views.py", line 22, in <module>
from posts.views import *
File "/Users/save/sites/myblog/posts/views.py", line 31, in <module>
from maps.views import render_map_geoloc
ImportError: cannot import name render_map_geoloc
Its because of cyclic dependency or circular reference.
b depends on c
c depends on d
d depends on b #which depends on c
Not sure for what purpose you are using. But you do explicit import to that function, and right above where its been used.
Looking at the error you are getting, it might be because of some dependency expected for d is coming from b so if you from b.views import *, it gets you that dependency. But if you import specific view (my_func), its missing that dependency.
Some more details you can find on SO answer thread - Django App Dependency Cycle