admin管理员组

文章数量:1129108

How does one go about creating a TypeAdapter from a dynamic Union without running into linting errors?

from pydantic import BaseModel, TypeAdapter

class Lion(BaseModel):
    roar: str


class Tiger(BaseModel):
    roar: str


ZOO = {
    "lion": Lion,
    "tiger": Tiger,
    # ...
}

Animal = Union[*[animal for animal in ZOO.values()]]    # Error: Invalid type alias: expression is not a valid type

AnimalTypeAdapter: TypeAdapter[Animal] = TypeAdapter(Animal)    # Error: Variable "Animal" is not valid as a type

How does one go about creating a TypeAdapter from a dynamic Union without running into linting errors?

from pydantic import BaseModel, TypeAdapter

class Lion(BaseModel):
    roar: str


class Tiger(BaseModel):
    roar: str


ZOO = {
    "lion": Lion,
    "tiger": Tiger,
    # ...
}

Animal = Union[*[animal for animal in ZOO.values()]]    # Error: Invalid type alias: expression is not a valid type

AnimalTypeAdapter: TypeAdapter[Animal] = TypeAdapter(Animal)    # Error: Variable "Animal" is not valid as a type

Share Improve this question edited Jan 8 at 15:45 InSync 10.3k4 gold badges15 silver badges51 bronze badges asked Jan 8 at 14:58 fmagnofmagno 1,54815 silver badges29 bronze badges 6
  • 2 In general, you shouldn't expect expect to be able to use a static analysis tool to in conjunction with dynamically generated annotations. Sometimes a language might special case a particular thing, but think about what you are asking the static analysis tools to do (basically, to run your code, and the whole point is that they work without running code) – juanpa.arrivillaga Commented Jan 8 at 16:35
  • @juanpa.arrivillaga It’s not an unreasonable question; most (all?) modern languages with powerful static type systems contain codegen tools to generate types. The lack of this in Python is conspicuous (and pretty problematic), especially since it clashes with previously prevalent styles of writing Python, which often heavily relies on codegen. (Put more strongly: contrary to your comment, you should definitely expect to be able to use static analysis in conjunction with codegen in a modern language.) – Konrad Rudolph Commented Jan 8 at 17:30
  • 1 @KonradRudolph I don't think the question is unreasonable, but I will say, this isn't really code-gen as I would understand it, although that term is a bit overloaded, but there are code-gen tools in python designed to work with the python static analysis ecosystem, usually by creating type-stubs, but that isn't what's happening here. – juanpa.arrivillaga Commented Jan 8 at 21:18
  • @juanpa.arrivillaga The second-to-last line in OP’s code is definitely codegen. So are many decorators (e.g. @dataclass). Having to rely on external tools for codegen is definitely not what I expect from a modern language, and especially not from Python, which is perfectly capable (within limits) of integrated codegen. – Konrad Rudolph Commented Jan 8 at 21:44
  • 1 @KonradRudolph you're certainly using some interesting definition of codegen. For me codegen is a solution involving some python code producing another python code (source files, AST, bytecode, immediately compiled strings, whatever). Nothing like that happens here (though dataclasses are indeed doing exactly that and are supported by type checkers well as a special case). When you have some heavy metaprogramming in python, type checkers are usually unable to understand it, you either use a lot of Any, or create a mypy plugin (Django), or write .pyi stubs. – STerliakov Commented Jan 8 at 22:11
 |  Show 1 more comment

1 Answer 1

Reset to default 3

You can't.

You should instead define the union first, then convert that back to runtime structures:

from typing import Union, get_args

Animal = Union[Tiger, Lion]

ZOO = dict(zip(['tiger', 'lion'], get_args(Animal)))
# {'tiger': Tiger, 'lion': Lion}

本文标签: