File: visual_studio_code.md

package info (click to toggle)
pydantic 2.12.5-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,640 kB
  • sloc: python: 75,984; javascript: 181; makefile: 115; sh: 38
file content (289 lines) | stat: -rw-r--r-- 10,821 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
Pydantic works well with any editor or IDE out of the box because it's made on top of standard Python type annotations.

When using [Visual Studio Code (VS Code)](https://code.visualstudio.com/), there are some **additional editor features** supported, comparable to the ones provided by the [PyCharm plugin](../integrations/pycharm.md).

This means that you will have **autocompletion** (or "IntelliSense") and **error checks** for types and required arguments even while creating new Pydantic model instances.

![pydantic autocompletion in VS Code](../img/vs_code_01.png)

## Configure VS Code

To take advantage of these features, you need to make sure you configure VS Code correctly, using the recommended settings.

In case you have a different configuration, here's a short overview of the steps.

### Install Pylance

You should use the [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) extension for VS Code. It is the recommended, next-generation, official VS Code plug-in for Python.

Pylance is installed as part of the [Python Extension for VS Code](https://marketplace.visualstudio.com/items?itemName=ms-python.python) by default, so it should probably just work. Otherwise, you can double check it's installed and enabled in your editor.

### Configure your environment

Then you need to make sure your editor knows the [Python environment](https://code.visualstudio.com/docs/python/python-tutorial#_install-and-use-packages) (probably a virtual environment) for your Python project.

This would be the environment in where you installed Pydantic.

### Configure Pylance

With the default configurations, you will get support for autocompletion, but Pylance might not check for type errors.

You can enable type error checks from Pylance with these steps:

* Open the "User Settings"
* Search for `Type Checking Mode`
* You will find an option under `Python › Analysis: Type Checking Mode`
* Set it to `basic` or `strict` (by default it's `off`)

![Type Checking Mode set to strict in VS Code](../img/vs_code_02.png)

Now you will not only get autocompletion when creating new Pydantic model instances but also error checks for **required arguments**.

![Required arguments error checks in VS Code](../img/vs_code_03.png)

And you will also get error checks for **invalid data types**.

![Invalid data types error checks in VS Code](../img/vs_code_04.png)

!!! note "Technical Details"
    Pylance is the VS Code extension, it's closed source, but free to use. Underneath, Pylance uses an open source tool (also from Microsoft) called [Pyright](https://github.com/microsoft/pyright) that does all the heavy lifting.

    You can read more about it in the [Pylance Frequently Asked Questions](https://github.com/microsoft/pylance-release/blob/main/FAQ.md#what-is-the-relationship-between-pylance-pyright-and-the-python-extension).

### Configure mypy

You might also want to configure mypy in VS Code to get mypy error checks inline in your editor (alternatively/additionally to Pylance).

This would include the errors detected by the [Pydantic mypy plugin](../integrations/mypy.md), if you configured it.

To enable mypy in VS Code, do the following:

* Open the "User Settings"
* Search for `Mypy Enabled`
* You will find an option under `Python › Linting: Mypy Enabled`
* Check the box (by default it's unchecked)

![mypy enabled in VS Code](../img/vs_code_05.png)

## Tips and tricks

Here are some additional tips and tricks to improve your developer experience when using VS Code with Pydantic.

### Strict errors

The way this additional editor support works is that Pylance will treat your Pydantic models as if they were Python's pure `dataclasses`.

And it will show **strict type error checks** about the data types passed in arguments when creating a new Pydantic model instance.

In this example you can see that it shows that a `str` of `'23'` is not a valid `int` for the argument `age`.

![VS Code strict type errors](../img/vs_code_06.png)

It would expect `age=23` instead of `age='23'`.

Nevertheless, the design, and one of the main features of Pydantic, is that it is very **lenient with data types**.

It will actually accept the `str` with value `'23'` and will convert it to an `int` with value `23`.

These strict error checks are **very useful** most of the time and can help you **detect many bugs early**. But there are cases, like with `age='23'`, where they could be inconvenient by reporting a "false positive" error.

---

This example above with `age='23'` is intentionally simple, to show the error and the differences in types.

But more common cases where these strict errors would be inconvenient would be when using more sophisticated data types, like `int` values for `datetime` fields, or `dict` values for Pydantic sub-models.

For example, this is valid for Pydantic:

```python {hl_lines="12 17"}
from pydantic import BaseModel


class Knight(BaseModel):
    title: str
    age: int
    color: str = 'blue'


class Quest(BaseModel):
    title: str
    knight: Knight


quest = Quest(
    title='To seek the Holy Grail', knight={'title': 'Sir Lancelot', 'age': 23}
)
```

The type of the field `knight` is declared with the class `Knight` (a Pydantic model) and the code is passing a literal `dict` instead. This is still valid for Pydantic, and the `dict` would be automatically converted to a `Knight` instance.

Nevertheless, it would be detected as a type error:

![VS Code strict type errors with model](../img/vs_code_07.png)

In those cases, there are several ways to disable or ignore strict errors in very specific places, while still preserving them in the rest of the code.

Below are several techniques to achieve it.

#### Disable type checks in a line

You can disable the errors for a specific line using a comment of:

```python
# type: ignore
```

or (to be specific to pylance/pyright):

```python
# pyright: ignore
```

([pyright](https://github.com/microsoft/pyright) is the language server used by Pylance.).

coming back to the example with `age='23'`, it would be:

```python {hl_lines="10"}
from pydantic import BaseModel


class Knight(BaseModel):
    title: str
    age: int
    color: str = 'blue'


lancelot = Knight(title='Sir Lancelot', age='23')  # pyright: ignore
```

that way Pylance and mypy will ignore errors in that line.

**Pros**: it's a simple change in that line to remove errors there.

**Cons**: any other error in that line will also be omitted, including type checks, misspelled arguments, required arguments not provided, etc.

#### Override the type of a variable

You can also create a variable with the value you want to use and declare its type explicitly with `Any`.

```python {hl_lines="1 11-12"}
from typing import Any

from pydantic import BaseModel


class Knight(BaseModel):
    title: str
    age: int
    color: str = 'blue'


age_str: Any = '23'
lancelot = Knight(title='Sir Lancelot', age=age_str)
```

that way Pylance and mypy will interpret the variable `age_str` as if they didn't know its type, instead of knowing it has a type of `str` when an `int` was expected (and then showing the corresponding error).

**Pros**: errors will be ignored only for a specific value, and you will still see any additional errors for the other arguments.

**Cons**: it requires importing `Any` and a new variable in a new line for each argument that needs ignoring errors.

#### Override the type of a value with `cast`

The same idea from the previous example can be put on the same line with the help of `cast()`.

This way, the type declaration of the value is overridden inline, without requiring another variable.

```python {hl_lines="1 11"}
from typing import Any, cast

from pydantic import BaseModel


class Knight(BaseModel):
    title: str
    age: int
    color: str = 'blue'


lancelot = Knight(title='Sir Lancelot', age=cast(Any, '23'))
```

`cast(Any, '23')` doesn't affect the value, it's still just `'23'`, but now Pylance and mypy will assume it is of type `Any`, which means, they will act as if they didn't know the type of the value.

So, this is the equivalent of the previous example, without the additional variable.

**Pros**: errors will be ignored only for a specific value, and you will still see any additional errors for the other arguments. There's no need for additional variables.

**Cons**: it requires importing `Any` and `cast`, and if you are not used to using `cast()`, it could seem strange at first.

### Config in class arguments

Pydantic has a rich set of [Model Configurations][pydantic.config.ConfigDict] available.

These configurations can be set in an internal `class Config` on each model:

```python {hl_lines="9-10"}
from pydantic import BaseModel


class Knight(BaseModel):
    model_config = dict(frozen=True)
    title: str
    age: int
    color: str = 'blue'
```

or passed as keyword arguments when defining the model class:

```python {hl_lines="4"}
from pydantic import BaseModel


class Knight(BaseModel, frozen=True):
    title: str
    age: int
    color: str = 'blue'
```

The specific configuration **`frozen`** (in beta) has a special meaning.

It prevents other code from changing a model instance once it's created, keeping it **"frozen"**.

When using the second version to declare `frozen=True` (with **keyword arguments** in the class definition),
Pylance can use it to help you check in your code and **detect errors** when something is trying to set values
in a model that is "frozen".

![VS Code strict type errors with model](../img/vs_code_08.png)

## Adding a default with `Field`

Pylance/pyright requires `default` to be a keyword argument to `Field` in order to infer that the field is optional.

```python
from pydantic import BaseModel, Field


class Knight(BaseModel):
    title: str = Field(default='Sir Lancelot')  # this is okay
    age: int = Field(
        23
    )  # this works fine at runtime but will case an error for pyright


lance = Knight()  # error: Argument missing for parameter "age"
```

This is a limitation of dataclass transforms and cannot be fixed in pydantic.

## Technical Details

!!! warning
    As a Pydantic user, you don't need the details below. Feel free to skip the rest of this section.

    These details are only useful for other library authors, etc.

This additional editor support works by making use of the [`@dataclass_transform` decorator](https://typing.python.org/en/latest/spec/dataclasses.html#the-dataclass-transform-decorator)
(introduced by [PEP 681](https://peps.python.org/pep-0681/)).

The standard provides a way for libraries like Pydantic and others to tell editors and tools that they (the editors) should treat these libraries (e.g. Pydantic) as if they were [dataclasses][dataclasses], providing autocompletion, type checks, etc.