Brettapps commited on
Commit
bf03bad
Β·
verified Β·
1 Parent(s): 9110c55

Upload folder using huggingface_hub (part 5)

Browse files
This view is limited to 50 files because it contains too many changes. Β  See raw diff
Files changed (50) hide show
  1. .gitattributes +6 -0
  2. .mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/INSTALLER +1 -0
  3. .mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/METADATA +0 -0
  4. .mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/RECORD +217 -0
  5. .mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/WHEEL +4 -0
  6. .mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/licenses/LICENSE +21 -0
  7. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_known_annotated_metadata.py +403 -0
  8. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_mock_val_ser.py +228 -0
  9. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_model_construction.py +868 -0
  10. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_namespace_utils.py +293 -0
  11. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_repr.py +124 -0
  12. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_schema_gather.py +212 -0
  13. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_schema_generation_shared.py +125 -0
  14. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_serializers.py +53 -0
  15. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_signature.py +189 -0
  16. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_typing_extra.py +785 -0
  17. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_utils.py +446 -0
  18. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_validate_call.py +141 -0
  19. .mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_validators.py +534 -0
  20. .mcp-venv/lib/python3.13/site-packages/pydantic/_migration.py +316 -0
  21. .mcp-venv/lib/python3.13/site-packages/pydantic/alias_generators.py +62 -0
  22. .mcp-venv/lib/python3.13/site-packages/pydantic/aliases.py +135 -0
  23. .mcp-venv/lib/python3.13/site-packages/pydantic/annotated_handlers.py +122 -0
  24. .mcp-venv/lib/python3.13/site-packages/pydantic/class_validators.py +5 -0
  25. .mcp-venv/lib/python3.13/site-packages/pydantic/color.py +604 -0
  26. .mcp-venv/lib/python3.13/site-packages/pydantic/config.py +1296 -0
  27. .mcp-venv/lib/python3.13/site-packages/pydantic/dataclasses.py +413 -0
  28. .mcp-venv/lib/python3.13/site-packages/pydantic/datetime_parse.py +5 -0
  29. .mcp-venv/lib/python3.13/site-packages/pydantic/decorator.py +5 -0
  30. .mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/__init__.py +0 -0
  31. .mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/class_validators.py +256 -0
  32. .mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/config.py +72 -0
  33. .mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/copy_internals.py +224 -0
  34. .mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/decorator.py +284 -0
  35. .mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/json.py +141 -0
  36. .mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/parse.py +80 -0
  37. .mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/tools.py +103 -0
  38. .mcp-venv/lib/python3.13/site-packages/pydantic/env_settings.py +5 -0
  39. .mcp-venv/lib/python3.13/site-packages/pydantic/error_wrappers.py +5 -0
  40. .mcp-venv/lib/python3.13/site-packages/pydantic/errors.py +189 -0
  41. .mcp-venv/lib/python3.13/site-packages/pydantic/experimental/__init__.py +1 -0
  42. .mcp-venv/lib/python3.13/site-packages/pydantic/experimental/arguments_schema.py +44 -0
  43. .mcp-venv/lib/python3.13/site-packages/pydantic/experimental/missing_sentinel.py +5 -0
  44. .mcp-venv/lib/python3.13/site-packages/pydantic/experimental/pipeline.py +663 -0
  45. .mcp-venv/lib/python3.13/site-packages/pydantic/fields.py +1892 -0
  46. .mcp-venv/lib/python3.13/site-packages/pydantic/functional_serializers.py +470 -0
  47. .mcp-venv/lib/python3.13/site-packages/pydantic/functional_validators.py +889 -0
  48. .mcp-venv/lib/python3.13/site-packages/pydantic/generics.py +5 -0
  49. .mcp-venv/lib/python3.13/site-packages/pydantic/json.py +5 -0
  50. .mcp-venv/lib/python3.13/site-packages/pydantic/json_schema.py +0 -0
.gitattributes CHANGED
@@ -38,3 +38,9 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
38
  .mcp-venv/bin/python3.13 filter=lfs diff=lfs merge=lfs -text
39
  .mcp-venv/lib/python3.13/site-packages/_cffi_backend.cpython-313-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
40
  .mcp-venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust.abi3.so filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
38
  .mcp-venv/bin/python3.13 filter=lfs diff=lfs merge=lfs -text
39
  .mcp-venv/lib/python3.13/site-packages/_cffi_backend.cpython-313-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
40
  .mcp-venv/lib/python3.13/site-packages/cryptography/hazmat/bindings/_rust.abi3.so filter=lfs diff=lfs merge=lfs -text
41
+ .mcp-venv/lib/python3.13/site-packages/pydantic_core/_pydantic_core.cpython-313-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
42
+ .mcp-venv/lib/python3.13/site-packages/rpds/rpds.cpython-313-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
43
+ .venv/bin/python filter=lfs diff=lfs merge=lfs -text
44
+ .venv/bin/python3 filter=lfs diff=lfs merge=lfs -text
45
+ .venv/bin/python3.13 filter=lfs diff=lfs merge=lfs -text
46
+ .venv/lib/python3.13/site-packages/PIL/_imaging.cpython-313-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
.mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
.mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/METADATA ADDED
The diff for this file is too large to render. See raw diff
 
.mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/RECORD ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ pydantic-2.13.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
2
+ pydantic-2.13.4.dist-info/METADATA,sha256=0eVsNBJJJRL7a1mp38Jat68qggRYXNe8oABRMCMTM5Q,109397
3
+ pydantic-2.13.4.dist-info/RECORD,,
4
+ pydantic-2.13.4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
5
+ pydantic-2.13.4.dist-info/licenses/LICENSE,sha256=qeGG88oWte74QxjnpwFyE1GgDLe4rjpDlLZ7SeNSnvM,1129
6
+ pydantic/__init__.py,sha256=5iEnJ4wHv1OEzdKQPzaKaZKfO4pSQAC65ODrYI6_S8Y,15812
7
+ pydantic/__pycache__/__init__.cpython-313.pyc,,
8
+ pydantic/__pycache__/_migration.cpython-313.pyc,,
9
+ pydantic/__pycache__/alias_generators.cpython-313.pyc,,
10
+ pydantic/__pycache__/aliases.cpython-313.pyc,,
11
+ pydantic/__pycache__/annotated_handlers.cpython-313.pyc,,
12
+ pydantic/__pycache__/class_validators.cpython-313.pyc,,
13
+ pydantic/__pycache__/color.cpython-313.pyc,,
14
+ pydantic/__pycache__/config.cpython-313.pyc,,
15
+ pydantic/__pycache__/dataclasses.cpython-313.pyc,,
16
+ pydantic/__pycache__/datetime_parse.cpython-313.pyc,,
17
+ pydantic/__pycache__/decorator.cpython-313.pyc,,
18
+ pydantic/__pycache__/env_settings.cpython-313.pyc,,
19
+ pydantic/__pycache__/error_wrappers.cpython-313.pyc,,
20
+ pydantic/__pycache__/errors.cpython-313.pyc,,
21
+ pydantic/__pycache__/fields.cpython-313.pyc,,
22
+ pydantic/__pycache__/functional_serializers.cpython-313.pyc,,
23
+ pydantic/__pycache__/functional_validators.cpython-313.pyc,,
24
+ pydantic/__pycache__/generics.cpython-313.pyc,,
25
+ pydantic/__pycache__/json.cpython-313.pyc,,
26
+ pydantic/__pycache__/json_schema.cpython-313.pyc,,
27
+ pydantic/__pycache__/main.cpython-313.pyc,,
28
+ pydantic/__pycache__/mypy.cpython-313.pyc,,
29
+ pydantic/__pycache__/networks.cpython-313.pyc,,
30
+ pydantic/__pycache__/parse.cpython-313.pyc,,
31
+ pydantic/__pycache__/root_model.cpython-313.pyc,,
32
+ pydantic/__pycache__/schema.cpython-313.pyc,,
33
+ pydantic/__pycache__/tools.cpython-313.pyc,,
34
+ pydantic/__pycache__/type_adapter.cpython-313.pyc,,
35
+ pydantic/__pycache__/types.cpython-313.pyc,,
36
+ pydantic/__pycache__/typing.cpython-313.pyc,,
37
+ pydantic/__pycache__/utils.cpython-313.pyc,,
38
+ pydantic/__pycache__/validate_call_decorator.cpython-313.pyc,,
39
+ pydantic/__pycache__/validators.cpython-313.pyc,,
40
+ pydantic/__pycache__/version.cpython-313.pyc,,
41
+ pydantic/__pycache__/warnings.cpython-313.pyc,,
42
+ pydantic/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ pydantic/_internal/__pycache__/__init__.cpython-313.pyc,,
44
+ pydantic/_internal/__pycache__/_config.cpython-313.pyc,,
45
+ pydantic/_internal/__pycache__/_core_metadata.cpython-313.pyc,,
46
+ pydantic/_internal/__pycache__/_core_utils.cpython-313.pyc,,
47
+ pydantic/_internal/__pycache__/_dataclasses.cpython-313.pyc,,
48
+ pydantic/_internal/__pycache__/_decorators.cpython-313.pyc,,
49
+ pydantic/_internal/__pycache__/_decorators_v1.cpython-313.pyc,,
50
+ pydantic/_internal/__pycache__/_discriminated_union.cpython-313.pyc,,
51
+ pydantic/_internal/__pycache__/_docs_extraction.cpython-313.pyc,,
52
+ pydantic/_internal/__pycache__/_fields.cpython-313.pyc,,
53
+ pydantic/_internal/__pycache__/_forward_ref.cpython-313.pyc,,
54
+ pydantic/_internal/__pycache__/_generate_schema.cpython-313.pyc,,
55
+ pydantic/_internal/__pycache__/_generics.cpython-313.pyc,,
56
+ pydantic/_internal/__pycache__/_git.cpython-313.pyc,,
57
+ pydantic/_internal/__pycache__/_import_utils.cpython-313.pyc,,
58
+ pydantic/_internal/__pycache__/_internal_dataclass.cpython-313.pyc,,
59
+ pydantic/_internal/__pycache__/_known_annotated_metadata.cpython-313.pyc,,
60
+ pydantic/_internal/__pycache__/_mock_val_ser.cpython-313.pyc,,
61
+ pydantic/_internal/__pycache__/_model_construction.cpython-313.pyc,,
62
+ pydantic/_internal/__pycache__/_namespace_utils.cpython-313.pyc,,
63
+ pydantic/_internal/__pycache__/_repr.cpython-313.pyc,,
64
+ pydantic/_internal/__pycache__/_schema_gather.cpython-313.pyc,,
65
+ pydantic/_internal/__pycache__/_schema_generation_shared.cpython-313.pyc,,
66
+ pydantic/_internal/__pycache__/_serializers.cpython-313.pyc,,
67
+ pydantic/_internal/__pycache__/_signature.cpython-313.pyc,,
68
+ pydantic/_internal/__pycache__/_typing_extra.cpython-313.pyc,,
69
+ pydantic/_internal/__pycache__/_utils.cpython-313.pyc,,
70
+ pydantic/_internal/__pycache__/_validate_call.cpython-313.pyc,,
71
+ pydantic/_internal/__pycache__/_validators.cpython-313.pyc,,
72
+ pydantic/_internal/_config.py,sha256=Rzys1Joffn4JczElcYDqsZLRgBgHn2lYWqDR55oASPA,14839
73
+ pydantic/_internal/_core_metadata.py,sha256=Y_g2t3i7uluK-wXCZvzJfRFMPUM23aBYLfae4FzBPy0,5162
74
+ pydantic/_internal/_core_utils.py,sha256=1jru4VbJ0x63R6dtVcuOI-dKQTC_d_lSnJWEBQzGNEQ,6487
75
+ pydantic/_internal/_dataclasses.py,sha256=Zgqcm1WaJLBwTQQC5mGKNowjlTgX3mfX_J5e2vd24lM,13188
76
+ pydantic/_internal/_decorators.py,sha256=RDEG_Jau5NiJcfO0xgdT7EOgsU1LgWIYlX7wN5rYtVs,33620
77
+ pydantic/_internal/_decorators_v1.py,sha256=tfdfdpQKY4R2XCOwqHbZeoQMur6VNigRrfhudXBHx38,6185
78
+ pydantic/_internal/_discriminated_union.py,sha256=JLx_MVLep7Mxl1zbpdNZjvHDcz-J3OEW6WcdV184dcM,26255
79
+ pydantic/_internal/_docs_extraction.py,sha256=fyznSAHh5AzohnXZStV0HvH-nRbavNHPyg-knx-S_EE,4127
80
+ pydantic/_internal/_fields.py,sha256=hXeb-zodGwTDvG9OK1um18P64b7cqHb0GOngP4jrgcY,31557
81
+ pydantic/_internal/_forward_ref.py,sha256=5n3Y7-3AKLn8_FS3Yc7KutLiPUhyXmAtkEZOaFnonwM,611
82
+ pydantic/_internal/_generate_schema.py,sha256=PjogUawIXmf8LuLNe9seJph7WLW4MJ7-GBsXwCsQC9Q,136348
83
+ pydantic/_internal/_generics.py,sha256=CXjcInlvci8VejaWn1f39kv0AcfJL0R523qRLFZVD-s,23393
84
+ pydantic/_internal/_git.py,sha256=IwPh3DPfa2Xq3rBuB9Nx8luR2A1i69QdeTfWWXIuCVg,809
85
+ pydantic/_internal/_import_utils.py,sha256=TRhxD5OuY6CUosioBdBcJUs0om7IIONiZdYAV7zQ8jM,402
86
+ pydantic/_internal/_internal_dataclass.py,sha256=_bedc1XbuuygRGiLZqkUkwwFpQaoR1hKLlR501nyySY,144
87
+ pydantic/_internal/_known_annotated_metadata.py,sha256=PynQIFQ61__4Gcrzn0D5ENllg7jPq_cxoLTmuFQBY88,16805
88
+ pydantic/_internal/_mock_val_ser.py,sha256=wmRRFSBvqfcLbI41PsFliB4u2AZ3mJpZeiERbD3xKTo,8885
89
+ pydantic/_internal/_model_construction.py,sha256=JoKmY4JrDBu3nG_tCIrJgtJJE1uq6v29TvTz5ElHE5g,38928
90
+ pydantic/_internal/_namespace_utils.py,sha256=hl3-TRAr82U2jTyPP3t-QqsvKLirxtkLfNfrN-fp0x8,12878
91
+ pydantic/_internal/_repr.py,sha256=jQfnJuyDxQpSRNhG29II9PX8e4Nv2qWZrEw2lqih3UE,5172
92
+ pydantic/_internal/_schema_gather.py,sha256=8nJ-uM6Y4z6xpasnGonEMubtNVX_mxeeRDFmd_qMVLA,9052
93
+ pydantic/_internal/_schema_generation_shared.py,sha256=F_rbQbrkoomgxsskdHpP0jUJ7TCfe0BADAEkq6CJ4nM,4842
94
+ pydantic/_internal/_serializers.py,sha256=YIWvSmAR5fnbGSWCOQduWt1yB4ZQY42eAruc-enrb6c,1491
95
+ pydantic/_internal/_signature.py,sha256=i_b6wtluiVWZRh1ZY8UvB2UZziP1KjqSXZgC-HxwOT0,6808
96
+ pydantic/_internal/_typing_extra.py,sha256=dDxqF46lzuqCoKLrAH_k95EDbayEeKb2lHjuTJ5OBoY,31574
97
+ pydantic/_internal/_utils.py,sha256=gN48BsR-FDrJDibCmo69ttQg67WbuFrdy_1NQL3cvLI,15959
98
+ pydantic/_internal/_validate_call.py,sha256=OD_BspHaL9FKzZ9XrndhiEuMnjF3SRIJUHtwv6yUffU,5366
99
+ pydantic/_internal/_validators.py,sha256=7GTjXXWFMLib4dxQ-HeaiHlAZiR2B2G8byCYMGrmQ48,20563
100
+ pydantic/_migration.py,sha256=VF73LRCUz3Irb5xVt13jb3NAcXVnEF6T1-J0OLfeZ5A,12160
101
+ pydantic/alias_generators.py,sha256=KM1n3u4JfLSBl1UuYg3hoYHzXJD-yvgrnq8u1ccwh_A,2124
102
+ pydantic/aliases.py,sha256=vhCHyoSWnX-EJ-wWb5qj4xyRssgGWnTQfzQp4GSZ9ug,4937
103
+ pydantic/annotated_handlers.py,sha256=WfyFSqwoEIFXBh7T73PycKloI1DiX45GWi0-JOsCR4Y,4407
104
+ pydantic/class_validators.py,sha256=i_V3j-PYdGLSLmj_IJZekTRjunO8SIVz8LMlquPyP7E,148
105
+ pydantic/color.py,sha256=AzqGfVQHF92_ZctDcue0DM4yTp2P6tekkwRINTWrLIo,21481
106
+ pydantic/config.py,sha256=o1P67FMWIQG-_RfGtKislkHwo4pXm_6jfsR41P88v78,44533
107
+ pydantic/dataclasses.py,sha256=4X9We0jj1KLwBtvYSkAFXNon46zrpBmRZANf4LfwbXg,18963
108
+ pydantic/datetime_parse.py,sha256=QC-WgMxMr_wQ_mNXUS7AVf-2hLEhvvsPY1PQyhSGOdk,150
109
+ pydantic/decorator.py,sha256=YX-jUApu5AKaVWKPoaV-n-4l7UbS69GEt9Ra3hszmKI,145
110
+ pydantic/deprecated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
+ pydantic/deprecated/__pycache__/__init__.cpython-313.pyc,,
112
+ pydantic/deprecated/__pycache__/class_validators.cpython-313.pyc,,
113
+ pydantic/deprecated/__pycache__/config.cpython-313.pyc,,
114
+ pydantic/deprecated/__pycache__/copy_internals.cpython-313.pyc,,
115
+ pydantic/deprecated/__pycache__/decorator.cpython-313.pyc,,
116
+ pydantic/deprecated/__pycache__/json.cpython-313.pyc,,
117
+ pydantic/deprecated/__pycache__/parse.cpython-313.pyc,,
118
+ pydantic/deprecated/__pycache__/tools.cpython-313.pyc,,
119
+ pydantic/deprecated/class_validators.py,sha256=n0jYQOcb5YQiw0b7YXyi7NPiYdV7ujWR4KyZumjTPok,10281
120
+ pydantic/deprecated/config.py,sha256=k_lsVk57paxLJOcBueH07cu1OgEgWdVBxm6lfaC3CCU,2663
121
+ pydantic/deprecated/copy_internals.py,sha256=Ghd-vkMd5EYCCgyCGtPKO58np9cEKBQC6qkBeIEFI2g,7618
122
+ pydantic/deprecated/decorator.py,sha256=TBm6bJ7wJsNih_8Wq5IzDcwP32m9_vfxs96desLuk00,10845
123
+ pydantic/deprecated/json.py,sha256=HlWCG35RRrxyzuTS6LTQiZBwRhmDZWmeqQH8rLW6wA8,4657
124
+ pydantic/deprecated/parse.py,sha256=Gzd6b_g8zJXcuE7QRq5adhx_EMJahXfcpXCF0RgrqqI,2511
125
+ pydantic/deprecated/tools.py,sha256=Nrm9oFRZWp8-jlfvPgJILEsywp4YzZD52XIGPDLxHcI,3330
126
+ pydantic/env_settings.py,sha256=6IHeeWEqlUPRUv3V-AXiF_W91fg2Jw_M3O0l34J_eyA,148
127
+ pydantic/error_wrappers.py,sha256=RK6mqATc9yMD-KBD9IJS9HpKCprWHd8wo84Bnm-3fR8,150
128
+ pydantic/errors.py,sha256=DrECPCWhSYrQ8Ba4O8hKzIAM2i9GBHTXWALzaFDpLf4,6013
129
+ pydantic/experimental/__init__.py,sha256=QT7rKYdDsCiTJ9GEjmsQdWHScwpKrrNkGq6vqONP6RQ,104
130
+ pydantic/experimental/__pycache__/__init__.cpython-313.pyc,,
131
+ pydantic/experimental/__pycache__/arguments_schema.cpython-313.pyc,,
132
+ pydantic/experimental/__pycache__/missing_sentinel.cpython-313.pyc,,
133
+ pydantic/experimental/__pycache__/pipeline.cpython-313.pyc,,
134
+ pydantic/experimental/arguments_schema.py,sha256=EFnjX_ulp-tPyUjQX5pmQtug1OFL_Acc8bcMbLd-fVY,1866
135
+ pydantic/experimental/missing_sentinel.py,sha256=hQejgtF00wUuQMni9429evg-eXyIwpKvjsD8ofqfj-w,127
136
+ pydantic/experimental/pipeline.py,sha256=auoW6l6g1FC41LciPmsI1M6ncf00Szde9B3C-yvb9mI,23956
137
+ pydantic/fields.py,sha256=a8ZhJfI8FD6TQDD7-cWMm1ZXlQva0wMdT2Ey5VvVe-M,82023
138
+ pydantic/functional_serializers.py,sha256=zwRAjZusORtEbtxpVU20kg8FpemyZz4Fq6wJk1mpwYQ,18117
139
+ pydantic/functional_validators.py,sha256=7p-4jvP__9jZyvcdXiide5pAa_JlM7fJ1BgkqbjxSWM,31724
140
+ pydantic/generics.py,sha256=0ZqZ9O9annIj_3mGBRqps4htey3b5lV1-d2tUxPMMnA,144
141
+ pydantic/json.py,sha256=ZH8RkI7h4Bz-zp8OdTAxbJUoVvcoU-jhMdRZ0B-k0xc,140
142
+ pydantic/json_schema.py,sha256=da3hQ9vQPLEhPsrDnUlijfQ1fuCCViGVnUzOrAZLgDs,125955
143
+ pydantic/main.py,sha256=NbhCz-ku8wDgYLQMBi75Ov7hywdc8LewA3oUNIZ8JVQ,85334
144
+ pydantic/mypy.py,sha256=sYmmZrL_GvoYSLcBuPRRDfSfgQWehkzw_ZvNkwDY2ME,60971
145
+ pydantic/networks.py,sha256=gCB96gt0G7tiVDhVnJfpKr1ARL5qkH-SPZkuNkmG2O4,42102
146
+ pydantic/parse.py,sha256=wkd82dgtvWtD895U_I6E1htqMlGhBSYEV39cuBSeo3A,141
147
+ pydantic/plugin/__init__.py,sha256=a7Tw366U6K3kltCCNZY76nc9ss-7uGGQ40TXad9OypQ,7333
148
+ pydantic/plugin/__pycache__/__init__.cpython-313.pyc,,
149
+ pydantic/plugin/__pycache__/_loader.cpython-313.pyc,,
150
+ pydantic/plugin/__pycache__/_schema_validator.cpython-313.pyc,,
151
+ pydantic/plugin/_loader.py,sha256=hAjgSljoIhGx3AVpIpuqw5SPttBNNeGBSTrqSMnNiJk,2213
152
+ pydantic/plugin/_schema_validator.py,sha256=5M5Ic1bZnjhNDxtRDVKbRPTQ6po6QuKMY7MguMkHeW0,5445
153
+ pydantic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
+ pydantic/root_model.py,sha256=cOMoeWdp536KF85uRIcW-oz1O7d5GRCpx9HTS4-1uf8,6394
155
+ pydantic/schema.py,sha256=Vqqjvq_LnapVknebUd3Bp_J1p2gXZZnZRgL48bVEG7o,142
156
+ pydantic/tools.py,sha256=iHQpd8SJ5DCTtPV5atAV06T89bjSaMFeZZ2LX9lasZY,141
157
+ pydantic/type_adapter.py,sha256=T05g8WQczBsVU_35RdKxgjIi7Y7LIip67pF3NI7X4GE,36123
158
+ pydantic/types.py,sha256=fpYcGnAncK4QjaFm3jZtqYwxJYzB7rJJPfAl89emzyQ,105961
159
+ pydantic/typing.py,sha256=P7feA35MwTcLsR1uL7db0S-oydBxobmXa55YDoBgajQ,138
160
+ pydantic/utils.py,sha256=15nR2QpqTBFlQV4TNtTItMyTJx_fbyV-gPmIEY1Gooc,141
161
+ pydantic/v1/__init__.py,sha256=SxQPklgBs4XHJwE6BZ9qoewYoGiNyYUnmHzEFCZbfnI,2946
162
+ pydantic/v1/__pycache__/__init__.cpython-313.pyc,,
163
+ pydantic/v1/__pycache__/_hypothesis_plugin.cpython-313.pyc,,
164
+ pydantic/v1/__pycache__/annotated_types.cpython-313.pyc,,
165
+ pydantic/v1/__pycache__/class_validators.cpython-313.pyc,,
166
+ pydantic/v1/__pycache__/color.cpython-313.pyc,,
167
+ pydantic/v1/__pycache__/config.cpython-313.pyc,,
168
+ pydantic/v1/__pycache__/dataclasses.cpython-313.pyc,,
169
+ pydantic/v1/__pycache__/datetime_parse.cpython-313.pyc,,
170
+ pydantic/v1/__pycache__/decorator.cpython-313.pyc,,
171
+ pydantic/v1/__pycache__/env_settings.cpython-313.pyc,,
172
+ pydantic/v1/__pycache__/error_wrappers.cpython-313.pyc,,
173
+ pydantic/v1/__pycache__/errors.cpython-313.pyc,,
174
+ pydantic/v1/__pycache__/fields.cpython-313.pyc,,
175
+ pydantic/v1/__pycache__/generics.cpython-313.pyc,,
176
+ pydantic/v1/__pycache__/json.cpython-313.pyc,,
177
+ pydantic/v1/__pycache__/main.cpython-313.pyc,,
178
+ pydantic/v1/__pycache__/mypy.cpython-313.pyc,,
179
+ pydantic/v1/__pycache__/networks.cpython-313.pyc,,
180
+ pydantic/v1/__pycache__/parse.cpython-313.pyc,,
181
+ pydantic/v1/__pycache__/schema.cpython-313.pyc,,
182
+ pydantic/v1/__pycache__/tools.cpython-313.pyc,,
183
+ pydantic/v1/__pycache__/types.cpython-313.pyc,,
184
+ pydantic/v1/__pycache__/typing.cpython-313.pyc,,
185
+ pydantic/v1/__pycache__/utils.cpython-313.pyc,,
186
+ pydantic/v1/__pycache__/validators.cpython-313.pyc,,
187
+ pydantic/v1/__pycache__/version.cpython-313.pyc,,
188
+ pydantic/v1/_hypothesis_plugin.py,sha256=5ES5xWuw1FQAsymLezy8QgnVz0ZpVfU3jkmT74H27VQ,14847
189
+ pydantic/v1/annotated_types.py,sha256=uk2NAAxqiNELKjiHhyhxKaIOh8F1lYW_LzrW3X7oZBc,3157
190
+ pydantic/v1/class_validators.py,sha256=ULOaIUgYUDBsHL7EEVEarcM-UubKUggoN8hSbDonsFE,14672
191
+ pydantic/v1/color.py,sha256=iZABLYp6OVoo2AFkP9Ipri_wSc6-Kklu8YuhSartd5g,16844
192
+ pydantic/v1/config.py,sha256=a6P0Wer9x4cbwKW7Xv8poSUqM4WP-RLWwX6YMpYq9AA,6532
193
+ pydantic/v1/dataclasses.py,sha256=784cqvInbwIPWr9usfpX3ch7z4t3J2tTK6N067_wk1o,18172
194
+ pydantic/v1/datetime_parse.py,sha256=4Qy1kQpq3rNVZJeIHeSPDpuS2Bvhp1KPtzJG1xu-H00,7724
195
+ pydantic/v1/decorator.py,sha256=zaaxxxoWPCm818D1bs0yhapRjXm32V8G0ZHWCdM1uXA,10339
196
+ pydantic/v1/env_settings.py,sha256=A9VXwtRl02AY-jH0C0ouy5VNw3fi6F_pkzuHDjgAAOM,14105
197
+ pydantic/v1/error_wrappers.py,sha256=6625Mfw9qkC2NwitB_JFAWe8B-Xv6zBU7rL9k28tfyo,5196
198
+ pydantic/v1/errors.py,sha256=mIwPED5vGM5Q5v4C4Z1JPldTRH-omvEylH6ksMhOmPw,17726
199
+ pydantic/v1/fields.py,sha256=VqWJCriUNiEyptXroDVJ501JpVA0en2VANcksqXL2b8,50649
200
+ pydantic/v1/generics.py,sha256=YzyKTZN6x5Q1RGJ3WQ9jN-uwHJxL3W4qoZqwcZXqxWg,17829
201
+ pydantic/v1/json.py,sha256=WQ5Hy_hIpfdR3YS8k6N2E6KMJzsdbBi_ldWOPJaV81M,3390
202
+ pydantic/v1/main.py,sha256=vRB1TbpkzPN3P5ijJlc-cjNuO-HciNOpC4b8K3zZnfc,45697
203
+ pydantic/v1/mypy.py,sha256=Cl8XRfCmIcVE3j5AEU52C8iDh8lcX__D3hz2jIWxMAs,38860
204
+ pydantic/v1/networks.py,sha256=HYNtKAfOmOnKJpsDg1g6SIkj9WPhU_-i8l5e2JKBpG4,22124
205
+ pydantic/v1/parse.py,sha256=BJtdqiZRtav9VRFCmOxoY-KImQmjPy-A_NoojiFUZxY,1821
206
+ pydantic/v1/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
207
+ pydantic/v1/schema.py,sha256=aqBuA--cq8gAVkim5BJPFASHzOZ8dFtmFX_fNGr6ip4,47801
208
+ pydantic/v1/tools.py,sha256=1lDdXHk0jL5uP3u5RCYAvUAlGClgAO-45lkq9j7fyBA,2881
209
+ pydantic/v1/types.py,sha256=Bzl-RcnitPBHnqwwj9iv7JjHuN1GpnWH24dKkF3l9e8,35455
210
+ pydantic/v1/typing.py,sha256=ovwtLpEZCbnghZaHfSNJupzetzHNkLXjn_66kgTnIV4,20102
211
+ pydantic/v1/utils.py,sha256=1PqOIlz6OVWwGds3HBKlw4Et6asFou0UUpAto7jFOCs,26014
212
+ pydantic/v1/validators.py,sha256=lyUkn1MWhHxlCX5ZfEgFj_CAHojoiPcaQeMdEM9XviU,22187
213
+ pydantic/v1/version.py,sha256=YpHWOQKtGoxfyikzGrcmXJVKUVYB9EBdoCR994QxSnE,1039
214
+ pydantic/validate_call_decorator.py,sha256=VLAi4hoFpjC-1eL0HixYaaWaEFO6htGcDctgsqa5VII,4416
215
+ pydantic/validators.py,sha256=pwbIJXVb1CV2mAE4w_EGfNj7DwzsKaWw_tTL6cviTus,146
216
+ pydantic/version.py,sha256=T5rziwDPrMjfaU0X--5fBdGVvh94QznNQ7QjD4LfgmA,3985
217
+ pydantic/warnings.py,sha256=3QyQo6lN35cO7OXDbFEXWcNaPlGCRaregVZA-G-lZwI,4822
.mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/WHEEL ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
.mcp-venv/lib/python3.13/site-packages/pydantic-2.13.4.dist-info/licenses/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 to present Pydantic Services Inc. and individual contributors.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_known_annotated_metadata.py ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from collections import defaultdict
4
+ from collections.abc import Iterable
5
+ from copy import copy
6
+ from functools import lru_cache, partial
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ from pydantic_core import CoreSchema, PydanticCustomError, ValidationError, to_jsonable_python
10
+ from pydantic_core import core_schema as cs
11
+
12
+ from ._fields import PydanticMetadata
13
+ from ._import_utils import import_cached_field_info
14
+
15
+ if TYPE_CHECKING:
16
+ pass
17
+
18
+ STRICT = {'strict'}
19
+ FAIL_FAST = {'fail_fast'}
20
+ LENGTH_CONSTRAINTS = {'min_length', 'max_length'}
21
+ INEQUALITY = {'le', 'ge', 'lt', 'gt'}
22
+ NUMERIC_CONSTRAINTS = {'multiple_of', *INEQUALITY}
23
+ ALLOW_INF_NAN = {'allow_inf_nan'}
24
+
25
+ STR_CONSTRAINTS = {
26
+ *LENGTH_CONSTRAINTS,
27
+ *STRICT,
28
+ 'strip_whitespace',
29
+ 'to_lower',
30
+ 'to_upper',
31
+ 'pattern',
32
+ 'coerce_numbers_to_str',
33
+ 'ascii_only',
34
+ }
35
+ BYTES_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT}
36
+
37
+ LIST_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT, *FAIL_FAST}
38
+ TUPLE_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT, *FAIL_FAST}
39
+ SET_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT, *FAIL_FAST}
40
+ DICT_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT}
41
+ GENERATOR_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *STRICT}
42
+ SEQUENCE_CONSTRAINTS = {*LENGTH_CONSTRAINTS, *FAIL_FAST}
43
+
44
+ FLOAT_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *ALLOW_INF_NAN, *STRICT}
45
+ DECIMAL_CONSTRAINTS = {'max_digits', 'decimal_places', *FLOAT_CONSTRAINTS}
46
+ INT_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *ALLOW_INF_NAN, *STRICT}
47
+ BOOL_CONSTRAINTS = STRICT
48
+ UUID_CONSTRAINTS = STRICT
49
+
50
+ DATE_TIME_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *STRICT}
51
+ TIMEDELTA_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *STRICT}
52
+ TIME_CONSTRAINTS = {*NUMERIC_CONSTRAINTS, *STRICT}
53
+ LAX_OR_STRICT_CONSTRAINTS = STRICT
54
+ ENUM_CONSTRAINTS = STRICT
55
+ COMPLEX_CONSTRAINTS = STRICT
56
+
57
+ UNION_CONSTRAINTS = {'union_mode'}
58
+ URL_CONSTRAINTS = {
59
+ 'max_length',
60
+ 'allowed_schemes',
61
+ 'host_required',
62
+ 'default_host',
63
+ 'default_port',
64
+ 'default_path',
65
+ }
66
+
67
+ TEXT_SCHEMA_TYPES = ('str', 'bytes', 'url', 'multi-host-url')
68
+ SEQUENCE_SCHEMA_TYPES = ('list', 'tuple', 'set', 'frozenset', 'generator', *TEXT_SCHEMA_TYPES)
69
+ NUMERIC_SCHEMA_TYPES = ('float', 'int', 'date', 'time', 'timedelta', 'datetime')
70
+
71
+ CONSTRAINTS_TO_ALLOWED_SCHEMAS: dict[str, set[str]] = defaultdict(set)
72
+
73
+ constraint_schema_pairings: list[tuple[set[str], tuple[str, ...]]] = [
74
+ (STR_CONSTRAINTS, TEXT_SCHEMA_TYPES),
75
+ (BYTES_CONSTRAINTS, ('bytes',)),
76
+ (LIST_CONSTRAINTS, ('list',)),
77
+ (TUPLE_CONSTRAINTS, ('tuple',)),
78
+ (SET_CONSTRAINTS, ('set', 'frozenset')),
79
+ (DICT_CONSTRAINTS, ('dict',)),
80
+ (GENERATOR_CONSTRAINTS, ('generator',)),
81
+ (FLOAT_CONSTRAINTS, ('float',)),
82
+ (INT_CONSTRAINTS, ('int',)),
83
+ (DATE_TIME_CONSTRAINTS, ('date', 'time', 'datetime', 'timedelta')),
84
+ # TODO: this is a bit redundant, we could probably avoid some of these
85
+ (STRICT, (*TEXT_SCHEMA_TYPES, *SEQUENCE_SCHEMA_TYPES, *NUMERIC_SCHEMA_TYPES, 'typed-dict', 'model')),
86
+ (UNION_CONSTRAINTS, ('union',)),
87
+ (URL_CONSTRAINTS, ('url', 'multi-host-url')),
88
+ (BOOL_CONSTRAINTS, ('bool',)),
89
+ (UUID_CONSTRAINTS, ('uuid',)),
90
+ (LAX_OR_STRICT_CONSTRAINTS, ('lax-or-strict',)),
91
+ (ENUM_CONSTRAINTS, ('enum',)),
92
+ (DECIMAL_CONSTRAINTS, ('decimal',)),
93
+ (COMPLEX_CONSTRAINTS, ('complex',)),
94
+ ]
95
+
96
+ for constraints, schemas in constraint_schema_pairings:
97
+ for c in constraints:
98
+ CONSTRAINTS_TO_ALLOWED_SCHEMAS[c].update(schemas)
99
+
100
+
101
+ def as_jsonable_value(v: Any) -> Any:
102
+ if type(v) not in (int, str, float, bytes, bool, type(None)):
103
+ return to_jsonable_python(v)
104
+ return v
105
+
106
+
107
+ def expand_grouped_metadata(annotations: Iterable[Any]) -> Iterable[Any]:
108
+ """Expand the annotations.
109
+
110
+ Args:
111
+ annotations: An iterable of annotations.
112
+
113
+ Returns:
114
+ An iterable of expanded annotations.
115
+
116
+ Example:
117
+ ```python
118
+ from annotated_types import Ge, Len
119
+
120
+ from pydantic._internal._known_annotated_metadata import expand_grouped_metadata
121
+
122
+ print(list(expand_grouped_metadata([Ge(4), Len(5)])))
123
+ #> [Ge(ge=4), MinLen(min_length=5)]
124
+ ```
125
+ """
126
+ import annotated_types as at
127
+
128
+ FieldInfo = import_cached_field_info()
129
+
130
+ for annotation in annotations:
131
+ if isinstance(annotation, at.GroupedMetadata):
132
+ yield from annotation
133
+ elif isinstance(annotation, FieldInfo):
134
+ yield from annotation.metadata
135
+ # this is a bit problematic in that it results in duplicate metadata
136
+ # all of our "consumers" can handle it, but it is not ideal
137
+ # we probably should split up FieldInfo into:
138
+ # - annotated types metadata
139
+ # - individual metadata known only to Pydantic
140
+ annotation = copy(annotation)
141
+ annotation.metadata = []
142
+ yield annotation
143
+ else:
144
+ yield annotation
145
+
146
+
147
+ @lru_cache
148
+ def _get_at_to_constraint_map() -> dict[type, str]:
149
+ """Return a mapping of annotated types to constraints.
150
+
151
+ Normally, we would define a mapping like this in the module scope, but we can't do that
152
+ because we don't permit module level imports of `annotated_types`, in an attempt to speed up
153
+ the import time of `pydantic`. We still only want to have this dictionary defined in one place,
154
+ so we use this function to cache the result.
155
+ """
156
+ import annotated_types as at
157
+
158
+ return {
159
+ at.Gt: 'gt',
160
+ at.Ge: 'ge',
161
+ at.Lt: 'lt',
162
+ at.Le: 'le',
163
+ at.MultipleOf: 'multiple_of',
164
+ at.MinLen: 'min_length',
165
+ at.MaxLen: 'max_length',
166
+ }
167
+
168
+
169
+ def apply_known_metadata(annotation: Any, schema: CoreSchema) -> CoreSchema | None: # noqa: C901
170
+ """Apply `annotation` to `schema` if it is an annotation we know about (Gt, Le, etc.).
171
+ Otherwise return `None`.
172
+
173
+ This does not handle all known annotations. If / when it does, it can always
174
+ return a CoreSchema and return the unmodified schema if the annotation should be ignored.
175
+
176
+ Assumes that GroupedMetadata has already been expanded via `expand_grouped_metadata`.
177
+
178
+ Args:
179
+ annotation: The annotation.
180
+ schema: The schema.
181
+
182
+ Returns:
183
+ An updated schema with annotation if it is an annotation we know about, `None` otherwise.
184
+
185
+ Raises:
186
+ RuntimeError: If a constraint can't be applied to a specific schema type.
187
+ ValueError: If an unknown constraint is encountered.
188
+ """
189
+ import annotated_types as at
190
+
191
+ from ._validators import NUMERIC_VALIDATOR_LOOKUP, forbid_inf_nan_check
192
+
193
+ schema = schema.copy()
194
+ schema_update, other_metadata = collect_known_metadata([annotation])
195
+ schema_type = schema['type']
196
+
197
+ chain_schema_constraints: set[str] = {
198
+ 'pattern',
199
+ 'strip_whitespace',
200
+ 'to_lower',
201
+ 'to_upper',
202
+ 'coerce_numbers_to_str',
203
+ 'ascii_only',
204
+ }
205
+ chain_schema_steps: list[CoreSchema] = []
206
+
207
+ for constraint, value in schema_update.items():
208
+ if constraint not in CONSTRAINTS_TO_ALLOWED_SCHEMAS:
209
+ raise ValueError(f'Unknown constraint {constraint}')
210
+ allowed_schemas = CONSTRAINTS_TO_ALLOWED_SCHEMAS[constraint]
211
+
212
+ # if it becomes necessary to handle more than one constraint
213
+ # in this recursive case with function-after or function-wrap, we should refactor
214
+ # this is a bit challenging because we sometimes want to apply constraints to the inner schema,
215
+ # whereas other times we want to wrap the existing schema with a new one that enforces a new constraint.
216
+ if schema_type in {'function-before', 'function-wrap', 'function-after'} and constraint == 'strict':
217
+ schema['schema'] = apply_known_metadata(annotation, schema['schema']) # type: ignore # schema is function schema
218
+ return schema
219
+
220
+ # if we're allowed to apply constraint directly to the schema, like le to int, do that
221
+ if schema_type in allowed_schemas:
222
+ if constraint == 'union_mode' and schema_type == 'union':
223
+ schema['mode'] = value # type: ignore # schema is UnionSchema
224
+ else:
225
+ schema[constraint] = value
226
+ continue
227
+
228
+ # else, apply a function after validator to the schema to enforce the corresponding constraint
229
+ if constraint in chain_schema_constraints:
230
+
231
+ def _apply_constraint_with_incompatibility_info(
232
+ value: Any, handler: cs.ValidatorFunctionWrapHandler
233
+ ) -> Any:
234
+ try:
235
+ x = handler(value)
236
+ except ValidationError as ve:
237
+ # if the error is about the type, it's likely that the constraint is incompatible the type of the field
238
+ # for example, the following invalid schema wouldn't be caught during schema build, but rather at this point
239
+ # with a cryptic 'string_type' error coming from the string validator,
240
+ # that we'd rather express as a constraint incompatibility error (TypeError)
241
+ # Annotated[list[int], Field(pattern='abc')]
242
+ if 'type' in ve.errors()[0]['type']:
243
+ raise TypeError(
244
+ f"Unable to apply constraint '{constraint}' to supplied value {value} for schema of type '{schema_type}'" # noqa: B023
245
+ )
246
+ raise ve
247
+ return x
248
+
249
+ chain_schema_steps.append(
250
+ cs.no_info_wrap_validator_function(
251
+ _apply_constraint_with_incompatibility_info, cs.str_schema(**{constraint: value})
252
+ )
253
+ )
254
+ elif constraint in NUMERIC_VALIDATOR_LOOKUP:
255
+ if constraint in LENGTH_CONSTRAINTS:
256
+ inner_schema = schema
257
+ while inner_schema['type'] in {'function-before', 'function-wrap', 'function-after'}:
258
+ inner_schema = inner_schema['schema'] # type: ignore
259
+ inner_schema_type = inner_schema['type']
260
+ if inner_schema_type == 'list' or (
261
+ inner_schema_type == 'json-or-python' and inner_schema['json_schema']['type'] == 'list' # type: ignore
262
+ ):
263
+ js_constraint_key = 'minItems' if constraint == 'min_length' else 'maxItems'
264
+ else:
265
+ js_constraint_key = 'minLength' if constraint == 'min_length' else 'maxLength'
266
+ else:
267
+ js_constraint_key = constraint
268
+
269
+ schema = cs.no_info_after_validator_function(
270
+ partial(NUMERIC_VALIDATOR_LOOKUP[constraint], **{constraint: value}), schema
271
+ )
272
+ metadata = schema.get('metadata', {})
273
+ if (existing_json_schema_updates := metadata.get('pydantic_js_updates')) is not None:
274
+ metadata['pydantic_js_updates'] = {
275
+ **existing_json_schema_updates,
276
+ **{js_constraint_key: as_jsonable_value(value)},
277
+ }
278
+ else:
279
+ metadata['pydantic_js_updates'] = {js_constraint_key: as_jsonable_value(value)}
280
+ schema['metadata'] = metadata
281
+ elif constraint == 'allow_inf_nan' and value is False:
282
+ schema = cs.no_info_after_validator_function(
283
+ forbid_inf_nan_check,
284
+ schema,
285
+ )
286
+ else:
287
+ # It's rare that we'd get here, but it's possible if we add a new constraint and forget to handle it
288
+ # Most constraint errors are caught at runtime during attempted application
289
+ raise RuntimeError(f"Unable to apply constraint '{constraint}' to schema of type '{schema_type}'")
290
+
291
+ for annotation in other_metadata:
292
+ if (annotation_type := type(annotation)) in (at_to_constraint_map := _get_at_to_constraint_map()):
293
+ constraint = at_to_constraint_map[annotation_type]
294
+ validator = NUMERIC_VALIDATOR_LOOKUP.get(constraint)
295
+ if validator is None:
296
+ raise ValueError(f'Unknown constraint {constraint}')
297
+ schema = cs.no_info_after_validator_function(
298
+ partial(validator, {constraint: getattr(annotation, constraint)}), schema
299
+ )
300
+ continue
301
+ elif isinstance(annotation, (at.Predicate, at.Not)):
302
+ predicate_name = f'{annotation.func.__qualname__!r} ' if hasattr(annotation.func, '__qualname__') else ''
303
+
304
+ # Note: B023 is ignored because even though we iterate over `other_metadata`, it is guaranteed
305
+ # to be of length 1. `apply_known_metadata()` is called from `GenerateSchema`, where annotations
306
+ # were already expanded via `expand_grouped_metadata()`. Confusing, but this falls into the annotations
307
+ # refactor.
308
+ if isinstance(annotation, at.Predicate):
309
+
310
+ def val_func(v: Any) -> Any:
311
+ predicate_satisfied = annotation.func(v) # noqa: B023
312
+ if not predicate_satisfied:
313
+ raise PydanticCustomError(
314
+ 'predicate_failed',
315
+ f'Predicate {predicate_name}failed', # pyright: ignore[reportArgumentType] # noqa: B023
316
+ )
317
+ return v
318
+
319
+ else:
320
+
321
+ def val_func(v: Any) -> Any:
322
+ predicate_satisfied = annotation.func(v) # noqa: B023
323
+ if predicate_satisfied:
324
+ raise PydanticCustomError(
325
+ 'not_operation_failed',
326
+ f'Not of {predicate_name}failed', # pyright: ignore[reportArgumentType] # noqa: B023
327
+ )
328
+ return v
329
+
330
+ schema = cs.no_info_after_validator_function(val_func, schema)
331
+ else:
332
+ # ignore any other unknown metadata
333
+ return None
334
+
335
+ if chain_schema_steps:
336
+ chain_schema_steps = [schema] + chain_schema_steps
337
+ return cs.chain_schema(chain_schema_steps)
338
+
339
+ return schema
340
+
341
+
342
+ def collect_known_metadata(annotations: Iterable[Any]) -> tuple[dict[str, Any], list[Any]]:
343
+ """Split `annotations` into known metadata and unknown annotations.
344
+
345
+ Args:
346
+ annotations: An iterable of annotations.
347
+
348
+ Returns:
349
+ A tuple contains a dict of known metadata and a list of unknown annotations.
350
+
351
+ Example:
352
+ ```python
353
+ from annotated_types import Gt, Len
354
+
355
+ from pydantic._internal._known_annotated_metadata import collect_known_metadata
356
+
357
+ print(collect_known_metadata([Gt(1), Len(42), ...]))
358
+ #> ({'gt': 1, 'min_length': 42}, [Ellipsis])
359
+ ```
360
+ """
361
+ annotations = expand_grouped_metadata(annotations)
362
+
363
+ res: dict[str, Any] = {}
364
+ remaining: list[Any] = []
365
+
366
+ for annotation in annotations:
367
+ # isinstance(annotation, PydanticMetadata) also covers ._fields:_PydanticGeneralMetadata
368
+ if isinstance(annotation, PydanticMetadata):
369
+ res.update(annotation.__dict__)
370
+ # we don't use dataclasses.asdict because that recursively calls asdict on the field values
371
+ elif (annotation_type := type(annotation)) in (at_to_constraint_map := _get_at_to_constraint_map()):
372
+ constraint = at_to_constraint_map[annotation_type]
373
+ res[constraint] = getattr(annotation, constraint)
374
+ elif isinstance(annotation, type) and issubclass(annotation, PydanticMetadata):
375
+ # also support PydanticMetadata classes being used without initialisation,
376
+ # e.g. `Annotated[int, Strict]` as well as `Annotated[int, Strict()]`
377
+ res.update({k: v for k, v in vars(annotation).items() if not k.startswith('_')})
378
+ else:
379
+ remaining.append(annotation)
380
+ # Nones can sneak in but pydantic-core will reject them
381
+ # it'd be nice to clean things up so we don't put in None (we probably don't _need_ to, it was just easier)
382
+ # but this is simple enough to kick that can down the road
383
+ res = {k: v for k, v in res.items() if v is not None}
384
+ return res, remaining
385
+
386
+
387
+ def check_metadata(metadata: dict[str, Any], allowed: Iterable[str], source_type: Any) -> None:
388
+ """A small utility function to validate that the given metadata can be applied to the target.
389
+ More than saving lines of code, this gives us a consistent error message for all of our internal implementations.
390
+
391
+ Args:
392
+ metadata: A dict of metadata.
393
+ allowed: An iterable of allowed metadata.
394
+ source_type: The source type.
395
+
396
+ Raises:
397
+ TypeError: If there is metadatas that can't be applied on source type.
398
+ """
399
+ unknown = metadata.keys() - set(allowed)
400
+ if unknown:
401
+ raise TypeError(
402
+ f'The following constraints cannot be applied to {source_type!r}: {", ".join([f"{k!r}" for k in unknown])}'
403
+ )
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_mock_val_ser.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterator, Mapping
4
+ from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, TypeVar, Union
5
+
6
+ from pydantic_core import CoreSchema, SchemaSerializer, SchemaValidator
7
+
8
+ from ..errors import PydanticErrorCodes, PydanticUserError
9
+ from ..plugin._schema_validator import PluggableSchemaValidator
10
+
11
+ if TYPE_CHECKING:
12
+ from ..dataclasses import PydanticDataclass
13
+ from ..main import BaseModel
14
+ from ..type_adapter import TypeAdapter
15
+
16
+
17
+ ValSer = TypeVar('ValSer', bound=Union[SchemaValidator, PluggableSchemaValidator, SchemaSerializer])
18
+ T = TypeVar('T')
19
+
20
+
21
+ class MockCoreSchema(Mapping[str, Any]):
22
+ """Mocker for `pydantic_core.CoreSchema` which optionally attempts to
23
+ rebuild the thing it's mocking when one of its methods is accessed and raises an error if that fails.
24
+ """
25
+
26
+ __slots__ = '_error_message', '_code', '_attempt_rebuild', '_built_memo'
27
+
28
+ def __init__(
29
+ self,
30
+ error_message: str,
31
+ *,
32
+ code: PydanticErrorCodes,
33
+ attempt_rebuild: Callable[[], CoreSchema | None] | None = None,
34
+ ) -> None:
35
+ self._error_message = error_message
36
+ self._code: PydanticErrorCodes = code
37
+ self._attempt_rebuild = attempt_rebuild
38
+ self._built_memo: CoreSchema | None = None
39
+
40
+ def __getitem__(self, key: str) -> Any:
41
+ return self._get_built().__getitem__(key)
42
+
43
+ def __len__(self) -> int:
44
+ return self._get_built().__len__()
45
+
46
+ def __iter__(self) -> Iterator[str]:
47
+ return self._get_built().__iter__()
48
+
49
+ def _get_built(self) -> CoreSchema:
50
+ if self._built_memo is not None:
51
+ return self._built_memo
52
+
53
+ if self._attempt_rebuild:
54
+ schema = self._attempt_rebuild()
55
+ if schema is not None:
56
+ self._built_memo = schema
57
+ return schema
58
+ raise PydanticUserError(self._error_message, code=self._code)
59
+
60
+ def rebuild(self) -> CoreSchema | None:
61
+ self._built_memo = None
62
+ if self._attempt_rebuild:
63
+ schema = self._attempt_rebuild()
64
+ if schema is not None:
65
+ return schema
66
+ else:
67
+ raise PydanticUserError(self._error_message, code=self._code)
68
+ return None
69
+
70
+
71
+ class MockValSer(Generic[ValSer]):
72
+ """Mocker for `pydantic_core.SchemaValidator` or `pydantic_core.SchemaSerializer` which optionally attempts to
73
+ rebuild the thing it's mocking when one of its methods is accessed and raises an error if that fails.
74
+ """
75
+
76
+ __slots__ = '_error_message', '_code', '_val_or_ser', '_attempt_rebuild'
77
+
78
+ def __init__(
79
+ self,
80
+ error_message: str,
81
+ *,
82
+ code: PydanticErrorCodes,
83
+ val_or_ser: Literal['validator', 'serializer'],
84
+ attempt_rebuild: Callable[[], ValSer | None] | None = None,
85
+ ) -> None:
86
+ self._error_message = error_message
87
+ self._val_or_ser = SchemaValidator if val_or_ser == 'validator' else SchemaSerializer
88
+ self._code: PydanticErrorCodes = code
89
+ self._attempt_rebuild = attempt_rebuild
90
+
91
+ def __getattr__(self, item: str) -> None:
92
+ __tracebackhide__ = True
93
+ if self._attempt_rebuild:
94
+ val_ser = self._attempt_rebuild()
95
+ if val_ser is not None:
96
+ return getattr(val_ser, item)
97
+
98
+ # raise an AttributeError if `item` doesn't exist
99
+ getattr(self._val_or_ser, item)
100
+ raise PydanticUserError(self._error_message, code=self._code)
101
+
102
+ def rebuild(self) -> ValSer | None:
103
+ if self._attempt_rebuild:
104
+ val_ser = self._attempt_rebuild()
105
+ if val_ser is not None:
106
+ return val_ser
107
+ else:
108
+ raise PydanticUserError(self._error_message, code=self._code)
109
+ return None
110
+
111
+
112
+ def set_type_adapter_mocks(adapter: TypeAdapter) -> None:
113
+ """Set `core_schema`, `validator` and `serializer` to mock core types on a type adapter instance.
114
+
115
+ Args:
116
+ adapter: The type adapter instance to set the mocks on
117
+ """
118
+ type_repr = str(adapter._type)
119
+ undefined_type_error_message = (
120
+ f'`TypeAdapter[{type_repr}]` is not fully defined; you should define `{type_repr}` and all referenced types,'
121
+ f' then call `.rebuild()` on the instance.'
122
+ )
123
+
124
+ def attempt_rebuild_fn(attr_fn: Callable[[TypeAdapter], T]) -> Callable[[], T | None]:
125
+ def handler() -> T | None:
126
+ if adapter.rebuild(raise_errors=False, _parent_namespace_depth=5) is not False:
127
+ return attr_fn(adapter)
128
+ return None
129
+
130
+ return handler
131
+
132
+ adapter.core_schema = MockCoreSchema( # pyright: ignore[reportAttributeAccessIssue]
133
+ undefined_type_error_message,
134
+ code='class-not-fully-defined',
135
+ attempt_rebuild=attempt_rebuild_fn(lambda ta: ta.core_schema),
136
+ )
137
+ adapter.validator = MockValSer( # pyright: ignore[reportAttributeAccessIssue]
138
+ undefined_type_error_message,
139
+ code='class-not-fully-defined',
140
+ val_or_ser='validator',
141
+ attempt_rebuild=attempt_rebuild_fn(lambda ta: ta.validator),
142
+ )
143
+ adapter.serializer = MockValSer( # pyright: ignore[reportAttributeAccessIssue]
144
+ undefined_type_error_message,
145
+ code='class-not-fully-defined',
146
+ val_or_ser='serializer',
147
+ attempt_rebuild=attempt_rebuild_fn(lambda ta: ta.serializer),
148
+ )
149
+
150
+
151
+ def set_model_mocks(cls: type[BaseModel], undefined_name: str = 'all referenced types') -> None:
152
+ """Set `__pydantic_core_schema__`, `__pydantic_validator__` and `__pydantic_serializer__` to mock core types on a model.
153
+
154
+ Args:
155
+ cls: The model class to set the mocks on
156
+ undefined_name: Name of the undefined thing, used in error messages
157
+ """
158
+ undefined_type_error_message = (
159
+ f'`{cls.__name__}` is not fully defined; you should define {undefined_name},'
160
+ f' then call `{cls.__name__}.model_rebuild()`.'
161
+ )
162
+
163
+ def attempt_rebuild_fn(attr_fn: Callable[[type[BaseModel]], T]) -> Callable[[], T | None]:
164
+ def handler() -> T | None:
165
+ if cls.model_rebuild(raise_errors=False, _parent_namespace_depth=5) is not False:
166
+ return attr_fn(cls)
167
+ return None
168
+
169
+ return handler
170
+
171
+ cls.__pydantic_core_schema__ = MockCoreSchema( # pyright: ignore[reportAttributeAccessIssue]
172
+ undefined_type_error_message,
173
+ code='class-not-fully-defined',
174
+ attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_core_schema__),
175
+ )
176
+ cls.__pydantic_validator__ = MockValSer( # pyright: ignore[reportAttributeAccessIssue]
177
+ undefined_type_error_message,
178
+ code='class-not-fully-defined',
179
+ val_or_ser='validator',
180
+ attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_validator__),
181
+ )
182
+ cls.__pydantic_serializer__ = MockValSer( # pyright: ignore[reportAttributeAccessIssue]
183
+ undefined_type_error_message,
184
+ code='class-not-fully-defined',
185
+ val_or_ser='serializer',
186
+ attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_serializer__),
187
+ )
188
+
189
+
190
+ def set_dataclass_mocks(cls: type[PydanticDataclass], undefined_name: str = 'all referenced types') -> None:
191
+ """Set `__pydantic_validator__` and `__pydantic_serializer__` to `MockValSer`s on a dataclass.
192
+
193
+ Args:
194
+ cls: The model class to set the mocks on
195
+ undefined_name: Name of the undefined thing, used in error messages
196
+ """
197
+ from ..dataclasses import rebuild_dataclass
198
+
199
+ undefined_type_error_message = (
200
+ f'`{cls.__name__}` is not fully defined; you should define {undefined_name},'
201
+ f' then call `pydantic.dataclasses.rebuild_dataclass({cls.__name__})`.'
202
+ )
203
+
204
+ def attempt_rebuild_fn(attr_fn: Callable[[type[PydanticDataclass]], T]) -> Callable[[], T | None]:
205
+ def handler() -> T | None:
206
+ if rebuild_dataclass(cls, raise_errors=False, _parent_namespace_depth=5) is not False:
207
+ return attr_fn(cls)
208
+ return None
209
+
210
+ return handler
211
+
212
+ cls.__pydantic_core_schema__ = MockCoreSchema( # pyright: ignore[reportAttributeAccessIssue]
213
+ undefined_type_error_message,
214
+ code='class-not-fully-defined',
215
+ attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_core_schema__),
216
+ )
217
+ cls.__pydantic_validator__ = MockValSer( # pyright: ignore[reportAttributeAccessIssue]
218
+ undefined_type_error_message,
219
+ code='class-not-fully-defined',
220
+ val_or_ser='validator',
221
+ attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_validator__),
222
+ )
223
+ cls.__pydantic_serializer__ = MockValSer( # pyright: ignore[reportAttributeAccessIssue]
224
+ undefined_type_error_message,
225
+ code='class-not-fully-defined',
226
+ val_or_ser='serializer',
227
+ attempt_rebuild=attempt_rebuild_fn(lambda c: c.__pydantic_serializer__),
228
+ )
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_model_construction.py ADDED
@@ -0,0 +1,868 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Private logic for creating models."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ import operator
6
+ import sys
7
+ import typing
8
+ import warnings
9
+ import weakref
10
+ from abc import ABCMeta
11
+ from functools import cache, partial, wraps
12
+ from types import FunctionType
13
+ from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, NoReturn, TypeVar, cast
14
+
15
+ from pydantic_core import PydanticUndefined, SchemaSerializer
16
+ from typing_extensions import TypeAliasType, dataclass_transform, deprecated, get_args, get_origin
17
+ from typing_inspection import typing_objects
18
+
19
+ from ..errors import PydanticUndefinedAnnotation, PydanticUserError
20
+ from ..plugin._schema_validator import create_schema_validator
21
+ from ..warnings import GenericBeforeBaseModelWarning, PydanticDeprecatedSince20
22
+ from ._config import ConfigWrapper
23
+ from ._decorators import DecoratorInfos, PydanticDescriptorProxy, get_attribute_from_bases, unwrap_wrapped_function
24
+ from ._fields import collect_model_fields, is_valid_field_name, is_valid_privateattr_name, rebuild_model_fields
25
+ from ._generate_schema import GenerateSchema, InvalidSchemaError
26
+ from ._generics import PydanticGenericMetadata, get_model_typevars_map
27
+ from ._import_utils import import_cached_base_model, import_cached_field_info
28
+ from ._mock_val_ser import set_model_mocks
29
+ from ._namespace_utils import NsResolver
30
+ from ._signature import generate_pydantic_signature
31
+ from ._typing_extra import (
32
+ _make_forward_ref,
33
+ eval_type_backport,
34
+ is_classvar_annotation,
35
+ parent_frame_namespace,
36
+ )
37
+ from ._utils import LazyClassAttribute, SafeGetItemProxy
38
+
39
+ if TYPE_CHECKING:
40
+ from ..fields import Field as PydanticModelField
41
+ from ..fields import FieldInfo, ModelPrivateAttr
42
+ from ..fields import PrivateAttr as PydanticModelPrivateAttr
43
+ from ..main import BaseModel
44
+ from ._fields import PydanticExtraInfo
45
+ else:
46
+ PydanticModelField = object()
47
+ PydanticModelPrivateAttr = object()
48
+
49
+ object_setattr = object.__setattr__
50
+
51
+
52
+ class _ModelNamespaceDict(dict):
53
+ """A dictionary subclass that intercepts attribute setting on model classes and
54
+ warns about overriding of decorators.
55
+ """
56
+
57
+ def __setitem__(self, k: str, v: object) -> None:
58
+ existing: Any = self.get(k, None)
59
+ if existing and v is not existing and isinstance(existing, PydanticDescriptorProxy):
60
+ warnings.warn(
61
+ f'`{k}` overrides an existing Pydantic `{existing.decorator_info.decorator_repr}` decorator',
62
+ stacklevel=2,
63
+ )
64
+
65
+ return super().__setitem__(k, v)
66
+
67
+
68
+ def NoInitField(
69
+ *,
70
+ init: Literal[False] = False,
71
+ ) -> Any:
72
+ """Only for typing purposes. Used as default value of `__pydantic_fields_set__`,
73
+ `__pydantic_extra__`, `__pydantic_private__`, so they could be ignored when
74
+ synthesizing the `__init__` signature.
75
+ """
76
+
77
+
78
+ # For ModelMetaclass.register():
79
+ _T = TypeVar('_T')
80
+
81
+
82
+ @dataclass_transform(kw_only_default=True, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr, NoInitField))
83
+ class ModelMetaclass(ABCMeta):
84
+ def __new__(
85
+ mcs,
86
+ cls_name: str,
87
+ bases: tuple[type[Any], ...],
88
+ namespace: dict[str, Any],
89
+ __pydantic_generic_metadata__: PydanticGenericMetadata | None = None,
90
+ __pydantic_reset_parent_namespace__: bool = True,
91
+ _create_model_module: str | None = None,
92
+ **kwargs: Any,
93
+ ) -> type:
94
+ """Metaclass for creating Pydantic models.
95
+
96
+ Args:
97
+ cls_name: The name of the class to be created.
98
+ bases: The base classes of the class to be created.
99
+ namespace: The attribute dictionary of the class to be created.
100
+ __pydantic_generic_metadata__: Metadata for generic models.
101
+ __pydantic_reset_parent_namespace__: Reset parent namespace.
102
+ _create_model_module: The module of the class to be created, if created by `create_model`.
103
+ **kwargs: Catch-all for any other keyword arguments.
104
+
105
+ Returns:
106
+ The new class created by the metaclass.
107
+ """
108
+ # Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we rely on the fact
109
+ # that `BaseModel` itself won't have any bases, but any subclass of it will, to determine whether the `__new__`
110
+ # call we're in the middle of is for the `BaseModel` class.
111
+ if bases:
112
+ raw_annotations: dict[str, Any]
113
+ if sys.version_info >= (3, 14):
114
+ if (
115
+ '__annotations__' in namespace
116
+ ): # `from __future__ import annotations` was used in the model's module
117
+ raw_annotations = namespace['__annotations__']
118
+ else:
119
+ # See https://docs.python.org/3.14/library/annotationlib.html#using-annotations-in-a-metaclass:
120
+ from annotationlib import Format, call_annotate_function, get_annotate_from_class_namespace
121
+
122
+ if annotate := get_annotate_from_class_namespace(namespace):
123
+ raw_annotations = call_annotate_function(annotate, format=Format.FORWARDREF)
124
+ else:
125
+ raw_annotations = {}
126
+ else:
127
+ raw_annotations = namespace.get('__annotations__', {})
128
+
129
+ base_field_names, class_vars, base_private_attributes = mcs._collect_bases_data(bases)
130
+
131
+ config_wrapper = ConfigWrapper.for_model(bases, namespace, raw_annotations, kwargs)
132
+ namespace['model_config'] = config_wrapper.config_dict
133
+ private_attributes = inspect_namespace(
134
+ namespace, raw_annotations, config_wrapper.ignored_types, class_vars, base_field_names
135
+ )
136
+ if private_attributes or base_private_attributes:
137
+ original_model_post_init = get_model_post_init(namespace, bases)
138
+ if original_model_post_init is not None:
139
+ # if there are private attributes and a model_post_init function, we handle both
140
+
141
+ @wraps(original_model_post_init)
142
+ def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
143
+ """We need to both initialize private attributes and call the user-defined model_post_init
144
+ method.
145
+ """
146
+ init_private_attributes(self, context)
147
+ original_model_post_init(self, context)
148
+
149
+ namespace['model_post_init'] = wrapped_model_post_init
150
+ else:
151
+ namespace['model_post_init'] = init_private_attributes
152
+
153
+ namespace['__class_vars__'] = class_vars
154
+ namespace['__private_attributes__'] = {**base_private_attributes, **private_attributes}
155
+
156
+ cls = cast('type[BaseModel]', super().__new__(mcs, cls_name, bases, namespace, **kwargs))
157
+ BaseModel_ = import_cached_base_model()
158
+
159
+ mro = cls.__mro__
160
+ if Generic in mro and mro.index(Generic) < mro.index(BaseModel_):
161
+ warnings.warn(
162
+ GenericBeforeBaseModelWarning(
163
+ 'Classes should inherit from `BaseModel` before generic classes (e.g. `typing.Generic[T]`) '
164
+ 'for pydantic generics to work properly.'
165
+ ),
166
+ stacklevel=2,
167
+ )
168
+
169
+ cls.__pydantic_custom_init__ = not getattr(cls.__init__, '__pydantic_base_init__', False)
170
+ cls.__pydantic_post_init__ = (
171
+ None if cls.model_post_init is BaseModel_.model_post_init else 'model_post_init'
172
+ )
173
+
174
+ cls.__pydantic_setattr_handlers__ = {}
175
+
176
+ cls.__pydantic_decorators__ = DecoratorInfos.build(cls, replace_wrapped_methods=True)
177
+ cls.__pydantic_decorators__.update_from_config(config_wrapper)
178
+
179
+ # Use the getattr below to grab the __parameters__ from the `typing.Generic` parent class
180
+ if __pydantic_generic_metadata__:
181
+ cls.__pydantic_generic_metadata__ = __pydantic_generic_metadata__
182
+ else:
183
+ parent_parameters = getattr(cls, '__pydantic_generic_metadata__', {}).get('parameters', ())
184
+ parameters = getattr(cls, '__parameters__', None) or parent_parameters
185
+ if parameters and parent_parameters and not all(x in parameters for x in parent_parameters):
186
+ from ..root_model import RootModelRootType
187
+
188
+ missing_parameters = tuple(x for x in parameters if x not in parent_parameters)
189
+ if RootModelRootType in parent_parameters and RootModelRootType not in parameters:
190
+ # This is a special case where the user has subclassed RootModel, but has not parameterized
191
+ # RootModel with the generic type identifiers being used. Ex:
192
+ # class MyModel(RootModel, Generic[T]):
193
+ # root: T
194
+ # Should instead just be:
195
+ # class MyModel(RootModel[T]):
196
+ # root: T
197
+ parameters_str = ', '.join([x.__name__ for x in missing_parameters])
198
+ error_message = (
199
+ f'{cls.__name__} is a subclass of `RootModel`, but does not include the generic type identifier(s) '
200
+ f'{parameters_str} in its parameters. '
201
+ f'You should parametrize RootModel directly, e.g., `class {cls.__name__}(RootModel[{parameters_str}]): ...`.'
202
+ )
203
+ else:
204
+ combined_parameters = parent_parameters + missing_parameters
205
+ parameters_str = ', '.join([str(x) for x in combined_parameters])
206
+ generic_type_label = f'typing.Generic[{parameters_str}]'
207
+ error_message = (
208
+ f'All parameters must be present on typing.Generic;'
209
+ f' you should inherit from {generic_type_label}.'
210
+ )
211
+ if Generic not in bases: # pragma: no cover
212
+ # We raise an error here not because it is desirable, but because some cases are mishandled.
213
+ # It would be nice to remove this error and still have things behave as expected, it's just
214
+ # challenging because we are using a custom `__class_getitem__` to parametrize generic models,
215
+ # and not returning a typing._GenericAlias from it.
216
+ bases_str = ', '.join([x.__name__ for x in bases] + [generic_type_label])
217
+ error_message += (
218
+ f' Note: `typing.Generic` must go last: `class {cls.__name__}({bases_str}): ...`)'
219
+ )
220
+ raise TypeError(error_message)
221
+
222
+ cls.__pydantic_generic_metadata__ = {
223
+ 'origin': None,
224
+ 'args': (),
225
+ 'parameters': parameters,
226
+ }
227
+
228
+ cls.__pydantic_complete__ = False # Ensure this specific class gets completed
229
+
230
+ # preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487
231
+ # for attributes not in `new_namespace` (e.g. private attributes)
232
+ for name, obj in private_attributes.items():
233
+ obj.__set_name__(cls, name)
234
+
235
+ if __pydantic_reset_parent_namespace__:
236
+ cls.__pydantic_parent_namespace__ = build_lenient_weakvaluedict(parent_frame_namespace())
237
+ parent_namespace: dict[str, Any] | None = getattr(cls, '__pydantic_parent_namespace__', None)
238
+ if isinstance(parent_namespace, dict):
239
+ parent_namespace = unpack_lenient_weakvaluedict(parent_namespace)
240
+
241
+ ns_resolver = NsResolver(parent_namespace=parent_namespace)
242
+
243
+ set_model_fields(cls, config_wrapper=config_wrapper, ns_resolver=ns_resolver)
244
+
245
+ # This is also set in `complete_model_class()`, after schema gen because they are recreated.
246
+ # We set them here as well for backwards compatibility:
247
+ cls.__pydantic_computed_fields__ = {
248
+ k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items()
249
+ }
250
+
251
+ if config_wrapper.defer_build:
252
+ set_model_mocks(cls)
253
+ else:
254
+ # Any operation that requires accessing the field infos instances should be put inside
255
+ # `complete_model_class()`:
256
+ complete_model_class(
257
+ cls,
258
+ config_wrapper,
259
+ ns_resolver,
260
+ raise_errors=False,
261
+ create_model_module=_create_model_module,
262
+ )
263
+
264
+ if config_wrapper.frozen and '__hash__' not in namespace:
265
+ set_default_hash_func(cls, bases)
266
+
267
+ # using super(cls, cls) on the next line ensures we only call the parent class's __pydantic_init_subclass__
268
+ # I believe the `type: ignore` is only necessary because mypy doesn't realize that this code branch is
269
+ # only hit for _proper_ subclasses of BaseModel
270
+ super(cls, cls).__pydantic_init_subclass__(**kwargs) # type: ignore[misc]
271
+ return cls
272
+ else:
273
+ # These are instance variables, but have been assigned to `NoInitField` to trick the type checker.
274
+ for instance_slot in '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__':
275
+ namespace.pop(
276
+ instance_slot,
277
+ None, # In case the metaclass is used with a class other than `BaseModel`.
278
+ )
279
+ namespace.get('__annotations__', {}).clear()
280
+ return super().__new__(mcs, cls_name, bases, namespace, **kwargs)
281
+
282
+ if not TYPE_CHECKING: # pragma: no branch
283
+ # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access
284
+
285
+ def __getattr__(self, item: str) -> Any:
286
+ """This is necessary to keep attribute access working for class attribute access."""
287
+ private_attributes = self.__dict__.get('__private_attributes__')
288
+ if private_attributes and item in private_attributes:
289
+ return private_attributes[item]
290
+ raise AttributeError(item)
291
+
292
+ @classmethod
293
+ def __prepare__(cls, *args: Any, **kwargs: Any) -> dict[str, object]:
294
+ return _ModelNamespaceDict()
295
+
296
+ # Due to performance and memory issues, in the ABCMeta.__subclasscheck__ implementation, we don't support
297
+ # registered virtual subclasses. See https://github.com/python/cpython/issues/92810#issuecomment-2762454345.
298
+ # This may change once CPython is fixed (possibly in 3.15), in which case we should conditionally
299
+ # define `register()`.
300
+ def register(self, subclass: type[_T]) -> type[_T]:
301
+ warnings.warn(
302
+ f"For performance reasons, virtual subclasses registered using '{self.__qualname__}.register()' "
303
+ "are not supported in 'isinstance()' and 'issubclass()' checks.",
304
+ stacklevel=2,
305
+ )
306
+ return super().register(subclass)
307
+
308
+ __instancecheck__ = type.__instancecheck__ # pyright: ignore[reportAssignmentType]
309
+ __subclasscheck__ = type.__subclasscheck__ # pyright: ignore[reportAssignmentType]
310
+
311
+ @staticmethod
312
+ def _collect_bases_data(bases: tuple[type[Any], ...]) -> tuple[set[str], set[str], dict[str, ModelPrivateAttr]]:
313
+ BaseModel = import_cached_base_model()
314
+
315
+ field_names: set[str] = set()
316
+ class_vars: set[str] = set()
317
+ private_attributes: dict[str, ModelPrivateAttr] = {}
318
+ for base in bases:
319
+ if issubclass(base, BaseModel) and base is not BaseModel:
320
+ # model_fields might not be defined yet in the case of generics, so we use getattr here:
321
+ field_names.update(getattr(base, '__pydantic_fields__', {}).keys())
322
+ class_vars.update(base.__class_vars__)
323
+ private_attributes.update(base.__private_attributes__)
324
+ return field_names, class_vars, private_attributes
325
+
326
+ @property
327
+ @deprecated(
328
+ 'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.', category=None
329
+ )
330
+ def __fields__(self) -> dict[str, FieldInfo]:
331
+ warnings.warn(
332
+ 'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.',
333
+ PydanticDeprecatedSince20,
334
+ stacklevel=2,
335
+ )
336
+ return getattr(self, '__pydantic_fields__', {})
337
+
338
+ @property
339
+ def __pydantic_fields_complete__(self) -> bool:
340
+ """Whether the fields were successfully collected (i.e. type hints were successfully resolved).
341
+
342
+ This is a private attribute, not meant to be used outside Pydantic.
343
+ """
344
+ if '__pydantic_fields__' not in self.__dict__:
345
+ return False
346
+
347
+ field_infos = cast('dict[str, FieldInfo]', self.__pydantic_fields__) # pyright: ignore[reportAttributeAccessIssue]
348
+
349
+ pydantic_extra_info = cast('PydanticExtraInfo | None', self.__pydantic_extra_info__) # pyright: ignore[reportAttributeAccessIssue]
350
+ if pydantic_extra_info is not None:
351
+ extra_complete = pydantic_extra_info.complete
352
+ else:
353
+ extra_complete = True
354
+
355
+ return all(field_info._complete for field_info in field_infos.values()) and extra_complete
356
+
357
+ def __dir__(self) -> list[str]:
358
+ attributes = list(super().__dir__())
359
+ if '__fields__' in attributes:
360
+ attributes.remove('__fields__')
361
+ return attributes
362
+
363
+
364
+ def init_private_attributes(self: BaseModel, context: Any, /) -> None:
365
+ """This function is meant to behave like a BaseModel method to initialize private attributes.
366
+
367
+ It takes context as an argument since that's what pydantic-core passes when calling it.
368
+
369
+ Args:
370
+ self: The BaseModel instance.
371
+ context: The context.
372
+ """
373
+ if getattr(self, '__pydantic_private__', None) is None:
374
+ pydantic_private = {}
375
+ for name, private_attr in self.__private_attributes__.items():
376
+ # Avoid needlessly creating a new dict for the validated data:
377
+ if private_attr.default_factory_takes_validated_data:
378
+ default = private_attr.get_default(
379
+ call_default_factory=True, validated_data={**self.__dict__, **pydantic_private}
380
+ )
381
+ else:
382
+ default = private_attr.get_default(call_default_factory=True)
383
+ if default is not PydanticUndefined:
384
+ pydantic_private[name] = default
385
+ object_setattr(self, '__pydantic_private__', pydantic_private)
386
+
387
+
388
+ def get_model_post_init(namespace: dict[str, Any], bases: tuple[type[Any], ...]) -> Callable[..., Any] | None:
389
+ """Get the `model_post_init` method from the namespace or the class bases, or `None` if not defined."""
390
+ if 'model_post_init' in namespace:
391
+ return namespace['model_post_init']
392
+
393
+ BaseModel = import_cached_base_model()
394
+
395
+ model_post_init = get_attribute_from_bases(bases, 'model_post_init')
396
+ if model_post_init is not BaseModel.model_post_init:
397
+ return model_post_init
398
+
399
+
400
+ def inspect_namespace( # noqa C901
401
+ namespace: dict[str, Any],
402
+ raw_annotations: dict[str, Any],
403
+ ignored_types: tuple[type[Any], ...],
404
+ base_class_vars: set[str],
405
+ base_class_fields: set[str],
406
+ ) -> dict[str, ModelPrivateAttr]:
407
+ """Iterate over the namespace and:
408
+ * gather private attributes
409
+ * check for items which look like fields but are not (e.g. have no annotation) and warn.
410
+
411
+ Args:
412
+ namespace: The attribute dictionary of the class to be created.
413
+ raw_annotations: The (non-evaluated) annotations of the model.
414
+ ignored_types: A tuple of ignore types.
415
+ base_class_vars: A set of base class class variables.
416
+ base_class_fields: A set of base class fields.
417
+
418
+ Returns:
419
+ A dict containing private attributes info.
420
+
421
+ Raises:
422
+ TypeError: If there is a `__root__` field in model.
423
+ NameError: If private attribute name is invalid.
424
+ PydanticUserError:
425
+ - If a field does not have a type annotation.
426
+ - If a field on base class was overridden by a non-annotated attribute.
427
+ """
428
+ from ..fields import ModelPrivateAttr, PrivateAttr
429
+
430
+ FieldInfo = import_cached_field_info()
431
+
432
+ all_ignored_types = ignored_types + default_ignored_types()
433
+
434
+ private_attributes: dict[str, ModelPrivateAttr] = {}
435
+
436
+ if '__root__' in raw_annotations or '__root__' in namespace:
437
+ raise TypeError("To define root models, use `pydantic.RootModel` rather than a field called '__root__'")
438
+
439
+ ignored_names: set[str] = set()
440
+ for var_name, value in list(namespace.items()):
441
+ if var_name == 'model_config' or var_name == '__pydantic_extra__':
442
+ continue
443
+ elif (
444
+ isinstance(value, type)
445
+ and value.__module__ == namespace['__module__']
446
+ and '__qualname__' in namespace
447
+ and value.__qualname__.startswith(f'{namespace["__qualname__"]}.')
448
+ ):
449
+ # `value` is a nested type defined in this namespace; don't error
450
+ continue
451
+ elif isinstance(value, all_ignored_types) or value.__class__.__module__ == 'functools':
452
+ ignored_names.add(var_name)
453
+ continue
454
+ elif isinstance(value, ModelPrivateAttr):
455
+ if var_name.startswith('__'):
456
+ raise NameError(
457
+ 'Private attributes must not use dunder names;'
458
+ f' use a single underscore prefix instead of {var_name!r}.'
459
+ )
460
+ elif is_valid_field_name(var_name):
461
+ raise NameError(
462
+ 'Private attributes must not use valid field names;'
463
+ f' use sunder names, e.g. {"_" + var_name!r} instead of {var_name!r}.'
464
+ )
465
+ private_attributes[var_name] = value
466
+ del namespace[var_name]
467
+ elif isinstance(value, FieldInfo) and not is_valid_field_name(var_name):
468
+ suggested_name = var_name.lstrip('_') or 'my_field' # don't suggest '' for all-underscore name
469
+ raise NameError(
470
+ f'Fields must not use names with leading underscores;'
471
+ f' e.g., use {suggested_name!r} instead of {var_name!r}.'
472
+ )
473
+
474
+ elif var_name.startswith('__'):
475
+ continue
476
+ elif is_valid_privateattr_name(var_name):
477
+ if var_name not in raw_annotations or not is_classvar_annotation(raw_annotations[var_name]):
478
+ private_attributes[var_name] = cast(ModelPrivateAttr, PrivateAttr(default=value))
479
+ del namespace[var_name]
480
+ elif var_name in base_class_vars:
481
+ continue
482
+ elif var_name not in raw_annotations:
483
+ if var_name in base_class_fields:
484
+ raise PydanticUserError(
485
+ f'Field {var_name!r} defined on a base class was overridden by a non-annotated attribute. '
486
+ f'All field definitions, including overrides, require a type annotation.',
487
+ code='model-field-overridden',
488
+ )
489
+ elif isinstance(value, FieldInfo):
490
+ raise PydanticUserError(
491
+ f'Field {var_name!r} requires a type annotation', code='model-field-missing-annotation'
492
+ )
493
+ else:
494
+ raise PydanticUserError(
495
+ f'A non-annotated attribute was detected: `{var_name} = {value!r}`. All model fields require a '
496
+ f'type annotation; if `{var_name}` is not meant to be a field, you may be able to resolve this '
497
+ f"error by annotating it as a `ClassVar` or updating `model_config['ignored_types']`.",
498
+ code='model-field-missing-annotation',
499
+ )
500
+
501
+ for ann_name, ann_type in raw_annotations.items():
502
+ if (
503
+ is_valid_privateattr_name(ann_name)
504
+ and ann_name not in private_attributes
505
+ and ann_name not in ignored_names
506
+ # This condition can be a false negative when `ann_type` is stringified,
507
+ # but it is handled in most cases in `set_model_fields`:
508
+ and not is_classvar_annotation(ann_type)
509
+ and ann_type not in all_ignored_types
510
+ and getattr(ann_type, '__module__', None) != 'functools'
511
+ ):
512
+ if isinstance(ann_type, str):
513
+ # Walking up the frames to get the module namespace where the model is defined
514
+ # (as the model class wasn't created yet, we unfortunately can't use `cls.__module__`):
515
+ frame = sys._getframe(2)
516
+ if frame is not None:
517
+ try:
518
+ ann_type = eval_type_backport(
519
+ _make_forward_ref(ann_type, is_argument=False, is_class=True),
520
+ globalns=frame.f_globals,
521
+ localns=frame.f_locals,
522
+ )
523
+ except (NameError, TypeError):
524
+ pass
525
+
526
+ if typing_objects.is_annotated(get_origin(ann_type)):
527
+ _, *metadata = get_args(ann_type)
528
+ private_attr = next((v for v in metadata if isinstance(v, ModelPrivateAttr)), None)
529
+ if private_attr is not None:
530
+ private_attributes[ann_name] = private_attr
531
+ continue
532
+ private_attributes[ann_name] = PrivateAttr()
533
+
534
+ return private_attributes
535
+
536
+
537
+ def set_default_hash_func(cls: type[BaseModel], bases: tuple[type[Any], ...]) -> None:
538
+ base_hash_func = get_attribute_from_bases(bases, '__hash__')
539
+ new_hash_func = make_hash_func(cls)
540
+ if base_hash_func in {None, object.__hash__} or getattr(base_hash_func, '__code__', None) == new_hash_func.__code__:
541
+ # If `__hash__` is some default, we generate a hash function.
542
+ # It will be `None` if not overridden from BaseModel.
543
+ # It may be `object.__hash__` if there is another
544
+ # parent class earlier in the bases which doesn't override `__hash__` (e.g. `typing.Generic`).
545
+ # It may be a value set by `set_default_hash_func` if `cls` is a subclass of another frozen model.
546
+ # In the last case we still need a new hash function to account for new `model_fields`.
547
+ cls.__hash__ = new_hash_func
548
+
549
+
550
+ def make_hash_func(cls: type[BaseModel]) -> Any:
551
+ getter = operator.itemgetter(*cls.__pydantic_fields__.keys()) if cls.__pydantic_fields__ else lambda _: 0
552
+
553
+ def hash_func(self: Any) -> int:
554
+ try:
555
+ return hash(getter(self.__dict__))
556
+ except KeyError:
557
+ # In rare cases (such as when using the deprecated copy method), the __dict__ may not contain
558
+ # all model fields, which is how we can get here.
559
+ # getter(self.__dict__) is much faster than any 'safe' method that accounts for missing keys,
560
+ # and wrapping it in a `try` doesn't slow things down much in the common case.
561
+ return hash(getter(SafeGetItemProxy(self.__dict__)))
562
+
563
+ return hash_func
564
+
565
+
566
+ def set_model_fields(
567
+ cls: type[BaseModel],
568
+ config_wrapper: ConfigWrapper,
569
+ ns_resolver: NsResolver,
570
+ ) -> None:
571
+ """Collect and set `cls.__pydantic_fields__` and `cls.__class_vars__`.
572
+
573
+ Args:
574
+ cls: BaseModel or dataclass.
575
+ config_wrapper: The config wrapper instance.
576
+ ns_resolver: Namespace resolver to use when getting model annotations.
577
+ """
578
+ typevars_map = get_model_typevars_map(cls)
579
+ fields, pydantic_extra_info, class_vars = collect_model_fields(
580
+ cls, config_wrapper, ns_resolver, typevars_map=typevars_map
581
+ )
582
+
583
+ cls.__pydantic_fields__ = fields
584
+ cls.__pydantic_extra_info__ = pydantic_extra_info
585
+ cls.__class_vars__.update(class_vars)
586
+
587
+ for k in class_vars:
588
+ # Class vars should not be private attributes
589
+ # We remove them _here_ and not earlier because we rely on inspecting the class to determine its classvars,
590
+ # but private attributes are determined by inspecting the namespace _prior_ to class creation.
591
+ # In the case that a classvar with a leading-'_' is defined via a ForwardRef (e.g., when using
592
+ # `__future__.annotations`), we want to remove the private attribute which was detected _before_ we knew it
593
+ # evaluated to a classvar
594
+
595
+ value = cls.__private_attributes__.pop(k, None)
596
+ if value is not None and value.default is not PydanticUndefined:
597
+ setattr(cls, k, value.default)
598
+
599
+
600
+ def complete_model_class(
601
+ cls: type[BaseModel],
602
+ config_wrapper: ConfigWrapper,
603
+ ns_resolver: NsResolver,
604
+ *,
605
+ raise_errors: bool = True,
606
+ call_on_complete_hook: bool = True,
607
+ create_model_module: str | None = None,
608
+ is_force_rebuild: bool = False,
609
+ ) -> bool:
610
+ """Finish building a model class.
611
+
612
+ This logic must be called after class has been created since validation functions must be bound
613
+ and `get_type_hints` requires a class object.
614
+
615
+ Args:
616
+ cls: BaseModel or dataclass.
617
+ config_wrapper: The config wrapper instance.
618
+ ns_resolver: The namespace resolver instance to use during schema building.
619
+ raise_errors: Whether to raise errors.
620
+ call_on_complete_hook: Whether to call the `__pydantic_on_complete__` hook.
621
+ create_model_module: The module of the class to be created, if created by `create_model`.
622
+ is_force_rebuild: Whether the model is being force-rebuilt (if True, pre-built serializers and
623
+ validators are not used, to avoid stale references).
624
+
625
+ Returns:
626
+ `True` if the model is successfully completed, else `False`.
627
+
628
+ Raises:
629
+ PydanticUndefinedAnnotation: If PydanticUndefinedAnnotation occurs in __get_pydantic_core_schema__
630
+ and `raise_errors=True`.
631
+ """
632
+ typevars_map = get_model_typevars_map(cls)
633
+
634
+ if not cls.__pydantic_fields_complete__:
635
+ # Note: when coming from `ModelMetaclass.__new__()`, this results in fields being built twice.
636
+ # We do so a second time here so that we can get the ``NameError`` for the specific undefined annotation.
637
+ # Alternatively, we could let `GenerateSchema()` raise the error, but there are cases where incomplete
638
+ # fields are inherited in `collect_model_fields()` and can actually have their annotation resolved in the
639
+ # generate schema process. As we want to avoid having `__pydantic_fields_complete__` set to `False`
640
+ # when `__pydantic_complete__` is `True`, we rebuild here:
641
+ try:
642
+ cls.__pydantic_fields__, cls.__pydantic_extra_info__ = rebuild_model_fields(
643
+ cls,
644
+ config_wrapper=config_wrapper,
645
+ ns_resolver=ns_resolver,
646
+ typevars_map=typevars_map,
647
+ )
648
+ except NameError as e:
649
+ exc = PydanticUndefinedAnnotation.from_name_error(e)
650
+ set_model_mocks(cls, f'`{exc.name}`')
651
+ if raise_errors:
652
+ raise exc from e
653
+
654
+ if not raise_errors and not cls.__pydantic_fields_complete__:
655
+ # No need to continue with schema gen, it is guaranteed to fail
656
+ return False
657
+
658
+ assert cls.__pydantic_fields_complete__
659
+
660
+ gen_schema = GenerateSchema(
661
+ config_wrapper,
662
+ ns_resolver,
663
+ typevars_map,
664
+ )
665
+
666
+ try:
667
+ schema = gen_schema.generate_schema(cls)
668
+ except PydanticUndefinedAnnotation as e:
669
+ if raise_errors:
670
+ raise
671
+ set_model_mocks(cls, f'`{e.name}`')
672
+ return False
673
+
674
+ core_config = config_wrapper.core_config(title=cls.__name__)
675
+
676
+ try:
677
+ schema = gen_schema.clean_schema(schema)
678
+ except InvalidSchemaError:
679
+ set_model_mocks(cls)
680
+ return False
681
+
682
+ # This needs to happen *after* model schema generation, as the return types
683
+ # of the properties are evaluated and the `ComputedFieldInfo` are recreated:
684
+ cls.__pydantic_computed_fields__ = {k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items()}
685
+
686
+ set_deprecated_descriptors(cls)
687
+
688
+ cls.__pydantic_core_schema__ = schema
689
+
690
+ cls.__pydantic_validator__ = create_schema_validator(
691
+ schema,
692
+ cls,
693
+ create_model_module or cls.__module__,
694
+ cls.__qualname__,
695
+ 'create_model' if create_model_module else 'BaseModel',
696
+ core_config,
697
+ config_wrapper.plugin_settings,
698
+ _use_prebuilt=not is_force_rebuild,
699
+ )
700
+ cls.__pydantic_serializer__ = SchemaSerializer(schema, core_config, _use_prebuilt=not is_force_rebuild)
701
+
702
+ # set __signature__ attr only for model class, but not for its instances
703
+ # (because instances can define `__call__`, and `inspect.signature` shouldn't
704
+ # use the `__signature__` attribute and instead generate from `__call__`).
705
+ cls.__signature__ = LazyClassAttribute(
706
+ '__signature__',
707
+ partial(
708
+ generate_pydantic_signature,
709
+ init=cls.__init__,
710
+ fields=cls.__pydantic_fields__,
711
+ validate_by_name=config_wrapper.validate_by_name,
712
+ extra=config_wrapper.extra,
713
+ ),
714
+ )
715
+
716
+ cls.__pydantic_complete__ = True
717
+
718
+ if call_on_complete_hook:
719
+ cls.__pydantic_on_complete__()
720
+
721
+ return True
722
+
723
+
724
+ def set_deprecated_descriptors(cls: type[BaseModel]) -> None:
725
+ """Set data descriptors on the class for deprecated fields."""
726
+ for field, field_info in cls.__pydantic_fields__.items():
727
+ if (msg := field_info.deprecation_message) is not None:
728
+ desc = _DeprecatedFieldDescriptor(msg)
729
+ desc.__set_name__(cls, field)
730
+ setattr(cls, field, desc)
731
+
732
+ for field, computed_field_info in cls.__pydantic_computed_fields__.items():
733
+ if (
734
+ (msg := computed_field_info.deprecation_message) is not None
735
+ # Avoid having two warnings emitted:
736
+ and not hasattr(unwrap_wrapped_function(computed_field_info.wrapped_property), '__deprecated__')
737
+ ):
738
+ desc = _DeprecatedFieldDescriptor(msg, computed_field_info.wrapped_property)
739
+ desc.__set_name__(cls, field)
740
+ setattr(cls, field, desc)
741
+
742
+
743
+ class _DeprecatedFieldDescriptor:
744
+ """Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
745
+
746
+ Attributes:
747
+ msg: The deprecation message to be emitted.
748
+ wrapped_property: The property instance if the deprecated field is a computed field, or `None`.
749
+ field_name: The name of the field being deprecated.
750
+ """
751
+
752
+ field_name: str
753
+
754
+ def __init__(self, msg: str, wrapped_property: property | None = None) -> None:
755
+ self.msg = msg
756
+ self.wrapped_property = wrapped_property
757
+
758
+ def __set_name__(self, cls: type[BaseModel], name: str) -> None:
759
+ self.field_name = name
760
+
761
+ def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
762
+ if obj is None:
763
+ if self.wrapped_property is not None:
764
+ return self.wrapped_property.__get__(None, obj_type)
765
+ raise AttributeError(self.field_name)
766
+
767
+ warnings.warn(self.msg, DeprecationWarning, stacklevel=2)
768
+
769
+ if self.wrapped_property is not None:
770
+ return self.wrapped_property.__get__(obj, obj_type)
771
+ return obj.__dict__[self.field_name]
772
+
773
+ # Defined to make it a data descriptor and take precedence over the instance's dictionary.
774
+ # Note that it will not be called when setting a value on a model instance
775
+ # as `BaseModel.__setattr__` is defined and takes priority.
776
+ def __set__(self, obj: Any, value: Any) -> NoReturn:
777
+ raise AttributeError(self.field_name)
778
+
779
+
780
+ class _PydanticWeakRef:
781
+ """Wrapper for `weakref.ref` that enables `pickle` serialization.
782
+
783
+ Cloudpickle fails to serialize weakref.ref objects due to an arcane error related to
784
+ to abstract base classes (`abc.ABC`). This class works around the issue by wrapping
785
+ `weakref.ref` instead of subclassing it.
786
+
787
+ See https://github.com/pydantic/pydantic/issues/6763 for context.
788
+
789
+ Semantics:
790
+ - If not pickled, behaves the same as a `weakref.ref`.
791
+ - If pickled along with the referenced object, the same `weakref.ref` behavior
792
+ will be maintained between them after unpickling.
793
+ - If pickled without the referenced object, after unpickling the underlying
794
+ reference will be cleared (`__call__` will always return `None`).
795
+ """
796
+
797
+ def __init__(self, obj: Any):
798
+ if obj is None:
799
+ # The object will be `None` upon deserialization if the serialized weakref
800
+ # had lost its underlying object.
801
+ self._wr = None
802
+ else:
803
+ self._wr = weakref.ref(obj)
804
+
805
+ def __call__(self) -> Any:
806
+ if self._wr is None:
807
+ return None
808
+ else:
809
+ return self._wr()
810
+
811
+ def __reduce__(self) -> tuple[Callable, tuple[weakref.ReferenceType | None]]:
812
+ return _PydanticWeakRef, (self(),)
813
+
814
+
815
+ def build_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None:
816
+ """Takes an input dictionary, and produces a new value that (invertibly) replaces the values with weakrefs.
817
+
818
+ We can't just use a WeakValueDictionary because many types (including int, str, etc.) can't be stored as values
819
+ in a WeakValueDictionary.
820
+
821
+ The `unpack_lenient_weakvaluedict` function can be used to reverse this operation.
822
+ """
823
+ if d is None:
824
+ return None
825
+ result = {}
826
+ for k, v in d.items():
827
+ try:
828
+ proxy = _PydanticWeakRef(v)
829
+ except TypeError:
830
+ proxy = v
831
+ result[k] = proxy
832
+ return result
833
+
834
+
835
+ def unpack_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None:
836
+ """Inverts the transform performed by `build_lenient_weakvaluedict`."""
837
+ if d is None:
838
+ return None
839
+
840
+ result = {}
841
+ for k, v in d.items():
842
+ if isinstance(v, _PydanticWeakRef):
843
+ v = v()
844
+ if v is not None:
845
+ result[k] = v
846
+ else:
847
+ result[k] = v
848
+ return result
849
+
850
+
851
+ @cache
852
+ def default_ignored_types() -> tuple[type[Any], ...]:
853
+ from ..fields import ComputedFieldInfo
854
+
855
+ ignored_types = [
856
+ FunctionType,
857
+ property,
858
+ classmethod,
859
+ staticmethod,
860
+ PydanticDescriptorProxy,
861
+ ComputedFieldInfo,
862
+ TypeAliasType, # from `typing_extensions`
863
+ ]
864
+
865
+ if sys.version_info >= (3, 12):
866
+ ignored_types.append(typing.TypeAliasType)
867
+
868
+ return tuple(ignored_types)
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_namespace_utils.py ADDED
@@ -0,0 +1,293 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from collections.abc import Generator, Iterator, Mapping
5
+ from contextlib import contextmanager
6
+ from functools import cached_property
7
+ from typing import Any, Callable, NamedTuple, TypeVar
8
+
9
+ from typing_extensions import ParamSpec, TypeAlias, TypeAliasType, TypeVarTuple
10
+
11
+ GlobalsNamespace: TypeAlias = 'dict[str, Any]'
12
+ """A global namespace.
13
+
14
+ In most cases, this is a reference to the `__dict__` attribute of a module.
15
+ This namespace type is expected as the `globals` argument during annotations evaluation.
16
+ """
17
+
18
+ MappingNamespace: TypeAlias = Mapping[str, Any]
19
+ """Any kind of namespace.
20
+
21
+ In most cases, this is a local namespace (e.g. the `__dict__` attribute of a class,
22
+ the [`f_locals`][frame.f_locals] attribute of a frame object, when dealing with types
23
+ defined inside functions).
24
+ This namespace type is expected as the `locals` argument during annotations evaluation.
25
+ """
26
+
27
+ _TypeVarLike: TypeAlias = 'TypeVar | ParamSpec | TypeVarTuple'
28
+
29
+
30
+ class NamespacesTuple(NamedTuple):
31
+ """A tuple of globals and locals to be used during annotations evaluation.
32
+
33
+ This datastructure is defined as a named tuple so that it can easily be unpacked:
34
+
35
+ ```python {lint="skip" test="skip"}
36
+ def eval_type(typ: type[Any], ns: NamespacesTuple) -> None:
37
+ return eval(typ, *ns)
38
+ ```
39
+ """
40
+
41
+ globals: GlobalsNamespace
42
+ """The namespace to be used as the `globals` argument during annotations evaluation."""
43
+
44
+ locals: MappingNamespace
45
+ """The namespace to be used as the `locals` argument during annotations evaluation."""
46
+
47
+
48
+ def get_module_ns_of(obj: Any) -> dict[str, Any]:
49
+ """Get the namespace of the module where the object is defined.
50
+
51
+ Caution: this function does not return a copy of the module namespace, so the result
52
+ should not be mutated. The burden of enforcing this is on the caller.
53
+ """
54
+ module_name = getattr(obj, '__module__', None)
55
+ if module_name:
56
+ try:
57
+ return sys.modules[module_name].__dict__
58
+ except KeyError:
59
+ # happens occasionally, see https://github.com/pydantic/pydantic/issues/2363
60
+ return {}
61
+ return {}
62
+
63
+
64
+ # Note that this class is almost identical to `collections.ChainMap`, but need to enforce
65
+ # immutable mappings here:
66
+ class LazyLocalNamespace(Mapping[str, Any]):
67
+ """A lazily evaluated mapping, to be used as the `locals` argument during annotations evaluation.
68
+
69
+ While the [`eval`][eval] function expects a mapping as the `locals` argument, it only
70
+ performs `__getitem__` calls. The [`Mapping`][collections.abc.Mapping] abstract base class
71
+ is fully implemented only for type checking purposes.
72
+
73
+ Args:
74
+ *namespaces: The namespaces to consider, in ascending order of priority.
75
+
76
+ Example:
77
+ ```python {lint="skip" test="skip"}
78
+ ns = LazyLocalNamespace({'a': 1, 'b': 2}, {'a': 3})
79
+ ns['a']
80
+ #> 3
81
+ ns['b']
82
+ #> 2
83
+ ```
84
+ """
85
+
86
+ def __init__(self, *namespaces: MappingNamespace) -> None:
87
+ self._namespaces = namespaces
88
+
89
+ @cached_property
90
+ def data(self) -> dict[str, Any]:
91
+ return {k: v for ns in self._namespaces for k, v in ns.items()}
92
+
93
+ def __len__(self) -> int:
94
+ return len(self.data)
95
+
96
+ def __getitem__(self, key: str) -> Any:
97
+ return self.data[key]
98
+
99
+ def __contains__(self, key: object) -> bool:
100
+ return key in self.data
101
+
102
+ def __iter__(self) -> Iterator[str]:
103
+ return iter(self.data)
104
+
105
+
106
+ def ns_for_function(obj: Callable[..., Any], parent_namespace: MappingNamespace | None = None) -> NamespacesTuple:
107
+ """Return the global and local namespaces to be used when evaluating annotations for the provided function.
108
+
109
+ The global namespace will be the `__dict__` attribute of the module the function was defined in.
110
+ The local namespace will contain the `__type_params__` introduced by PEP 695.
111
+
112
+ Args:
113
+ obj: The object to use when building namespaces.
114
+ parent_namespace: Optional namespace to be added with the lowest priority in the local namespace.
115
+ If the passed function is a method, the `parent_namespace` will be the namespace of the class
116
+ the method is defined in. Thus, we also fetch type `__type_params__` from there (i.e. the
117
+ class-scoped type variables).
118
+ """
119
+ locals_list: list[MappingNamespace] = []
120
+ if parent_namespace is not None:
121
+ locals_list.append(parent_namespace)
122
+
123
+ # Get the `__type_params__` attribute introduced by PEP 695.
124
+ # Note that the `typing._eval_type` function expects type params to be
125
+ # passed as a separate argument. However, internally, `_eval_type` calls
126
+ # `ForwardRef._evaluate` which will merge type params with the localns,
127
+ # essentially mimicking what we do here.
128
+ type_params: tuple[_TypeVarLike, ...] = getattr(obj, '__type_params__', ())
129
+ if parent_namespace is not None:
130
+ # We also fetch type params from the parent namespace. If present, it probably
131
+ # means the function was defined in a class. This is to support the following:
132
+ # https://github.com/python/cpython/issues/124089.
133
+ type_params += parent_namespace.get('__type_params__', ())
134
+
135
+ locals_list.append({t.__name__: t for t in type_params})
136
+
137
+ # What about short-circuiting to `obj.__globals__`?
138
+ globalns = get_module_ns_of(obj)
139
+
140
+ return NamespacesTuple(globalns, LazyLocalNamespace(*locals_list))
141
+
142
+
143
+ class NsResolver:
144
+ """A class responsible for the namespaces resolving logic for annotations evaluation.
145
+
146
+ This class handles the namespace logic when evaluating annotations mainly for class objects.
147
+
148
+ It holds a stack of classes that are being inspected during the core schema building,
149
+ and the `types_namespace` property exposes the globals and locals to be used for
150
+ type annotation evaluation. Additionally -- if no class is present in the stack -- a
151
+ fallback globals and locals can be provided using the `namespaces_tuple` argument
152
+ (this is useful when generating a schema for a simple annotation, e.g. when using
153
+ `TypeAdapter`).
154
+
155
+ The namespace creation logic is unfortunately flawed in some cases, for backwards
156
+ compatibility reasons and to better support valid edge cases. See the description
157
+ for the `parent_namespace` argument and the example for more details.
158
+
159
+ Args:
160
+ namespaces_tuple: The default globals and locals to use if no class is present
161
+ on the stack. This can be useful when using the `GenerateSchema` class
162
+ with `TypeAdapter`, where the "type" being analyzed is a simple annotation.
163
+ parent_namespace: An optional parent namespace that will be added to the locals
164
+ with the lowest priority. For a given class defined in a function, the locals
165
+ of this function are usually used as the parent namespace:
166
+
167
+ ```python {lint="skip" test="skip"}
168
+ from pydantic import BaseModel
169
+
170
+ def func() -> None:
171
+ SomeType = int
172
+
173
+ class Model(BaseModel):
174
+ f: 'SomeType'
175
+
176
+ # when collecting fields, an namespace resolver instance will be created
177
+ # this way:
178
+ # ns_resolver = NsResolver(parent_namespace={'SomeType': SomeType})
179
+ ```
180
+
181
+ For backwards compatibility reasons and to support valid edge cases, this parent
182
+ namespace will be used for *every* type being pushed to the stack. In the future,
183
+ we might want to be smarter by only doing so when the type being pushed is defined
184
+ in the same module as the parent namespace.
185
+
186
+ Example:
187
+ ```python {lint="skip" test="skip"}
188
+ ns_resolver = NsResolver(
189
+ parent_namespace={'fallback': 1},
190
+ )
191
+
192
+ class Sub:
193
+ m: 'Model'
194
+
195
+ class Model:
196
+ some_local = 1
197
+ sub: Sub
198
+
199
+ ns_resolver = NsResolver()
200
+
201
+ # This is roughly what happens when we build a core schema for `Model`:
202
+ with ns_resolver.push(Model):
203
+ ns_resolver.types_namespace
204
+ #> NamespacesTuple({'Sub': Sub}, {'Model': Model, 'some_local': 1})
205
+ # First thing to notice here, the model being pushed is added to the locals.
206
+ # Because `NsResolver` is being used during the model definition, it is not
207
+ # yet added to the globals. This is useful when resolving self-referencing annotations.
208
+
209
+ with ns_resolver.push(Sub):
210
+ ns_resolver.types_namespace
211
+ #> NamespacesTuple({'Sub': Sub}, {'Sub': Sub, 'Model': Model})
212
+ # Second thing to notice: `Sub` is present in both the globals and locals.
213
+ # This is not an issue, just that as described above, the model being pushed
214
+ # is added to the locals, but it happens to be present in the globals as well
215
+ # because it is already defined.
216
+ # Third thing to notice: `Model` is also added in locals. This is a backwards
217
+ # compatibility workaround that allows for `Sub` to be able to resolve `'Model'`
218
+ # correctly (as otherwise models would have to be rebuilt even though this
219
+ # doesn't look necessary).
220
+ ```
221
+ """
222
+
223
+ def __init__(
224
+ self,
225
+ namespaces_tuple: NamespacesTuple | None = None,
226
+ parent_namespace: MappingNamespace | None = None,
227
+ ) -> None:
228
+ self._base_ns_tuple = namespaces_tuple or NamespacesTuple({}, {})
229
+ self._parent_ns = parent_namespace
230
+ self._types_stack: list[type[Any] | TypeAliasType] = []
231
+
232
+ @cached_property
233
+ def types_namespace(self) -> NamespacesTuple:
234
+ """The current global and local namespaces to be used for annotations evaluation."""
235
+ if not self._types_stack:
236
+ # TODO: should we merge the parent namespace here?
237
+ # This is relevant for TypeAdapter, where there are no types on the stack, and we might
238
+ # need access to the parent_ns. Right now, we sidestep this in `type_adapter.py` by passing
239
+ # locals to both parent_ns and the base_ns_tuple, but this is a bit hacky.
240
+ # we might consider something like:
241
+ # if self._parent_ns is not None:
242
+ # # Hacky workarounds, see class docstring:
243
+ # # An optional parent namespace that will be added to the locals with the lowest priority
244
+ # locals_list: list[MappingNamespace] = [self._parent_ns, self._base_ns_tuple.locals]
245
+ # return NamespacesTuple(self._base_ns_tuple.globals, LazyLocalNamespace(*locals_list))
246
+ return self._base_ns_tuple
247
+
248
+ typ = self._types_stack[-1]
249
+
250
+ globalns = get_module_ns_of(typ)
251
+
252
+ locals_list: list[MappingNamespace] = []
253
+ # Hacky workarounds, see class docstring:
254
+ # An optional parent namespace that will be added to the locals with the lowest priority
255
+ if self._parent_ns is not None:
256
+ locals_list.append(self._parent_ns)
257
+ if len(self._types_stack) > 1:
258
+ first_type = self._types_stack[0]
259
+ locals_list.append({first_type.__name__: first_type})
260
+
261
+ # Adding `__type_params__` *before* `vars(typ)`, as the latter takes priority
262
+ # (see https://github.com/python/cpython/pull/120272).
263
+ # TODO `typ.__type_params__` when we drop support for Python 3.11:
264
+ type_params: tuple[_TypeVarLike, ...] = getattr(typ, '__type_params__', ())
265
+ if type_params:
266
+ # Adding `__type_params__` is mostly useful for generic classes defined using
267
+ # PEP 695 syntax *and* using forward annotations (see the example in
268
+ # https://github.com/python/cpython/issues/114053). For TypeAliasType instances,
269
+ # it is way less common, but still required if using a string annotation in the alias
270
+ # value, e.g. `type A[T] = 'T'` (which is not necessary in most cases).
271
+ locals_list.append({t.__name__: t for t in type_params})
272
+
273
+ # TypeAliasType instances don't have a `__dict__` attribute, so the check
274
+ # is necessary:
275
+ if hasattr(typ, '__dict__'):
276
+ locals_list.append(vars(typ))
277
+
278
+ # The `len(self._types_stack) > 1` check above prevents this from being added twice:
279
+ locals_list.append({typ.__name__: typ})
280
+
281
+ return NamespacesTuple(globalns, LazyLocalNamespace(*locals_list))
282
+
283
+ @contextmanager
284
+ def push(self, typ: type[Any] | TypeAliasType, /) -> Generator[None]:
285
+ """Push a type to the stack."""
286
+ self._types_stack.append(typ)
287
+ # Reset the cached property:
288
+ self.__dict__.pop('types_namespace', None)
289
+ try:
290
+ yield
291
+ finally:
292
+ self._types_stack.pop()
293
+ self.__dict__.pop('types_namespace', None)
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_repr.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tools to provide pretty/human-readable display of objects."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ import types
6
+ from collections.abc import Callable, Collection, Generator, Iterable
7
+ from typing import TYPE_CHECKING, Any, ForwardRef, cast
8
+
9
+ import typing_extensions
10
+ from typing_extensions import TypeAlias
11
+ from typing_inspection import typing_objects
12
+ from typing_inspection.introspection import is_union_origin
13
+
14
+ from . import _typing_extra
15
+
16
+ if TYPE_CHECKING:
17
+ # TODO remove type error comments when we drop support for Python 3.9
18
+ ReprArgs: TypeAlias = Iterable[tuple[str | None, Any]] # pyright: ignore[reportGeneralTypeIssues]
19
+ RichReprResult: TypeAlias = Iterable[Any | tuple[Any] | tuple[str, Any] | tuple[str, Any, Any]] # pyright: ignore[reportGeneralTypeIssues]
20
+
21
+
22
+ class PlainRepr(str):
23
+ """String class where repr doesn't include quotes. Useful with Representation when you want to return a string
24
+ representation of something that is valid (or pseudo-valid) python.
25
+ """
26
+
27
+ def __repr__(self) -> str:
28
+ return str(self)
29
+
30
+
31
+ class Representation:
32
+ # Mixin to provide `__str__`, `__repr__`, and `__pretty__` and `__rich_repr__` methods.
33
+ # `__pretty__` is used by [devtools](https://python-devtools.helpmanual.io/).
34
+ # `__rich_repr__` is used by [rich](https://rich.readthedocs.io/en/stable/pretty.html).
35
+ # (this is not a docstring to avoid adding a docstring to classes which inherit from Representation)
36
+
37
+ __slots__ = ()
38
+
39
+ def __repr_args__(self) -> ReprArgs:
40
+ """Returns the attributes to show in __str__, __repr__, and __pretty__ this is generally overridden.
41
+
42
+ Can either return:
43
+ * name - value pairs, e.g.: `[('foo_name', 'foo'), ('bar_name', ['b', 'a', 'r'])]`
44
+ * or, just values, e.g.: `[(None, 'foo'), (None, ['b', 'a', 'r'])]`
45
+ """
46
+ attrs_names = cast(Collection[str], self.__slots__)
47
+ if not attrs_names and hasattr(self, '__dict__'):
48
+ attrs_names = self.__dict__.keys()
49
+ attrs = ((s, getattr(self, s)) for s in attrs_names)
50
+ return [(a, v if v is not self else self.__repr_recursion__(v)) for a, v in attrs if v is not None]
51
+
52
+ def __repr_name__(self) -> str:
53
+ """Name of the instance's class, used in __repr__."""
54
+ return self.__class__.__name__
55
+
56
+ def __repr_recursion__(self, object: Any) -> str:
57
+ """Returns the string representation of a recursive object."""
58
+ # This is copied over from the stdlib `pprint` module:
59
+ return f'<Recursion on {type(object).__name__} with id={id(object)}>'
60
+
61
+ def __repr_str__(self, join_str: str) -> str:
62
+ return join_str.join(repr(v) if a is None else f'{a}={v!r}' for a, v in self.__repr_args__())
63
+
64
+ def __pretty__(self, fmt: Callable[[Any], Any], **kwargs: Any) -> Generator[Any]:
65
+ """Used by devtools (https://python-devtools.helpmanual.io/) to pretty print objects."""
66
+ yield self.__repr_name__() + '('
67
+ yield 1
68
+ for name, value in self.__repr_args__():
69
+ if name is not None:
70
+ yield name + '='
71
+ yield fmt(value)
72
+ yield ','
73
+ yield 0
74
+ yield -1
75
+ yield ')'
76
+
77
+ def __rich_repr__(self) -> RichReprResult:
78
+ """Used by Rich (https://rich.readthedocs.io/en/stable/pretty.html) to pretty print objects."""
79
+ for name, field_repr in self.__repr_args__():
80
+ if name is None:
81
+ yield field_repr
82
+ else:
83
+ yield name, field_repr
84
+
85
+ def __str__(self) -> str:
86
+ return self.__repr_str__(' ')
87
+
88
+ def __repr__(self) -> str:
89
+ return f'{self.__repr_name__()}({self.__repr_str__(", ")})'
90
+
91
+
92
+ def display_as_type(obj: Any) -> str:
93
+ """Pretty representation of a type, should be as close as possible to the original type definition string.
94
+
95
+ Takes some logic from `typing._type_repr`.
96
+ """
97
+ if isinstance(obj, (types.FunctionType, types.BuiltinFunctionType)):
98
+ return obj.__name__
99
+ elif obj is ...:
100
+ return '...'
101
+ elif isinstance(obj, Representation):
102
+ return repr(obj)
103
+ elif isinstance(obj, ForwardRef) or typing_objects.is_typealiastype(obj):
104
+ return str(obj)
105
+
106
+ if not isinstance(obj, (_typing_extra.typing_base, _typing_extra.WithArgsTypes, type)):
107
+ obj = obj.__class__
108
+
109
+ if is_union_origin(typing_extensions.get_origin(obj)):
110
+ args = ', '.join(map(display_as_type, typing_extensions.get_args(obj)))
111
+ return f'Union[{args}]'
112
+ elif isinstance(obj, _typing_extra.WithArgsTypes):
113
+ if typing_objects.is_literal(typing_extensions.get_origin(obj)):
114
+ args = ', '.join(map(repr, typing_extensions.get_args(obj)))
115
+ else:
116
+ args = ', '.join(map(display_as_type, typing_extensions.get_args(obj)))
117
+ try:
118
+ return f'{obj.__qualname__}[{args}]'
119
+ except AttributeError:
120
+ return str(obj).replace('typing.', '').replace('typing_extensions.', '') # handles TypeAliasType in 3.12
121
+ elif isinstance(obj, type):
122
+ return obj.__qualname__
123
+ else:
124
+ return repr(obj).replace('typing.', '').replace('typing_extensions.', '')
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_schema_gather.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # pyright: reportTypedDictNotRequiredAccess=false, reportGeneralTypeIssues=false, reportArgumentType=false, reportAttributeAccessIssue=false
2
+ from __future__ import annotations
3
+
4
+ from dataclasses import dataclass, field
5
+ from typing import TypedDict
6
+
7
+ from pydantic_core.core_schema import (
8
+ ComputedField,
9
+ CoreSchema,
10
+ DefinitionReferenceSchema,
11
+ SerSchema,
12
+ iter_union_choices,
13
+ )
14
+ from typing_extensions import TypeAlias
15
+
16
+ AllSchemas: TypeAlias = 'CoreSchema | SerSchema | ComputedField'
17
+
18
+
19
+ class GatherResult(TypedDict):
20
+ """Schema traversing result."""
21
+
22
+ collected_references: dict[str, DefinitionReferenceSchema | None]
23
+ """The collected definition references.
24
+
25
+ If a definition reference schema can be inlined, it means that there is
26
+ only one in the whole core schema. As such, it is stored as the value.
27
+ Otherwise, the value is set to `None`.
28
+ """
29
+
30
+ deferred_discriminator_schemas: list[CoreSchema]
31
+ """The list of core schemas having the discriminator application deferred."""
32
+
33
+
34
+ class MissingDefinitionError(LookupError):
35
+ """A reference was pointing to a non-existing core schema."""
36
+
37
+ def __init__(self, schema_reference: str, /) -> None:
38
+ self.schema_reference = schema_reference
39
+
40
+
41
+ @dataclass
42
+ class GatherContext:
43
+ """The current context used during core schema traversing.
44
+
45
+ Context instances should only be used during schema traversing.
46
+ """
47
+
48
+ definitions: dict[str, CoreSchema]
49
+ """The available definitions."""
50
+
51
+ deferred_discriminator_schemas: list[CoreSchema] = field(init=False, default_factory=list)
52
+ """The list of core schemas having the discriminator application deferred.
53
+
54
+ Internally, these core schemas have a specific key set in the core metadata dict.
55
+ """
56
+
57
+ collected_references: dict[str, DefinitionReferenceSchema | None] = field(init=False, default_factory=dict)
58
+ """The collected definition references.
59
+
60
+ If a definition reference schema can be inlined, it means that there is
61
+ only one in the whole core schema. As such, it is stored as the value.
62
+ Otherwise, the value is set to `None`.
63
+
64
+ During schema traversing, definition reference schemas can be added as candidates, or removed
65
+ (by setting the value to `None`).
66
+ """
67
+
68
+
69
+ def traverse_metadata(schema: AllSchemas, ctx: GatherContext) -> None:
70
+ meta = schema.get('metadata')
71
+ if meta is not None and 'pydantic_internal_union_discriminator' in meta:
72
+ ctx.deferred_discriminator_schemas.append(schema) # pyright: ignore[reportArgumentType]
73
+
74
+
75
+ def traverse_definition_ref(def_ref_schema: DefinitionReferenceSchema, ctx: GatherContext) -> None:
76
+ schema_ref = def_ref_schema['schema_ref']
77
+
78
+ if schema_ref not in ctx.collected_references:
79
+ definition = ctx.definitions.get(schema_ref)
80
+ if definition is None:
81
+ raise MissingDefinitionError(schema_ref)
82
+
83
+ # The `'definition-ref'` schema was only encountered once, make it
84
+ # a candidate to be inlined:
85
+ ctx.collected_references[schema_ref] = def_ref_schema
86
+ traverse_schema(definition, ctx)
87
+ if 'serialization' in def_ref_schema:
88
+ traverse_schema(def_ref_schema['serialization'], ctx)
89
+ traverse_metadata(def_ref_schema, ctx)
90
+ else:
91
+ # The `'definition-ref'` schema was already encountered, meaning
92
+ # the previously encountered schema (and this one) can't be inlined:
93
+ ctx.collected_references[schema_ref] = None
94
+
95
+
96
+ def traverse_schema(schema: AllSchemas, context: GatherContext) -> None:
97
+ # TODO When we drop 3.9, use a match statement to get better type checking and remove
98
+ # file-level type ignore.
99
+ # (the `'type'` could also be fetched in every `if/elif` statement, but this alters performance).
100
+ schema_type = schema['type']
101
+
102
+ if schema_type == 'definition-ref':
103
+ traverse_definition_ref(schema, context)
104
+ # `traverse_definition_ref` handles the possible serialization and metadata schemas:
105
+ return
106
+ elif schema_type == 'definitions':
107
+ traverse_schema(schema['schema'], context)
108
+ for definition in schema['definitions']:
109
+ traverse_schema(definition, context)
110
+ elif schema_type in {'list', 'set', 'frozenset', 'generator'}:
111
+ if 'items_schema' in schema:
112
+ traverse_schema(schema['items_schema'], context)
113
+ elif schema_type == 'tuple':
114
+ if 'items_schema' in schema:
115
+ for s in schema['items_schema']:
116
+ traverse_schema(s, context)
117
+ elif schema_type == 'dict':
118
+ if 'keys_schema' in schema:
119
+ traverse_schema(schema['keys_schema'], context)
120
+ if 'values_schema' in schema:
121
+ traverse_schema(schema['values_schema'], context)
122
+ elif schema_type == 'union':
123
+ for choice in iter_union_choices(schema):
124
+ traverse_schema(choice, context)
125
+ elif schema_type == 'tagged-union':
126
+ for v in schema['choices'].values():
127
+ traverse_schema(v, context)
128
+ elif schema_type == 'chain':
129
+ for step in schema['steps']:
130
+ traverse_schema(step, context)
131
+ elif schema_type == 'lax-or-strict':
132
+ traverse_schema(schema['lax_schema'], context)
133
+ traverse_schema(schema['strict_schema'], context)
134
+ elif schema_type == 'json-or-python':
135
+ traverse_schema(schema['json_schema'], context)
136
+ traverse_schema(schema['python_schema'], context)
137
+ elif schema_type in {'model-fields', 'typed-dict'}:
138
+ if 'extras_schema' in schema:
139
+ traverse_schema(schema['extras_schema'], context)
140
+ if 'computed_fields' in schema:
141
+ for s in schema['computed_fields']:
142
+ traverse_schema(s, context)
143
+ for s in schema['fields'].values():
144
+ traverse_schema(s, context)
145
+ elif schema_type == 'dataclass-args':
146
+ if 'computed_fields' in schema:
147
+ for s in schema['computed_fields']:
148
+ traverse_schema(s, context)
149
+ for s in schema['fields']:
150
+ traverse_schema(s, context)
151
+ elif schema_type == 'arguments':
152
+ for s in schema['arguments_schema']:
153
+ traverse_schema(s['schema'], context)
154
+ if 'var_args_schema' in schema:
155
+ traverse_schema(schema['var_args_schema'], context)
156
+ if 'var_kwargs_schema' in schema:
157
+ traverse_schema(schema['var_kwargs_schema'], context)
158
+ elif schema_type == 'arguments-v3':
159
+ for s in schema['arguments_schema']:
160
+ traverse_schema(s['schema'], context)
161
+ elif schema_type == 'call':
162
+ traverse_schema(schema['arguments_schema'], context)
163
+ if 'return_schema' in schema:
164
+ traverse_schema(schema['return_schema'], context)
165
+ elif schema_type == 'computed-field':
166
+ traverse_schema(schema['return_schema'], context)
167
+ elif schema_type == 'function-before':
168
+ if 'schema' in schema:
169
+ traverse_schema(schema['schema'], context)
170
+ if 'json_schema_input_schema' in schema:
171
+ traverse_schema(schema['json_schema_input_schema'], context)
172
+ elif schema_type == 'function-plain':
173
+ # TODO duplicate schema types for serializers and validators, needs to be deduplicated.
174
+ if 'return_schema' in schema:
175
+ traverse_schema(schema['return_schema'], context)
176
+ if 'json_schema_input_schema' in schema:
177
+ traverse_schema(schema['json_schema_input_schema'], context)
178
+ elif schema_type == 'function-wrap':
179
+ # TODO duplicate schema types for serializers and validators, needs to be deduplicated.
180
+ if 'return_schema' in schema:
181
+ traverse_schema(schema['return_schema'], context)
182
+ if 'schema' in schema:
183
+ traverse_schema(schema['schema'], context)
184
+ if 'json_schema_input_schema' in schema:
185
+ traverse_schema(schema['json_schema_input_schema'], context)
186
+ else:
187
+ if 'schema' in schema:
188
+ traverse_schema(schema['schema'], context)
189
+
190
+ if 'serialization' in schema:
191
+ traverse_schema(schema['serialization'], context)
192
+ traverse_metadata(schema, context)
193
+
194
+
195
+ def gather_schemas_for_cleaning(schema: CoreSchema, definitions: dict[str, CoreSchema]) -> GatherResult:
196
+ """Traverse the core schema and definitions and return the necessary information for schema cleaning.
197
+
198
+ During the core schema traversing, any `'definition-ref'` schema is:
199
+
200
+ - Validated: the reference must point to an existing definition. If this is not the case, a
201
+ `MissingDefinitionError` exception is raised.
202
+ - Stored in the context: the actual reference is stored in the context. Depending on whether
203
+ the `'definition-ref'` schema is encountered more that once, the schema itself is also
204
+ saved in the context to be inlined (i.e. replaced by the definition it points to).
205
+ """
206
+ context = GatherContext(definitions)
207
+ traverse_schema(schema, context)
208
+
209
+ return {
210
+ 'collected_references': context.collected_references,
211
+ 'deferred_discriminator_schemas': context.deferred_discriminator_schemas,
212
+ }
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_schema_generation_shared.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Types and utility functions used by various other internal tools."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any, Callable, Literal
6
+
7
+ from pydantic_core import core_schema
8
+
9
+ from ..annotated_handlers import GetCoreSchemaHandler, GetJsonSchemaHandler
10
+
11
+ if TYPE_CHECKING:
12
+ from ..json_schema import GenerateJsonSchema, JsonSchemaValue
13
+ from ._core_utils import CoreSchemaOrField
14
+ from ._generate_schema import GenerateSchema
15
+ from ._namespace_utils import NamespacesTuple
16
+
17
+ GetJsonSchemaFunction = Callable[[CoreSchemaOrField, GetJsonSchemaHandler], JsonSchemaValue]
18
+ HandlerOverride = Callable[[CoreSchemaOrField], JsonSchemaValue]
19
+
20
+
21
+ class GenerateJsonSchemaHandler(GetJsonSchemaHandler):
22
+ """JsonSchemaHandler implementation that doesn't do ref unwrapping by default.
23
+
24
+ This is used for any Annotated metadata so that we don't end up with conflicting
25
+ modifications to the definition schema.
26
+
27
+ Used internally by Pydantic, please do not rely on this implementation.
28
+ See `GetJsonSchemaHandler` for the handler API.
29
+ """
30
+
31
+ def __init__(self, generate_json_schema: GenerateJsonSchema, handler_override: HandlerOverride | None) -> None:
32
+ self.generate_json_schema = generate_json_schema
33
+ self.handler = handler_override or generate_json_schema.generate_inner
34
+ self.mode = generate_json_schema.mode
35
+
36
+ def __call__(self, core_schema: CoreSchemaOrField, /) -> JsonSchemaValue:
37
+ return self.handler(core_schema)
38
+
39
+ def resolve_ref_schema(self, maybe_ref_json_schema: JsonSchemaValue) -> JsonSchemaValue:
40
+ """Resolves `$ref` in the json schema.
41
+
42
+ This returns the input json schema if there is no `$ref` in json schema.
43
+
44
+ Args:
45
+ maybe_ref_json_schema: The input json schema that may contains `$ref`.
46
+
47
+ Returns:
48
+ Resolved json schema.
49
+
50
+ Raises:
51
+ LookupError: If it can't find the definition for `$ref`.
52
+ """
53
+ if '$ref' not in maybe_ref_json_schema:
54
+ return maybe_ref_json_schema
55
+ ref = maybe_ref_json_schema['$ref']
56
+ json_schema = self.generate_json_schema.get_schema_from_definitions(ref)
57
+ if json_schema is None:
58
+ raise LookupError(
59
+ f'Could not find a ref for {ref}.'
60
+ ' Maybe you tried to call resolve_ref_schema from within a recursive model?'
61
+ )
62
+ return json_schema
63
+
64
+
65
+ class CallbackGetCoreSchemaHandler(GetCoreSchemaHandler):
66
+ """Wrapper to use an arbitrary function as a `GetCoreSchemaHandler`.
67
+
68
+ Used internally by Pydantic, please do not rely on this implementation.
69
+ See `GetCoreSchemaHandler` for the handler API.
70
+ """
71
+
72
+ def __init__(
73
+ self,
74
+ handler: Callable[[Any], core_schema.CoreSchema],
75
+ generate_schema: GenerateSchema,
76
+ ref_mode: Literal['to-def', 'unpack'] = 'to-def',
77
+ ) -> None:
78
+ self._handler = handler
79
+ self._generate_schema = generate_schema
80
+ self._ref_mode = ref_mode
81
+
82
+ def __call__(self, source_type: Any, /) -> core_schema.CoreSchema:
83
+ schema = self._handler(source_type)
84
+ if self._ref_mode == 'to-def':
85
+ ref = schema.get('ref')
86
+ if ref is not None:
87
+ return self._generate_schema.defs.create_definition_reference_schema(schema)
88
+ return schema
89
+ else: # ref_mode = 'unpack'
90
+ return self.resolve_ref_schema(schema)
91
+
92
+ def _get_types_namespace(self) -> NamespacesTuple:
93
+ return self._generate_schema._types_namespace
94
+
95
+ def generate_schema(self, source_type: Any, /) -> core_schema.CoreSchema:
96
+ return self._generate_schema.generate_schema(source_type)
97
+
98
+ @property
99
+ def field_name(self) -> str | None:
100
+ return self._generate_schema.field_name_stack.get()
101
+
102
+ def resolve_ref_schema(self, maybe_ref_schema: core_schema.CoreSchema) -> core_schema.CoreSchema:
103
+ """Resolves reference in the core schema.
104
+
105
+ Args:
106
+ maybe_ref_schema: The input core schema that may contains reference.
107
+
108
+ Returns:
109
+ Resolved core schema.
110
+
111
+ Raises:
112
+ LookupError: If it can't find the definition for reference.
113
+ """
114
+ if maybe_ref_schema['type'] == 'definition-ref':
115
+ ref = maybe_ref_schema['schema_ref']
116
+ definition = self._generate_schema.defs.get_schema_from_ref(ref)
117
+ if definition is None:
118
+ raise LookupError(
119
+ f'Could not find a ref for {ref}.'
120
+ ' Maybe you tried to call resolve_ref_schema from within a recursive model?'
121
+ )
122
+ return definition
123
+ elif maybe_ref_schema['type'] == 'definitions':
124
+ return self.resolve_ref_schema(maybe_ref_schema['schema'])
125
+ return maybe_ref_schema
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_serializers.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import collections
4
+ import collections.abc
5
+ import typing
6
+ from typing import Any
7
+
8
+ from pydantic_core import PydanticOmit, core_schema
9
+
10
+ SEQUENCE_ORIGIN_MAP: dict[Any, Any] = {
11
+ typing.Deque: collections.deque, # noqa: UP006
12
+ collections.deque: collections.deque,
13
+ list: list,
14
+ typing.List: list, # noqa: UP006
15
+ tuple: tuple,
16
+ typing.Tuple: tuple, # noqa: UP006
17
+ set: set,
18
+ typing.AbstractSet: set,
19
+ typing.Set: set, # noqa: UP006
20
+ frozenset: frozenset,
21
+ typing.FrozenSet: frozenset, # noqa: UP006
22
+ typing.Sequence: list,
23
+ typing.MutableSequence: list,
24
+ typing.MutableSet: set,
25
+ # this doesn't handle subclasses of these
26
+ # parametrized typing.Set creates one of these
27
+ collections.abc.MutableSet: set,
28
+ collections.abc.Set: frozenset,
29
+ }
30
+
31
+
32
+ def serialize_sequence_via_list(
33
+ v: Any, handler: core_schema.SerializerFunctionWrapHandler, info: core_schema.SerializationInfo
34
+ ) -> Any:
35
+ items: list[Any] = []
36
+
37
+ mapped_origin = SEQUENCE_ORIGIN_MAP.get(type(v), None)
38
+ if mapped_origin is None:
39
+ # we shouldn't hit this branch, should probably add a serialization error or something
40
+ return v
41
+
42
+ for index, item in enumerate(v):
43
+ try:
44
+ v = handler(item, index)
45
+ except PydanticOmit: # noqa: PERF203
46
+ pass
47
+ else:
48
+ items.append(v)
49
+
50
+ if info.mode_is_json():
51
+ return items
52
+ else:
53
+ return mapped_origin(items)
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_signature.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ from inspect import Parameter, Signature
5
+ from typing import TYPE_CHECKING, Any, Callable
6
+
7
+ from pydantic_core import PydanticUndefined
8
+
9
+ from ._typing_extra import signature_no_eval
10
+ from ._utils import is_valid_identifier
11
+
12
+ if TYPE_CHECKING:
13
+ from ..config import ExtraValues
14
+ from ..fields import FieldInfo
15
+
16
+
17
+ # Copied over from stdlib dataclasses
18
+ class _HAS_DEFAULT_FACTORY_CLASS:
19
+ def __repr__(self):
20
+ return '<factory>'
21
+
22
+
23
+ _HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS()
24
+
25
+
26
+ def _field_name_for_signature(field_name: str, field_info: FieldInfo) -> str:
27
+ """Extract the correct name to use for the field when generating a signature.
28
+
29
+ Assuming the field has a valid alias, this will return the alias. Otherwise, it will return the field name.
30
+ First priority is given to the alias, then the validation_alias, then the field name.
31
+
32
+ Args:
33
+ field_name: The name of the field
34
+ field_info: The corresponding FieldInfo object.
35
+
36
+ Returns:
37
+ The correct name to use when generating a signature.
38
+ """
39
+ if isinstance(field_info.alias, str) and is_valid_identifier(field_info.alias):
40
+ return field_info.alias
41
+ if isinstance(field_info.validation_alias, str) and is_valid_identifier(field_info.validation_alias):
42
+ return field_info.validation_alias
43
+
44
+ return field_name
45
+
46
+
47
+ def _process_param_defaults(param: Parameter) -> Parameter:
48
+ """Modify the signature for a parameter in a dataclass where the default value is a FieldInfo instance.
49
+
50
+ Args:
51
+ param (Parameter): The parameter
52
+
53
+ Returns:
54
+ Parameter: The custom processed parameter
55
+ """
56
+ from ..fields import FieldInfo
57
+
58
+ param_default = param.default
59
+ if isinstance(param_default, FieldInfo):
60
+ annotation = param.annotation
61
+ # Replace the annotation if appropriate
62
+ # inspect does "clever" things to show annotations as strings because we have
63
+ # `from __future__ import annotations` in main, we don't want that
64
+ if annotation == 'Any':
65
+ annotation = Any
66
+
67
+ # Replace the field default
68
+ default = param_default.default
69
+ if default is PydanticUndefined:
70
+ if param_default.default_factory is None:
71
+ default = Signature.empty
72
+ else:
73
+ # this is used by dataclasses to indicate a factory exists:
74
+ default = dataclasses._HAS_DEFAULT_FACTORY # type: ignore
75
+ return param.replace(
76
+ annotation=annotation, name=_field_name_for_signature(param.name, param_default), default=default
77
+ )
78
+ return param
79
+
80
+
81
+ def _generate_signature_parameters( # noqa: C901 (ignore complexity, could use a refactor)
82
+ init: Callable[..., None],
83
+ fields: dict[str, FieldInfo],
84
+ validate_by_name: bool,
85
+ extra: ExtraValues | None,
86
+ ) -> dict[str, Parameter]:
87
+ """Generate a mapping of parameter names to Parameter objects for a pydantic BaseModel or dataclass."""
88
+ from itertools import islice
89
+
90
+ present_params = signature_no_eval(init).parameters.values()
91
+ merged_params: dict[str, Parameter] = {}
92
+ var_kw = None
93
+ use_var_kw = False
94
+
95
+ for param in islice(present_params, 1, None): # skip self arg
96
+ # inspect does "clever" things to show annotations as strings because we have
97
+ # `from __future__ import annotations` in main, we don't want that
98
+ if fields.get(param.name):
99
+ # exclude params with init=False
100
+ if getattr(fields[param.name], 'init', True) is False:
101
+ continue
102
+ param = param.replace(name=_field_name_for_signature(param.name, fields[param.name]))
103
+ if param.annotation == 'Any':
104
+ param = param.replace(annotation=Any)
105
+ if param.kind is param.VAR_KEYWORD:
106
+ var_kw = param
107
+ continue
108
+ merged_params[param.name] = param
109
+
110
+ if var_kw: # if custom init has no var_kw, fields which are not declared in it cannot be passed through
111
+ allow_names = validate_by_name
112
+ for field_name, field in fields.items():
113
+ # when alias is a str it should be used for signature generation
114
+ param_name = _field_name_for_signature(field_name, field)
115
+
116
+ if field_name in merged_params or param_name in merged_params:
117
+ continue
118
+
119
+ if not is_valid_identifier(param_name):
120
+ if allow_names:
121
+ param_name = field_name
122
+ else:
123
+ use_var_kw = True
124
+ continue
125
+
126
+ if field.is_required():
127
+ default = Parameter.empty
128
+ elif field.default_factory is not None:
129
+ # Mimics stdlib dataclasses:
130
+ default = _HAS_DEFAULT_FACTORY
131
+ else:
132
+ default = field.default
133
+ merged_params[param_name] = Parameter(
134
+ param_name,
135
+ Parameter.KEYWORD_ONLY,
136
+ annotation=field.rebuild_annotation(),
137
+ default=default,
138
+ )
139
+
140
+ if extra == 'allow':
141
+ use_var_kw = True
142
+
143
+ if var_kw and use_var_kw:
144
+ # Make sure the parameter for extra kwargs
145
+ # does not have the same name as a field
146
+ default_model_signature = [
147
+ ('self', Parameter.POSITIONAL_ONLY),
148
+ ('data', Parameter.VAR_KEYWORD),
149
+ ]
150
+ if [(p.name, p.kind) for p in present_params] == default_model_signature:
151
+ # if this is the standard model signature, use extra_data as the extra args name
152
+ var_kw_name = 'extra_data'
153
+ else:
154
+ # else start from var_kw
155
+ var_kw_name = var_kw.name
156
+
157
+ # generate a name that's definitely unique
158
+ while var_kw_name in fields:
159
+ var_kw_name += '_'
160
+ merged_params[var_kw_name] = var_kw.replace(name=var_kw_name)
161
+
162
+ return merged_params
163
+
164
+
165
+ def generate_pydantic_signature(
166
+ init: Callable[..., None],
167
+ fields: dict[str, FieldInfo],
168
+ validate_by_name: bool,
169
+ extra: ExtraValues | None,
170
+ is_dataclass: bool = False,
171
+ ) -> Signature:
172
+ """Generate signature for a pydantic BaseModel or dataclass.
173
+
174
+ Args:
175
+ init: The class init.
176
+ fields: The model fields.
177
+ validate_by_name: The `validate_by_name` value of the config.
178
+ extra: The `extra` value of the config.
179
+ is_dataclass: Whether the model is a dataclass.
180
+
181
+ Returns:
182
+ The dataclass/BaseModel subclass signature.
183
+ """
184
+ merged_params = _generate_signature_parameters(init, fields, validate_by_name, extra)
185
+
186
+ if is_dataclass:
187
+ merged_params = {k: _process_param_defaults(v) for k, v in merged_params.items()}
188
+
189
+ return Signature(parameters=list(merged_params.values()), return_annotation=None)
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_typing_extra.py ADDED
@@ -0,0 +1,785 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Logic for interacting with type annotations, mostly extensions, shims and hacks to wrap Python's typing module."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import collections.abc
6
+ import re
7
+ import sys
8
+ import types
9
+ import typing
10
+ from functools import partial
11
+ from inspect import Signature, signature
12
+ from typing import TYPE_CHECKING, Any, Callable, cast
13
+
14
+ import typing_extensions
15
+ from typing_extensions import deprecated, get_args, get_origin
16
+ from typing_inspection import typing_objects
17
+ from typing_inspection.introspection import is_union_origin
18
+
19
+ from pydantic.version import version_short
20
+
21
+ from ._namespace_utils import GlobalsNamespace, MappingNamespace, NsResolver, get_module_ns_of
22
+
23
+ if sys.version_info < (3, 10):
24
+ NoneType = type(None)
25
+ EllipsisType = type(Ellipsis)
26
+ else:
27
+ from types import EllipsisType as EllipsisType
28
+ from types import NoneType as NoneType
29
+
30
+ if sys.version_info >= (3, 14):
31
+ import annotationlib
32
+
33
+ if TYPE_CHECKING:
34
+ from pydantic import BaseModel
35
+ from pydantic.fields import FieldInfo
36
+
37
+ # As per https://typing-extensions.readthedocs.io/en/latest/#runtime-use-of-types,
38
+ # always check for both `typing` and `typing_extensions` variants of a typing construct.
39
+ # (this is implemented differently than the suggested approach in the `typing_extensions`
40
+ # docs for performance).
41
+
42
+
43
+ _t_annotated = typing.Annotated
44
+ _te_annotated = typing_extensions.Annotated
45
+
46
+
47
+ def is_annotated(tp: Any, /) -> bool:
48
+ """Return whether the provided argument is a `Annotated` special form.
49
+
50
+ ```python {test="skip" lint="skip"}
51
+ is_annotated(Annotated[int, ...])
52
+ #> True
53
+ ```
54
+ """
55
+ origin = get_origin(tp)
56
+ return origin is _t_annotated or origin is _te_annotated
57
+
58
+
59
+ def annotated_type(tp: Any, /) -> Any | None:
60
+ """Return the type of the `Annotated` special form, or `None`."""
61
+ return tp.__origin__ if typing_objects.is_annotated(get_origin(tp)) else None
62
+
63
+
64
+ def unpack_type(tp: Any, /) -> Any | None:
65
+ """Return the type wrapped by the `Unpack` special form, or `None`."""
66
+ return get_args(tp)[0] if typing_objects.is_unpack(get_origin(tp)) else None
67
+
68
+
69
+ def is_hashable(tp: Any, /) -> bool:
70
+ """Return whether the provided argument is the `Hashable` class.
71
+
72
+ ```python {test="skip" lint="skip"}
73
+ is_hashable(Hashable)
74
+ #> True
75
+ ```
76
+ """
77
+ # `get_origin` is documented as normalizing any typing-module aliases to `collections` classes,
78
+ # hence the second check:
79
+ return tp is collections.abc.Hashable or get_origin(tp) is collections.abc.Hashable
80
+
81
+
82
+ def is_callable(tp: Any, /) -> bool:
83
+ """Return whether the provided argument is a `Callable`, parametrized or not.
84
+
85
+ ```python {test="skip" lint="skip"}
86
+ is_callable(Callable[[int], str])
87
+ #> True
88
+ is_callable(typing.Callable)
89
+ #> True
90
+ is_callable(collections.abc.Callable)
91
+ #> True
92
+ ```
93
+ """
94
+ # `get_origin` is documented as normalizing any typing-module aliases to `collections` classes,
95
+ # hence the second check:
96
+ return tp is collections.abc.Callable or get_origin(tp) is collections.abc.Callable
97
+
98
+
99
+ _classvar_re = re.compile(r'((\w+\.)?Annotated\[)?(\w+\.)?ClassVar\[')
100
+
101
+
102
+ def is_classvar_annotation(tp: Any, /) -> bool:
103
+ """Return whether the provided argument represents a class variable annotation.
104
+
105
+ Although not explicitly stated by the typing specification, `ClassVar` can be used
106
+ inside `Annotated` and as such, this function checks for this specific scenario.
107
+
108
+ Because this function is used to detect class variables before evaluating forward references
109
+ (or because evaluation failed), we also implement a naive regex match implementation. This is
110
+ required because class variables are inspected before fields are collected, so we try to be
111
+ as accurate as possible.
112
+ """
113
+ if typing_objects.is_classvar(tp):
114
+ return True
115
+
116
+ origin = get_origin(tp)
117
+
118
+ if typing_objects.is_classvar(origin):
119
+ return True
120
+
121
+ if typing_objects.is_annotated(origin):
122
+ annotated_type = tp.__origin__
123
+ if typing_objects.is_classvar(annotated_type) or typing_objects.is_classvar(get_origin(annotated_type)):
124
+ return True
125
+
126
+ str_ann: str | None = None
127
+ if isinstance(tp, typing.ForwardRef):
128
+ str_ann = tp.__forward_arg__
129
+ if isinstance(tp, str):
130
+ str_ann = tp
131
+
132
+ if str_ann is not None and _classvar_re.match(str_ann):
133
+ # stdlib dataclasses do something similar, although a bit more advanced
134
+ # (see `dataclass._is_type`).
135
+ return True
136
+
137
+ return False
138
+
139
+
140
+ _t_final = typing.Final
141
+ _te_final = typing_extensions.Final
142
+
143
+
144
+ # TODO implement `is_finalvar_annotation` as Final can be wrapped with other special forms:
145
+ def is_finalvar(tp: Any, /) -> bool:
146
+ """Return whether the provided argument is a `Final` special form, parametrized or not.
147
+
148
+ ```python {test="skip" lint="skip"}
149
+ is_finalvar(Final[int])
150
+ #> True
151
+ is_finalvar(Final)
152
+ #> True
153
+ """
154
+ # Final is not necessarily parametrized:
155
+ if tp is _t_final or tp is _te_final:
156
+ return True
157
+ origin = get_origin(tp)
158
+ return origin is _t_final or origin is _te_final
159
+
160
+
161
+ _NONE_TYPES: tuple[Any, ...] = (None, NoneType, typing.Literal[None], typing_extensions.Literal[None])
162
+
163
+
164
+ def is_none_type(tp: Any, /) -> bool:
165
+ """Return whether the argument represents the `None` type as part of an annotation.
166
+
167
+ ```python {test="skip" lint="skip"}
168
+ is_none_type(None)
169
+ #> True
170
+ is_none_type(NoneType)
171
+ #> True
172
+ is_none_type(Literal[None])
173
+ #> True
174
+ is_none_type(type[None])
175
+ #> False
176
+ """
177
+ return tp in _NONE_TYPES
178
+
179
+
180
+ def is_namedtuple(tp: Any, /) -> bool:
181
+ """Return whether the provided argument is a named tuple class.
182
+
183
+ The class can be created using `typing.NamedTuple` or `collections.namedtuple`.
184
+ Parametrized generic classes are *not* assumed to be named tuples.
185
+ """
186
+ from ._utils import lenient_issubclass # circ. import
187
+
188
+ return lenient_issubclass(tp, tuple) and hasattr(tp, '_fields')
189
+
190
+
191
+ # TODO In 2.12, delete this export. It is currently defined only to not break
192
+ # pydantic-settings which relies on it:
193
+ origin_is_union = is_union_origin
194
+
195
+
196
+ def is_generic_alias(tp: Any, /) -> bool:
197
+ return isinstance(tp, (types.GenericAlias, typing._GenericAlias)) # pyright: ignore[reportAttributeAccessIssue]
198
+
199
+
200
+ # TODO: Ideally, we should avoid relying on the private `typing` constructs:
201
+
202
+ if sys.version_info < (3, 10):
203
+ WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias) # pyright: ignore[reportAttributeAccessIssue]
204
+ else:
205
+ WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias, types.UnionType) # pyright: ignore[reportAttributeAccessIssue]
206
+
207
+
208
+ # Similarly, we shouldn't rely on this `_Final` class, which is even more private than `_GenericAlias`:
209
+ typing_base: Any = typing._Final # pyright: ignore[reportAttributeAccessIssue]
210
+
211
+
212
+ ### Annotation evaluations functions:
213
+
214
+
215
+ def parent_frame_namespace(*, parent_depth: int = 2, force: bool = False) -> dict[str, Any] | None:
216
+ """Fetch the local namespace of the parent frame where this function is called.
217
+
218
+ Using this function is mostly useful to resolve forward annotations pointing to members defined in a local namespace,
219
+ such as assignments inside a function. Using the standard library tools, it is currently not possible to resolve
220
+ such annotations:
221
+
222
+ ```python {lint="skip" test="skip"}
223
+ from typing import get_type_hints
224
+
225
+ def func() -> None:
226
+ Alias = int
227
+
228
+ class C:
229
+ a: 'Alias'
230
+
231
+ # Raises a `NameError: 'Alias' is not defined`
232
+ get_type_hints(C)
233
+ ```
234
+
235
+ Pydantic uses this function when a Pydantic model is being defined to fetch the parent frame locals. However,
236
+ this only allows us to fetch the parent frame namespace and not other parents (e.g. a model defined in a function,
237
+ itself defined in another function). Inspecting the next outer frames (using `f_back`) is not reliable enough
238
+ (see https://discuss.python.org/t/20659).
239
+
240
+ Because this function is mostly used to better resolve forward annotations, nothing is returned if the parent frame's
241
+ code object is defined at the module level. In this case, the locals of the frame will be the same as the module
242
+ globals where the class is defined (see `_namespace_utils.get_module_ns_of`). However, if you still want to fetch
243
+ the module globals (e.g. when rebuilding a model, where the frame where the rebuild call is performed might contain
244
+ members that you want to use for forward annotations evaluation), you can use the `force` parameter.
245
+
246
+ Args:
247
+ parent_depth: The depth at which to get the frame. Defaults to 2, meaning the parent frame where this function
248
+ is called will be used.
249
+ force: Whether to always return the frame locals, even if the frame's code object is defined at the module level.
250
+
251
+ Returns:
252
+ The locals of the namespace, or `None` if it was skipped as per the described logic.
253
+ """
254
+ frame = sys._getframe(parent_depth)
255
+
256
+ if frame.f_code.co_name.startswith('<generic parameters of'):
257
+ # As `parent_frame_namespace` is mostly called in `ModelMetaclass.__new__`,
258
+ # the parent frame can be the annotation scope if the PEP 695 generic syntax is used.
259
+ # (see https://docs.python.org/3/reference/executionmodel.html#annotation-scopes,
260
+ # https://docs.python.org/3/reference/compound_stmts.html#generic-classes).
261
+ # In this case, the code name is set to `<generic parameters of MyClass>`,
262
+ # and we need to skip this frame as it is irrelevant.
263
+ frame = cast(types.FrameType, frame.f_back) # guaranteed to not be `None`
264
+
265
+ # note, we don't copy frame.f_locals here (or during the last return call), because we don't expect the namespace to be
266
+ # modified down the line if this becomes a problem, we could implement some sort of frozen mapping structure to enforce this.
267
+ if force:
268
+ return frame.f_locals
269
+
270
+ # If either of the following conditions are true, the class is defined at the top module level.
271
+ # To better understand why we need both of these checks, see
272
+ # https://github.com/pydantic/pydantic/pull/10113#discussion_r1714981531.
273
+ if frame.f_back is None or frame.f_code.co_name == '<module>':
274
+ return None
275
+
276
+ return frame.f_locals
277
+
278
+
279
+ def _type_convert(arg: Any) -> Any:
280
+ """Convert `None` to `NoneType` and strings to `ForwardRef` instances.
281
+
282
+ This is a backport of the private `typing._type_convert` function. When
283
+ evaluating a type, `ForwardRef._evaluate` ends up being called, and is
284
+ responsible for making this conversion. However, we still have to apply
285
+ it for the first argument passed to our type evaluation functions, similarly
286
+ to the `typing.get_type_hints` function.
287
+ """
288
+ if arg is None:
289
+ return NoneType
290
+ if isinstance(arg, str):
291
+ # Like `typing.get_type_hints`, assume the arg can be in any context,
292
+ # hence the proper `is_argument` and `is_class` args:
293
+ return _make_forward_ref(arg, is_argument=False, is_class=True)
294
+ return arg
295
+
296
+
297
+ def safe_get_annotations(obj: Any) -> dict[str, Any]:
298
+ """Get the annotations for the provided object, accounting for potential deferred forward references.
299
+
300
+ Starting with Python 3.14, accessing the `__annotations__` attribute might raise a `NameError` if
301
+ a referenced symbol isn't defined yet. In this case, we return the annotation in the *forward ref*
302
+ format.
303
+ """
304
+ if sys.version_info >= (3, 14):
305
+ return annotationlib.get_annotations(obj, format=annotationlib.Format.FORWARDREF)
306
+ else:
307
+ # TODO just do getattr(obj, '__annotations__', {}) when dropping support for Python 3.9:
308
+ if isinstance(obj, type):
309
+ return obj.__dict__.get('__annotations__', {})
310
+ else:
311
+ return getattr(obj, '__annotations__', {})
312
+
313
+
314
+ def get_model_type_hints(
315
+ model_class: type[BaseModel],
316
+ *,
317
+ ns_resolver: NsResolver | None = None,
318
+ ) -> dict[str, tuple[Any, bool]]:
319
+ """Collect annotations from a Pydantic model class, including those from parent classes.
320
+
321
+ Args:
322
+ model_class: The Pydantic model class to inspect.
323
+ ns_resolver: A namespace resolver instance to use. Defaults to an empty instance.
324
+
325
+ Returns:
326
+ A dictionary mapping annotation names to a two-tuple: the first element is the evaluated
327
+ type or the original annotation if a `NameError` occurred, the second element is a boolean
328
+ indicating if whether the evaluation succeeded.
329
+ """
330
+ hints: dict[str, Any] | dict[str, tuple[Any, bool]] = {}
331
+ ns_resolver = ns_resolver or NsResolver()
332
+
333
+ for base in reversed(model_class.__mro__[:-1]):
334
+ # For Python 3.14, we could also use `Format.VALUE` and pass the globals/locals
335
+ # from the ns_resolver, but we want to be able to know which specific field failed
336
+ # to evaluate:
337
+ ann = safe_get_annotations(base)
338
+
339
+ if not ann:
340
+ continue
341
+
342
+ with ns_resolver.push(base):
343
+ base_model_fields: dict[str, FieldInfo] | None = base.__dict__.get('__pydantic_fields__')
344
+
345
+ for name, value in ann.items():
346
+ if name.startswith('_'):
347
+ globalns, localns = ns_resolver.types_namespace
348
+
349
+ # For private attributes, we only need the annotation to detect the `ClassVar` special form.
350
+ # For this reason, we still try to evaluate it, but we also catch any possible exception (on
351
+ # top of the `NameError`s caught in `try_eval_type`) that could happen so that users are free
352
+ # to use any kind of forward annotation for private fields (e.g. circular imports, new typing
353
+ # syntax, etc).
354
+ try:
355
+ hints[name] = try_eval_type(value, globalns, localns)
356
+ except Exception:
357
+ hints[name] = (value, False)
358
+ else:
359
+ if base_model_fields is not None and name in base_model_fields:
360
+ # Avoid unnecessarily evaluating annotations from parent models, as we'll end up
361
+ # copying the `FieldInfo` instance from it anyway if we need to.
362
+ # We use the `annotation` attribute here, but in reality could put anything here,
363
+ # As we are guaranteed to not make use of it:
364
+ hints[name] = (base_model_fields[name].annotation, True)
365
+ else:
366
+ globalns, localns = ns_resolver.types_namespace
367
+
368
+ hints[name] = try_eval_type(value, globalns, localns)
369
+
370
+ return hints
371
+
372
+
373
+ def get_cls_type_hints(
374
+ obj: type[Any],
375
+ *,
376
+ ns_resolver: NsResolver | None = None,
377
+ ) -> dict[str, Any]:
378
+ """Collect annotations from a class, including those from parent classes.
379
+
380
+ Args:
381
+ obj: The class to inspect.
382
+ ns_resolver: A namespace resolver instance to use. Defaults to an empty instance.
383
+ """
384
+ hints: dict[str, Any] = {}
385
+ ns_resolver = ns_resolver or NsResolver()
386
+
387
+ for base in reversed(obj.__mro__):
388
+ # For Python 3.14, we could also use `Format.VALUE` and pass the globals/locals
389
+ # from the ns_resolver, but we want to be able to know which specific field failed
390
+ # to evaluate:
391
+ ann = safe_get_annotations(base)
392
+
393
+ if not ann:
394
+ continue
395
+
396
+ with ns_resolver.push(base):
397
+ globalns, localns = ns_resolver.types_namespace
398
+ for name, value in ann.items():
399
+ hints[name] = eval_type(value, globalns, localns)
400
+ return hints
401
+
402
+
403
+ def try_eval_type(
404
+ value: Any,
405
+ globalns: GlobalsNamespace | None = None,
406
+ localns: MappingNamespace | None = None,
407
+ ) -> tuple[Any, bool]:
408
+ """Try evaluating the annotation using the provided namespaces.
409
+
410
+ Args:
411
+ value: The value to evaluate. If `None`, it will be replaced by `type[None]`. If an instance
412
+ of `str`, it will be converted to a `ForwardRef`.
413
+ localns: The global namespace to use during annotation evaluation.
414
+ globalns: The local namespace to use during annotation evaluation.
415
+
416
+ Returns:
417
+ A two-tuple containing the possibly evaluated type and a boolean indicating
418
+ whether the evaluation succeeded or not.
419
+ """
420
+ value = _type_convert(value)
421
+
422
+ try:
423
+ return eval_type_backport(value, globalns, localns), True
424
+ except NameError:
425
+ return value, False
426
+
427
+
428
+ def eval_type(
429
+ value: Any,
430
+ globalns: GlobalsNamespace | None = None,
431
+ localns: MappingNamespace | None = None,
432
+ ) -> Any:
433
+ """Evaluate the annotation using the provided namespaces.
434
+
435
+ Args:
436
+ value: The value to evaluate. If `None`, it will be replaced by `type[None]`. If an instance
437
+ of `str`, it will be converted to a `ForwardRef`.
438
+ localns: The global namespace to use during annotation evaluation.
439
+ globalns: The local namespace to use during annotation evaluation.
440
+ """
441
+ value = _type_convert(value)
442
+ return eval_type_backport(value, globalns, localns)
443
+
444
+
445
+ @deprecated(
446
+ '`eval_type_lenient` is deprecated, use `try_eval_type` instead.',
447
+ category=None,
448
+ )
449
+ def eval_type_lenient(
450
+ value: Any,
451
+ globalns: GlobalsNamespace | None = None,
452
+ localns: MappingNamespace | None = None,
453
+ ) -> Any:
454
+ ev, _ = try_eval_type(value, globalns, localns)
455
+ return ev
456
+
457
+
458
+ def eval_type_backport(
459
+ value: Any,
460
+ globalns: GlobalsNamespace | None = None,
461
+ localns: MappingNamespace | None = None,
462
+ type_params: tuple[Any, ...] | None = None,
463
+ ) -> Any:
464
+ """An enhanced version of `typing._eval_type` which will fall back to using the `eval_type_backport`
465
+ package if it's installed to let older Python versions use newer typing constructs.
466
+
467
+ Specifically, this transforms `X | Y` into `typing.Union[X, Y]` and `list[X]` into `typing.List[X]`
468
+ (as well as all the types made generic in PEP 585) if the original syntax is not supported in the
469
+ current Python version.
470
+
471
+ This function will also display a helpful error if the value passed fails to evaluate.
472
+ """
473
+ try:
474
+ return _eval_type_backport(value, globalns, localns, type_params)
475
+ except TypeError as e:
476
+ if 'Unable to evaluate type annotation' in str(e):
477
+ raise
478
+
479
+ # If it is a `TypeError` and value isn't a `ForwardRef`, it would have failed during annotation definition.
480
+ # Thus we assert here for type checking purposes:
481
+ assert isinstance(value, typing.ForwardRef)
482
+
483
+ message = f'Unable to evaluate type annotation {value.__forward_arg__!r}.'
484
+ if sys.version_info >= (3, 11):
485
+ e.add_note(message)
486
+ raise
487
+ else:
488
+ raise TypeError(message) from e
489
+ except RecursionError as e:
490
+ # TODO ideally recursion errors should be checked in `eval_type` above, but `eval_type_backport`
491
+ # is used directly in some places.
492
+ message = (
493
+ "If you made use of an implicit recursive type alias (e.g. `MyType = list['MyType']), "
494
+ 'consider using PEP 695 type aliases instead. For more details, refer to the documentation: '
495
+ f'https://docs.pydantic.dev/{version_short()}/concepts/types/#named-recursive-types'
496
+ )
497
+ if sys.version_info >= (3, 11):
498
+ e.add_note(message)
499
+ raise
500
+ else:
501
+ raise RecursionError(f'{e.args[0]}\n{message}')
502
+
503
+
504
+ def _eval_type_backport(
505
+ value: Any,
506
+ globalns: GlobalsNamespace | None = None,
507
+ localns: MappingNamespace | None = None,
508
+ type_params: tuple[Any, ...] | None = None,
509
+ ) -> Any:
510
+ try:
511
+ return _eval_type(value, globalns, localns, type_params)
512
+ except TypeError as e:
513
+ if not (isinstance(value, typing.ForwardRef) and is_backport_fixable_error(e)):
514
+ raise
515
+
516
+ try:
517
+ from eval_type_backport import eval_type_backport
518
+ except ImportError:
519
+ raise TypeError(
520
+ f'Unable to evaluate type annotation {value.__forward_arg__!r}. If you are making use '
521
+ 'of the new typing syntax (unions using `|` since Python 3.10 or builtins subscripting '
522
+ 'since Python 3.9), you should either replace the use of new syntax with the existing '
523
+ '`typing` constructs or install the `eval_type_backport` package.'
524
+ ) from e
525
+
526
+ return eval_type_backport(
527
+ value,
528
+ globalns,
529
+ localns, # pyright: ignore[reportArgumentType], waiting on a new `eval_type_backport` release.
530
+ try_default=False,
531
+ )
532
+
533
+
534
+ def _eval_type(
535
+ value: Any,
536
+ globalns: GlobalsNamespace | None = None,
537
+ localns: MappingNamespace | None = None,
538
+ type_params: tuple[Any, ...] | None = None,
539
+ ) -> Any:
540
+ if sys.version_info >= (3, 14):
541
+ # Starting in 3.14, `_eval_type()` does *not* apply `_type_convert()`
542
+ # anymore. This means the `None` -> `type(None)` conversion does not apply:
543
+ evaluated = typing._eval_type( # type: ignore
544
+ value,
545
+ globalns,
546
+ localns,
547
+ type_params=type_params,
548
+ # This is relevant when evaluating types from `TypedDict` classes, where string annotations
549
+ # are automatically converted to `ForwardRef` instances with a module set. In this case,
550
+ # Our `globalns` is irrelevant and we need to indicate `typing._eval_type()` that it should
551
+ # infer it from the `ForwardRef.__forward_module__` attribute instead (`typing.get_type_hints()`
552
+ # does the same). Note that this would probably be unnecessary if we properly iterated over the
553
+ # `__orig_bases__` for TypedDicts in `get_cls_type_hints()`:
554
+ prefer_fwd_module=True,
555
+ )
556
+ if evaluated is None:
557
+ evaluated = type(None)
558
+ return evaluated
559
+ elif sys.version_info >= (3, 13):
560
+ return typing._eval_type( # type: ignore
561
+ value, globalns, localns, type_params=type_params
562
+ )
563
+ else:
564
+ return typing._eval_type( # type: ignore
565
+ value, globalns, localns
566
+ )
567
+
568
+
569
+ def is_backport_fixable_error(e: TypeError) -> bool:
570
+ msg = str(e)
571
+
572
+ return sys.version_info < (3, 10) and msg.startswith('unsupported operand type(s) for |: ')
573
+
574
+
575
+ def signature_no_eval(f: Callable[..., Any]) -> Signature:
576
+ """Get the signature of a callable without evaluating any annotations."""
577
+ if sys.version_info >= (3, 14):
578
+ from annotationlib import Format
579
+
580
+ return signature(f, annotation_format=Format.FORWARDREF)
581
+ else:
582
+ return signature(f)
583
+
584
+
585
+ def get_function_type_hints(
586
+ function: Callable[..., Any],
587
+ *,
588
+ include_keys: set[str] | None = None,
589
+ globalns: GlobalsNamespace | None = None,
590
+ localns: MappingNamespace | None = None,
591
+ ) -> dict[str, Any]:
592
+ """Return type hints for a function.
593
+
594
+ This is similar to the `typing.get_type_hints` function, with a few differences:
595
+ - Support `functools.partial` by using the underlying `func` attribute.
596
+ - Do not wrap type annotation of a parameter with `Optional` if it has a default value of `None`
597
+ (related bug: https://github.com/python/cpython/issues/90353, only fixed in 3.11+).
598
+ """
599
+ if isinstance(function, partial):
600
+ annotations = safe_get_annotations(function.func)
601
+ else:
602
+ annotations = safe_get_annotations(function)
603
+
604
+ if globalns is None:
605
+ globalns = get_module_ns_of(function)
606
+ type_params: tuple[Any, ...] | None = None
607
+ if localns is None:
608
+ # If localns was specified, it is assumed to already contain type params. This is because
609
+ # Pydantic has more advanced logic to do so (see `_namespace_utils.ns_for_function`).
610
+ type_params = getattr(function, '__type_params__', ())
611
+
612
+ type_hints = {}
613
+ for name, value in annotations.items():
614
+ if include_keys is not None and name not in include_keys:
615
+ continue
616
+ if value is None:
617
+ value = NoneType
618
+ elif isinstance(value, str):
619
+ value = _make_forward_ref(value)
620
+
621
+ type_hints[name] = eval_type_backport(value, globalns, localns, type_params)
622
+
623
+ return type_hints
624
+
625
+
626
+ # TODO use typing.ForwardRef directly when we stop supporting 3.9:
627
+ if sys.version_info < (3, 9, 8) or (3, 10) <= sys.version_info < (3, 10, 1):
628
+
629
+ def _make_forward_ref(
630
+ arg: Any,
631
+ is_argument: bool = True,
632
+ *,
633
+ is_class: bool = False,
634
+ ) -> typing.ForwardRef:
635
+ """Wrapper for ForwardRef that accounts for the `is_class` argument missing in older versions.
636
+ The `module` argument is omitted as it breaks <3.9.8, =3.10.0 and isn't used in the calls below.
637
+
638
+ See https://github.com/python/cpython/pull/28560 for some background.
639
+ The backport happened on 3.9.8, see:
640
+ https://github.com/pydantic/pydantic/discussions/6244#discussioncomment-6275458,
641
+ and on 3.10.1 for the 3.10 branch, see:
642
+ https://github.com/pydantic/pydantic/issues/6912
643
+
644
+ Implemented as EAFP with memory.
645
+ """
646
+ return typing.ForwardRef(arg, is_argument) # pyright: ignore[reportCallIssue]
647
+
648
+ else:
649
+ _make_forward_ref = typing.ForwardRef # pyright: ignore[reportAssignmentType]
650
+
651
+
652
+ if sys.version_info >= (3, 10):
653
+ get_type_hints = typing.get_type_hints
654
+
655
+ else:
656
+ """
657
+ For older versions of python, we have a custom implementation of `get_type_hints` which is a close as possible to
658
+ the implementation in CPython 3.10.8.
659
+ """
660
+
661
+ @typing.no_type_check
662
+ def get_type_hints( # noqa: C901
663
+ obj: Any,
664
+ globalns: dict[str, Any] | None = None,
665
+ localns: dict[str, Any] | None = None,
666
+ include_extras: bool = False,
667
+ ) -> dict[str, Any]: # pragma: no cover
668
+ """Taken verbatim from python 3.10.8 unchanged, except:
669
+ * type annotations of the function definition above.
670
+ * prefixing `typing.` where appropriate
671
+ * Use `_make_forward_ref` instead of `typing.ForwardRef` to handle the `is_class` argument.
672
+
673
+ https://github.com/python/cpython/blob/aaaf5174241496afca7ce4d4584570190ff972fe/Lib/typing.py#L1773-L1875
674
+
675
+ DO NOT CHANGE THIS METHOD UNLESS ABSOLUTELY NECESSARY.
676
+ ======================================================
677
+
678
+ Return type hints for an object.
679
+
680
+ This is often the same as obj.__annotations__, but it handles
681
+ forward references encoded as string literals, adds Optional[t] if a
682
+ default value equal to None is set and recursively replaces all
683
+ 'Annotated[T, ...]' with 'T' (unless 'include_extras=True').
684
+
685
+ The argument may be a module, class, method, or function. The annotations
686
+ are returned as a dictionary. For classes, annotations include also
687
+ inherited members.
688
+
689
+ TypeError is raised if the argument is not of a type that can contain
690
+ annotations, and an empty dictionary is returned if no annotations are
691
+ present.
692
+
693
+ BEWARE -- the behavior of globalns and localns is counterintuitive
694
+ (unless you are familiar with how eval() and exec() work). The
695
+ search order is locals first, then globals.
696
+
697
+ - If no dict arguments are passed, an attempt is made to use the
698
+ globals from obj (or the respective module's globals for classes),
699
+ and these are also used as the locals. If the object does not appear
700
+ to have globals, an empty dictionary is used. For classes, the search
701
+ order is globals first then locals.
702
+
703
+ - If one dict argument is passed, it is used for both globals and
704
+ locals.
705
+
706
+ - If two dict arguments are passed, they specify globals and
707
+ locals, respectively.
708
+ """
709
+ if getattr(obj, '__no_type_check__', None):
710
+ return {}
711
+ # Classes require a special treatment.
712
+ if isinstance(obj, type):
713
+ hints = {}
714
+ for base in reversed(obj.__mro__):
715
+ if globalns is None:
716
+ base_globals = getattr(sys.modules.get(base.__module__, None), '__dict__', {})
717
+ else:
718
+ base_globals = globalns
719
+ ann = base.__dict__.get('__annotations__', {})
720
+ if isinstance(ann, types.GetSetDescriptorType):
721
+ ann = {}
722
+ base_locals = dict(vars(base)) if localns is None else localns
723
+ if localns is None and globalns is None:
724
+ # This is surprising, but required. Before Python 3.10,
725
+ # get_type_hints only evaluated the globalns of
726
+ # a class. To maintain backwards compatibility, we reverse
727
+ # the globalns and localns order so that eval() looks into
728
+ # *base_globals* first rather than *base_locals*.
729
+ # This only affects ForwardRefs.
730
+ base_globals, base_locals = base_locals, base_globals
731
+ for name, value in ann.items():
732
+ if value is None:
733
+ value = type(None)
734
+ if isinstance(value, str):
735
+ value = _make_forward_ref(value, is_argument=False, is_class=True)
736
+
737
+ value = eval_type_backport(value, base_globals, base_locals)
738
+ hints[name] = value
739
+ if not include_extras and hasattr(typing, '_strip_annotations'):
740
+ return {
741
+ k: typing._strip_annotations(t) # type: ignore
742
+ for k, t in hints.items()
743
+ }
744
+ else:
745
+ return hints
746
+
747
+ if globalns is None:
748
+ if isinstance(obj, types.ModuleType):
749
+ globalns = obj.__dict__
750
+ else:
751
+ nsobj = obj
752
+ # Find globalns for the unwrapped object.
753
+ while hasattr(nsobj, '__wrapped__'):
754
+ nsobj = nsobj.__wrapped__
755
+ globalns = getattr(nsobj, '__globals__', {})
756
+ if localns is None:
757
+ localns = globalns
758
+ elif localns is None:
759
+ localns = globalns
760
+ hints = getattr(obj, '__annotations__', None)
761
+ if hints is None:
762
+ # Return empty annotations for something that _could_ have them.
763
+ if isinstance(obj, typing._allowed_types): # type: ignore
764
+ return {}
765
+ else:
766
+ raise TypeError(f'{obj!r} is not a module, class, method, or function.')
767
+ defaults = typing._get_defaults(obj) # type: ignore
768
+ hints = dict(hints)
769
+ for name, value in hints.items():
770
+ if value is None:
771
+ value = type(None)
772
+ if isinstance(value, str):
773
+ # class-level forward refs were handled above, this must be either
774
+ # a module-level annotation or a function argument annotation
775
+
776
+ value = _make_forward_ref(
777
+ value,
778
+ is_argument=not isinstance(obj, types.ModuleType),
779
+ is_class=False,
780
+ )
781
+ value = eval_type_backport(value, globalns, localns)
782
+ if name in defaults and defaults[name] is None:
783
+ value = typing.Optional[value]
784
+ hints[name] = value
785
+ return hints if include_extras else {k: typing._strip_annotations(t) for k, t in hints.items()} # type: ignore
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_utils.py ADDED
@@ -0,0 +1,446 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Bucket of reusable internal utilities.
2
+
3
+ This should be reduced as much as possible with functions only used in one place, moved to that place.
4
+ """
5
+
6
+ from __future__ import annotations as _annotations
7
+
8
+ import dataclasses
9
+ import keyword
10
+ import sys
11
+ import warnings
12
+ import weakref
13
+ from collections import OrderedDict, defaultdict, deque
14
+ from collections.abc import Callable, Iterable, Mapping
15
+ from collections.abc import Set as AbstractSet
16
+ from copy import deepcopy
17
+ from functools import cached_property
18
+ from inspect import Parameter
19
+ from itertools import zip_longest
20
+ from types import BuiltinFunctionType, CodeType, FunctionType, GeneratorType, LambdaType, ModuleType
21
+ from typing import TYPE_CHECKING, Any, Generic, TypeVar, overload
22
+
23
+ from pydantic_core import MISSING, PydanticUndefined
24
+ from typing_extensions import TypeAlias, TypeGuard, deprecated
25
+
26
+ from pydantic import PydanticDeprecatedSince211
27
+
28
+ from . import _repr, _typing_extra
29
+ from ._import_utils import import_cached_base_model
30
+
31
+ if TYPE_CHECKING:
32
+ # TODO remove type error comments when we drop support for Python 3.9
33
+ MappingIntStrAny: TypeAlias = Mapping[int, Any] | Mapping[str, Any] # pyright: ignore[reportGeneralTypeIssues]
34
+ AbstractSetIntStr: TypeAlias = AbstractSet[int] | AbstractSet[str] # pyright: ignore[reportGeneralTypeIssues]
35
+ from ..main import BaseModel
36
+
37
+
38
+ # these are types that are returned unchanged by deepcopy
39
+ IMMUTABLE_NON_COLLECTIONS_TYPES: set[type[Any]] = {
40
+ int,
41
+ float,
42
+ complex,
43
+ str,
44
+ bool,
45
+ bytes,
46
+ type,
47
+ _typing_extra.NoneType,
48
+ FunctionType,
49
+ BuiltinFunctionType,
50
+ LambdaType,
51
+ weakref.ref,
52
+ CodeType,
53
+ # note: including ModuleType will differ from behaviour of deepcopy by not producing error.
54
+ # It might be not a good idea in general, but considering that this function used only internally
55
+ # against default values of fields, this will allow to actually have a field with module as default value
56
+ ModuleType,
57
+ NotImplemented.__class__,
58
+ Ellipsis.__class__,
59
+ }
60
+
61
+ # these are types that if empty, might be copied with simple copy() instead of deepcopy()
62
+ BUILTIN_COLLECTIONS: set[type[Any]] = {
63
+ list,
64
+ set,
65
+ tuple,
66
+ frozenset,
67
+ dict,
68
+ OrderedDict,
69
+ defaultdict,
70
+ deque,
71
+ }
72
+
73
+
74
+ def can_be_positional(param: Parameter) -> bool:
75
+ """Return whether the parameter accepts a positional argument.
76
+
77
+ ```python {test="skip" lint="skip"}
78
+ def func(a, /, b, *, c):
79
+ pass
80
+
81
+ params = inspect.signature(func).parameters
82
+ can_be_positional(params['a'])
83
+ #> True
84
+ can_be_positional(params['b'])
85
+ #> True
86
+ can_be_positional(params['c'])
87
+ #> False
88
+ ```
89
+ """
90
+ return param.kind in (Parameter.POSITIONAL_ONLY, Parameter.POSITIONAL_OR_KEYWORD)
91
+
92
+
93
+ def sequence_like(v: Any) -> bool:
94
+ return isinstance(v, (list, tuple, set, frozenset, GeneratorType, deque))
95
+
96
+
97
+ def lenient_isinstance(o: Any, class_or_tuple: type[Any] | tuple[type[Any], ...] | None) -> bool: # pragma: no cover
98
+ try:
99
+ return isinstance(o, class_or_tuple) # type: ignore[arg-type]
100
+ except TypeError:
101
+ return False
102
+
103
+
104
+ def lenient_issubclass(cls: Any, class_or_tuple: Any) -> bool: # pragma: no cover
105
+ try:
106
+ return isinstance(cls, type) and issubclass(cls, class_or_tuple)
107
+ except TypeError:
108
+ if isinstance(cls, _typing_extra.WithArgsTypes):
109
+ return False
110
+ raise # pragma: no cover
111
+
112
+
113
+ def is_model_class(cls: Any) -> TypeGuard[type[BaseModel]]:
114
+ """Returns true if cls is a _proper_ subclass of BaseModel, and provides proper type-checking,
115
+ unlike raw calls to lenient_issubclass.
116
+ """
117
+ BaseModel = import_cached_base_model()
118
+
119
+ return lenient_issubclass(cls, BaseModel) and cls is not BaseModel
120
+
121
+
122
+ def is_valid_identifier(identifier: str) -> bool:
123
+ """Checks that a string is a valid identifier and not a Python keyword.
124
+ :param identifier: The identifier to test.
125
+ :return: True if the identifier is valid.
126
+ """
127
+ return identifier.isidentifier() and not keyword.iskeyword(identifier)
128
+
129
+
130
+ KeyType = TypeVar('KeyType')
131
+
132
+
133
+ def deep_update(mapping: dict[KeyType, Any], *updating_mappings: dict[KeyType, Any]) -> dict[KeyType, Any]:
134
+ updated_mapping = mapping.copy()
135
+ for updating_mapping in updating_mappings:
136
+ for k, v in updating_mapping.items():
137
+ if k in updated_mapping and isinstance(updated_mapping[k], dict) and isinstance(v, dict):
138
+ updated_mapping[k] = deep_update(updated_mapping[k], v)
139
+ else:
140
+ updated_mapping[k] = v
141
+ return updated_mapping
142
+
143
+
144
+ def update_not_none(mapping: dict[Any, Any], **update: Any) -> None:
145
+ mapping.update({k: v for k, v in update.items() if v is not None})
146
+
147
+
148
+ T = TypeVar('T')
149
+
150
+
151
+ def unique_list(
152
+ input_list: list[T] | tuple[T, ...],
153
+ *,
154
+ name_factory: Callable[[T], str] = str,
155
+ ) -> list[T]:
156
+ """Make a list unique while maintaining order.
157
+ We update the list if another one with the same name is set
158
+ (e.g. model validator overridden in subclass).
159
+ """
160
+ result: list[T] = []
161
+ result_names: list[str] = []
162
+ for v in input_list:
163
+ v_name = name_factory(v)
164
+ if v_name not in result_names:
165
+ result_names.append(v_name)
166
+ result.append(v)
167
+ else:
168
+ result[result_names.index(v_name)] = v
169
+
170
+ return result
171
+
172
+
173
+ class ValueItems(_repr.Representation):
174
+ """Class for more convenient calculation of excluded or included fields on values."""
175
+
176
+ __slots__ = ('_items', '_type')
177
+
178
+ def __init__(self, value: Any, items: AbstractSetIntStr | MappingIntStrAny) -> None:
179
+ items = self._coerce_items(items)
180
+
181
+ if isinstance(value, (list, tuple)):
182
+ items = self._normalize_indexes(items, len(value)) # type: ignore
183
+
184
+ self._items: MappingIntStrAny = items # type: ignore
185
+
186
+ def is_excluded(self, item: Any) -> bool:
187
+ """Check if item is fully excluded.
188
+
189
+ :param item: key or index of a value
190
+ """
191
+ return self.is_true(self._items.get(item))
192
+
193
+ def is_included(self, item: Any) -> bool:
194
+ """Check if value is contained in self._items.
195
+
196
+ :param item: key or index of value
197
+ """
198
+ return item in self._items
199
+
200
+ def for_element(self, e: int | str) -> AbstractSetIntStr | MappingIntStrAny | None:
201
+ """:param e: key or index of element on value
202
+ :return: raw values for element if self._items is dict and contain needed element
203
+ """
204
+ item = self._items.get(e) # type: ignore
205
+ return item if not self.is_true(item) else None
206
+
207
+ def _normalize_indexes(self, items: MappingIntStrAny, v_length: int) -> dict[int | str, Any]:
208
+ """:param items: dict or set of indexes which will be normalized
209
+ :param v_length: length of sequence indexes of which will be
210
+
211
+ >>> self._normalize_indexes({0: True, -2: True, -1: True}, 4)
212
+ {0: True, 2: True, 3: True}
213
+ >>> self._normalize_indexes({'__all__': True}, 4)
214
+ {0: True, 1: True, 2: True, 3: True}
215
+ """
216
+ normalized_items: dict[int | str, Any] = {}
217
+ all_items = None
218
+ for i, v in items.items():
219
+ if not (isinstance(v, Mapping) or isinstance(v, AbstractSet) or self.is_true(v)):
220
+ raise TypeError(f'Unexpected type of exclude value for index "{i}" {v.__class__}')
221
+ if i == '__all__':
222
+ all_items = self._coerce_value(v)
223
+ continue
224
+ if not isinstance(i, int):
225
+ raise TypeError(
226
+ 'Excluding fields from a sequence of sub-models or dicts must be performed index-wise: '
227
+ 'expected integer keys or keyword "__all__"'
228
+ )
229
+ normalized_i = v_length + i if i < 0 else i
230
+ normalized_items[normalized_i] = self.merge(v, normalized_items.get(normalized_i))
231
+
232
+ if not all_items:
233
+ return normalized_items
234
+ if self.is_true(all_items):
235
+ for i in range(v_length):
236
+ normalized_items.setdefault(i, ...)
237
+ return normalized_items
238
+ for i in range(v_length):
239
+ normalized_item = normalized_items.setdefault(i, {})
240
+ if not self.is_true(normalized_item):
241
+ normalized_items[i] = self.merge(all_items, normalized_item)
242
+ return normalized_items
243
+
244
+ @classmethod
245
+ def merge(cls, base: Any, override: Any, intersect: bool = False) -> Any:
246
+ """Merge a `base` item with an `override` item.
247
+
248
+ Both `base` and `override` are converted to dictionaries if possible.
249
+ Sets are converted to dictionaries with the sets entries as keys and
250
+ Ellipsis as values.
251
+
252
+ Each key-value pair existing in `base` is merged with `override`,
253
+ while the rest of the key-value pairs are updated recursively with this function.
254
+
255
+ Merging takes place based on the "union" of keys if `intersect` is
256
+ set to `False` (default) and on the intersection of keys if
257
+ `intersect` is set to `True`.
258
+ """
259
+ override = cls._coerce_value(override)
260
+ base = cls._coerce_value(base)
261
+ if override is None:
262
+ return base
263
+ if cls.is_true(base) or base is None:
264
+ return override
265
+ if cls.is_true(override):
266
+ return base if intersect else override
267
+
268
+ # intersection or union of keys while preserving ordering:
269
+ if intersect:
270
+ merge_keys = [k for k in base if k in override] + [k for k in override if k in base]
271
+ else:
272
+ merge_keys = list(base) + [k for k in override if k not in base]
273
+
274
+ merged: dict[int | str, Any] = {}
275
+ for k in merge_keys:
276
+ merged_item = cls.merge(base.get(k), override.get(k), intersect=intersect)
277
+ if merged_item is not None:
278
+ merged[k] = merged_item
279
+
280
+ return merged
281
+
282
+ @staticmethod
283
+ def _coerce_items(items: AbstractSetIntStr | MappingIntStrAny) -> MappingIntStrAny:
284
+ if isinstance(items, Mapping):
285
+ pass
286
+ elif isinstance(items, AbstractSet):
287
+ items = dict.fromkeys(items, ...) # type: ignore
288
+ else:
289
+ class_name = getattr(items, '__class__', '???')
290
+ raise TypeError(f'Unexpected type of exclude value {class_name}')
291
+ return items # type: ignore
292
+
293
+ @classmethod
294
+ def _coerce_value(cls, value: Any) -> Any:
295
+ if value is None or cls.is_true(value):
296
+ return value
297
+ return cls._coerce_items(value)
298
+
299
+ @staticmethod
300
+ def is_true(v: Any) -> bool:
301
+ return v is True or v is ...
302
+
303
+ def __repr_args__(self) -> _repr.ReprArgs:
304
+ return [(None, self._items)]
305
+
306
+
307
+ if TYPE_CHECKING:
308
+
309
+ def LazyClassAttribute(name: str, get_value: Callable[[], T]) -> T: ...
310
+
311
+ else:
312
+
313
+ class LazyClassAttribute:
314
+ """A descriptor exposing an attribute only accessible on a class (hidden from instances).
315
+
316
+ The attribute is lazily computed and cached during the first access.
317
+ """
318
+
319
+ def __init__(self, name: str, get_value: Callable[[], Any]) -> None:
320
+ self.name = name
321
+ self.get_value = get_value
322
+
323
+ @cached_property
324
+ def value(self) -> Any:
325
+ return self.get_value()
326
+
327
+ def __get__(self, instance: Any, owner: type[Any]) -> None:
328
+ if instance is None:
329
+ return self.value
330
+ raise AttributeError(f'{self.name!r} attribute of {owner.__name__!r} is class-only')
331
+
332
+
333
+ Obj = TypeVar('Obj')
334
+
335
+
336
+ def smart_deepcopy(obj: Obj) -> Obj:
337
+ """Return type as is for immutable built-in types
338
+ Use obj.copy() for built-in empty collections
339
+ Use copy.deepcopy() for non-empty collections and unknown objects.
340
+ """
341
+ if obj is MISSING or obj is PydanticUndefined:
342
+ return obj # pyright: ignore[reportReturnType]
343
+ obj_type = obj.__class__
344
+ if obj_type in IMMUTABLE_NON_COLLECTIONS_TYPES:
345
+ return obj # fastest case: obj is immutable and not collection therefore will not be copied anyway
346
+ try:
347
+ if not obj and obj_type in BUILTIN_COLLECTIONS:
348
+ # faster way for empty collections, no need to copy its members
349
+ return obj if obj_type is tuple else obj.copy() # tuple doesn't have copy method # type: ignore
350
+ except (TypeError, ValueError, RuntimeError):
351
+ # do we really dare to catch ALL errors? Seems a bit risky
352
+ pass
353
+
354
+ return deepcopy(obj) # slowest way when we actually might need a deepcopy
355
+
356
+
357
+ _SENTINEL = object()
358
+
359
+
360
+ def all_identical(left: Iterable[Any], right: Iterable[Any]) -> bool:
361
+ """Check that the items of `left` are the same objects as those in `right`.
362
+
363
+ >>> a, b = object(), object()
364
+ >>> all_identical([a, b, a], [a, b, a])
365
+ True
366
+ >>> all_identical([a, b, [a]], [a, b, [a]]) # new list object, while "equal" is not "identical"
367
+ False
368
+ """
369
+ for left_item, right_item in zip_longest(left, right, fillvalue=_SENTINEL):
370
+ if left_item is not right_item:
371
+ return False
372
+ return True
373
+
374
+
375
+ def get_first_not_none(a: Any, b: Any) -> Any:
376
+ """Return the first argument if it is not `None`, otherwise return the second argument."""
377
+ return a if a is not None else b
378
+
379
+
380
+ @dataclasses.dataclass(frozen=True)
381
+ class SafeGetItemProxy:
382
+ """Wrapper redirecting `__getitem__` to `get` with a sentinel value as default
383
+
384
+ This makes is safe to use in `operator.itemgetter` when some keys may be missing
385
+ """
386
+
387
+ # Define __slots__manually for performances
388
+ # @dataclasses.dataclass() only support slots=True in python>=3.10
389
+ __slots__ = ('wrapped',)
390
+
391
+ wrapped: Mapping[str, Any]
392
+
393
+ def __getitem__(self, key: str, /) -> Any:
394
+ return self.wrapped.get(key, _SENTINEL)
395
+
396
+ # required to pass the object to operator.itemgetter() instances due to a quirk of typeshed
397
+ # https://github.com/python/mypy/issues/13713
398
+ # https://github.com/python/typeshed/pull/8785
399
+ # Since this is typing-only, hide it in a typing.TYPE_CHECKING block
400
+ if TYPE_CHECKING:
401
+
402
+ def __contains__(self, key: str, /) -> bool:
403
+ return self.wrapped.__contains__(key)
404
+
405
+
406
+ _ModelT = TypeVar('_ModelT', bound='BaseModel')
407
+ _RT = TypeVar('_RT')
408
+
409
+
410
+ class deprecated_instance_property(Generic[_ModelT, _RT]):
411
+ """A decorator exposing the decorated class method as a property, with a warning on instance access.
412
+
413
+ This decorator takes a class method defined on the `BaseModel` class and transforms it into
414
+ an attribute. The attribute can be accessed on both the class and instances of the class. If accessed
415
+ via an instance, a deprecation warning is emitted stating that instance access will be removed in V3.
416
+ """
417
+
418
+ def __init__(self, fget: Callable[[type[_ModelT]], _RT], /) -> None:
419
+ # Note: fget should be a classmethod:
420
+ self.fget = fget
421
+
422
+ @overload
423
+ def __get__(self, instance: None, objtype: type[_ModelT]) -> _RT: ...
424
+ @overload
425
+ @deprecated(
426
+ 'Accessing this attribute on the instance is deprecated, and will be removed in Pydantic V3. '
427
+ 'Instead, you should access this attribute from the model class.',
428
+ category=None,
429
+ )
430
+ def __get__(self, instance: _ModelT, objtype: type[_ModelT]) -> _RT: ...
431
+ def __get__(self, instance: _ModelT | None, objtype: type[_ModelT]) -> _RT:
432
+ if instance is not None:
433
+ # fmt: off
434
+ attr_name = (
435
+ self.fget.__name__
436
+ if sys.version_info >= (3, 10)
437
+ else self.fget.__func__.__name__ # pyright: ignore[reportFunctionMemberAccess]
438
+ )
439
+ # fmt: on
440
+ warnings.warn(
441
+ f'Accessing the {attr_name!r} attribute on the instance is deprecated. '
442
+ 'Instead, you should access this attribute from the model class.',
443
+ category=PydanticDeprecatedSince211,
444
+ stacklevel=2,
445
+ )
446
+ return self.fget.__get__(instance, objtype)()
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_validate_call.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations as _annotations
2
+
3
+ import functools
4
+ import inspect
5
+ from collections.abc import Awaitable
6
+ from functools import partial
7
+ from typing import Any, Callable
8
+
9
+ import pydantic_core
10
+
11
+ from ..config import ConfigDict
12
+ from ..plugin._schema_validator import create_schema_validator
13
+ from ._config import ConfigWrapper
14
+ from ._generate_schema import GenerateSchema, ValidateCallSupportedTypes
15
+ from ._namespace_utils import MappingNamespace, NsResolver, ns_for_function
16
+ from ._typing_extra import signature_no_eval
17
+
18
+
19
+ def extract_function_name(func: ValidateCallSupportedTypes) -> str:
20
+ """Extract the name of a `ValidateCallSupportedTypes` object."""
21
+ return f'partial({func.func.__name__})' if isinstance(func, functools.partial) else func.__name__
22
+
23
+
24
+ def extract_function_qualname(func: ValidateCallSupportedTypes) -> str:
25
+ """Extract the qualname of a `ValidateCallSupportedTypes` object."""
26
+ return f'partial({func.func.__qualname__})' if isinstance(func, functools.partial) else func.__qualname__
27
+
28
+
29
+ def update_wrapper_attributes(wrapped: ValidateCallSupportedTypes, wrapper: Callable[..., Any]):
30
+ """Update the `wrapper` function with the attributes of the `wrapped` function. Return the updated function."""
31
+ if inspect.iscoroutinefunction(wrapped):
32
+
33
+ @functools.wraps(wrapped)
34
+ async def wrapper_function(*args, **kwargs): # type: ignore
35
+ return await wrapper(*args, **kwargs)
36
+ else:
37
+
38
+ @functools.wraps(wrapped)
39
+ def wrapper_function(*args, **kwargs):
40
+ return wrapper(*args, **kwargs)
41
+
42
+ # We need to manually update this because `partial` object has no `__name__` and `__qualname__`.
43
+ wrapper_function.__name__ = extract_function_name(wrapped)
44
+ wrapper_function.__qualname__ = extract_function_qualname(wrapped)
45
+ wrapper_function.raw_function = wrapped # type: ignore
46
+
47
+ return wrapper_function
48
+
49
+
50
+ class ValidateCallWrapper:
51
+ """This is a wrapper around a function that validates the arguments passed to it, and optionally the return value."""
52
+
53
+ __slots__ = (
54
+ 'function',
55
+ 'validate_return',
56
+ 'schema_type',
57
+ 'module',
58
+ 'qualname',
59
+ 'ns_resolver',
60
+ 'config_wrapper',
61
+ '__pydantic_complete__',
62
+ '__pydantic_validator__',
63
+ '__return_pydantic_validator__',
64
+ )
65
+
66
+ def __init__(
67
+ self,
68
+ function: ValidateCallSupportedTypes,
69
+ config: ConfigDict | None,
70
+ validate_return: bool,
71
+ parent_namespace: MappingNamespace | None,
72
+ ) -> None:
73
+ self.function = function
74
+ self.validate_return = validate_return
75
+ if isinstance(function, partial):
76
+ self.schema_type = function.func
77
+ self.module = function.func.__module__
78
+ else:
79
+ self.schema_type = function
80
+ self.module = function.__module__
81
+ self.qualname = extract_function_qualname(function)
82
+
83
+ self.ns_resolver = NsResolver(
84
+ namespaces_tuple=ns_for_function(self.schema_type, parent_namespace=parent_namespace)
85
+ )
86
+ self.config_wrapper = ConfigWrapper(config)
87
+ if not self.config_wrapper.defer_build:
88
+ self._create_validators()
89
+ else:
90
+ self.__pydantic_complete__ = False
91
+
92
+ def _create_validators(self) -> None:
93
+ gen_schema = GenerateSchema(self.config_wrapper, self.ns_resolver)
94
+ schema = gen_schema.clean_schema(gen_schema.generate_schema(self.function))
95
+ core_config = self.config_wrapper.core_config(title=self.qualname)
96
+
97
+ self.__pydantic_validator__ = create_schema_validator(
98
+ schema,
99
+ self.schema_type,
100
+ self.module,
101
+ self.qualname,
102
+ 'validate_call',
103
+ core_config,
104
+ self.config_wrapper.plugin_settings,
105
+ )
106
+ if self.validate_return:
107
+ signature = signature_no_eval(self.function)
108
+ return_type = signature.return_annotation if signature.return_annotation is not signature.empty else Any
109
+ gen_schema = GenerateSchema(self.config_wrapper, self.ns_resolver)
110
+ schema = gen_schema.clean_schema(gen_schema.generate_schema(return_type))
111
+ validator = create_schema_validator(
112
+ schema,
113
+ self.schema_type,
114
+ self.module,
115
+ self.qualname,
116
+ 'validate_call',
117
+ core_config,
118
+ self.config_wrapper.plugin_settings,
119
+ )
120
+ if inspect.iscoroutinefunction(self.function):
121
+
122
+ async def return_val_wrapper(aw: Awaitable[Any]) -> None:
123
+ return validator.validate_python(await aw)
124
+
125
+ self.__return_pydantic_validator__ = return_val_wrapper
126
+ else:
127
+ self.__return_pydantic_validator__ = validator.validate_python
128
+ else:
129
+ self.__return_pydantic_validator__ = None
130
+
131
+ self.__pydantic_complete__ = True
132
+
133
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
134
+ if not self.__pydantic_complete__:
135
+ self._create_validators()
136
+
137
+ res = self.__pydantic_validator__.validate_python(pydantic_core.ArgsKwargs(args, kwargs))
138
+ if self.__return_pydantic_validator__:
139
+ return self.__return_pydantic_validator__(res)
140
+ else:
141
+ return res
.mcp-venv/lib/python3.13/site-packages/pydantic/_internal/_validators.py ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Validator functions for standard library types.
2
+
3
+ Import of this module is deferred since it contains imports of many standard library modules.
4
+ """
5
+
6
+ from __future__ import annotations as _annotations
7
+
8
+ import collections.abc
9
+ import math
10
+ import re
11
+ import typing
12
+ from collections.abc import Sequence
13
+ from decimal import Decimal
14
+ from fractions import Fraction
15
+ from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network
16
+ from typing import Any, Callable, TypeVar, Union, cast
17
+ from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
18
+
19
+ import typing_extensions
20
+ from pydantic_core import PydanticCustomError, PydanticKnownError, core_schema
21
+ from typing_extensions import get_args, get_origin
22
+ from typing_inspection import typing_objects
23
+
24
+ from pydantic._internal._import_utils import import_cached_field_info
25
+ from pydantic.errors import PydanticSchemaGenerationError
26
+
27
+
28
+ def sequence_validator(
29
+ input_value: Sequence[Any],
30
+ /,
31
+ validator: core_schema.ValidatorFunctionWrapHandler,
32
+ ) -> Sequence[Any]:
33
+ """Validator for `Sequence` types, isinstance(v, Sequence) has already been called."""
34
+ value_type = type(input_value)
35
+
36
+ # We don't accept any plain string as a sequence
37
+ # Relevant issue: https://github.com/pydantic/pydantic/issues/5595
38
+ if issubclass(value_type, (str, bytes)):
39
+ raise PydanticCustomError(
40
+ 'sequence_str',
41
+ "'{type_name}' instances are not allowed as a Sequence value",
42
+ {'type_name': value_type.__name__},
43
+ )
44
+
45
+ # TODO: refactor sequence validation to validate with either a list or a tuple
46
+ # schema, depending on the type of the value.
47
+ # Additionally, we should be able to remove one of either this validator or the
48
+ # SequenceValidator in _std_types_schema.py (preferably this one, while porting over some logic).
49
+ # Effectively, a refactor for sequence validation is needed.
50
+ if value_type is tuple:
51
+ input_value = list(input_value)
52
+
53
+ v_list = validator(input_value)
54
+
55
+ # the rest of the logic is just re-creating the original type from `v_list`
56
+ if value_type is list:
57
+ return v_list
58
+ elif issubclass(value_type, range):
59
+ # return the list as we probably can't re-create the range
60
+ return v_list
61
+ elif value_type is tuple:
62
+ return tuple(v_list)
63
+ else:
64
+ # best guess at how to re-create the original type, more custom construction logic might be required
65
+ return value_type(v_list) # type: ignore[call-arg]
66
+
67
+
68
+ def import_string(value: Any) -> Any:
69
+ if isinstance(value, str):
70
+ try:
71
+ return _import_string_logic(value)
72
+ except ImportError as e:
73
+ raise PydanticCustomError('import_error', 'Invalid python path: {error}', {'error': str(e)}) from e
74
+ else:
75
+ # otherwise we just return the value and let the next validator do the rest of the work
76
+ return value
77
+
78
+
79
+ def _import_string_logic(dotted_path: str) -> Any:
80
+ """Inspired by uvicorn β€” dotted paths should include a colon before the final item if that item is not a module.
81
+ (This is necessary to distinguish between a submodule and an attribute when there is a conflict.).
82
+
83
+ If the dotted path does not include a colon and the final item is not a valid module, importing as an attribute
84
+ rather than a submodule will be attempted automatically.
85
+
86
+ So, for example, the following values of `dotted_path` result in the following returned values:
87
+ * 'collections': <module 'collections'>
88
+ * 'collections.abc': <module 'collections.abc'>
89
+ * 'collections.abc:Mapping': <class 'collections.abc.Mapping'>
90
+ * `collections.abc.Mapping`: <class 'collections.abc.Mapping'> (though this is a bit slower than the previous line)
91
+
92
+ An error will be raised under any of the following scenarios:
93
+ * `dotted_path` contains more than one colon (e.g., 'collections:abc:Mapping')
94
+ * the substring of `dotted_path` before the colon is not a valid module in the environment (e.g., '123:Mapping')
95
+ * the substring of `dotted_path` after the colon is not an attribute of the module (e.g., 'collections:abc123')
96
+ """
97
+ from importlib import import_module
98
+
99
+ components = dotted_path.strip().split(':')
100
+ if len(components) > 2:
101
+ raise ImportError(f"Import strings should have at most one ':'; received {dotted_path!r}")
102
+ attribute = None
103
+ if len(components) == 2:
104
+ attribute = components[1]
105
+ module_path = components[0]
106
+ if not module_path:
107
+ raise ImportError(f'Import strings should have a nonempty module name; received {dotted_path!r}')
108
+
109
+ try:
110
+ module = import_module(module_path)
111
+ except ModuleNotFoundError:
112
+ if attribute is None and '.' in module_path:
113
+ # Try interpreting the final dotted segment as an attribute, not a submodule
114
+ maybe_module_path, maybe_attribute = module_path.rsplit('.', 1)
115
+
116
+ try:
117
+ return _import_string_logic(f'{maybe_module_path}:{maybe_attribute}')
118
+ except ImportError:
119
+ pass
120
+ raise
121
+
122
+ if attribute is not None:
123
+ try:
124
+ return getattr(module, attribute)
125
+ except AttributeError as e:
126
+ raise ImportError(f'cannot import name {attribute!r} from {module_path!r}') from e
127
+ else:
128
+ return module
129
+
130
+
131
+ def pattern_either_validator(input_value: Any, /) -> re.Pattern[Any]:
132
+ if isinstance(input_value, re.Pattern):
133
+ return input_value
134
+ elif isinstance(input_value, (str, bytes)):
135
+ # todo strict mode
136
+ return compile_pattern(input_value) # type: ignore
137
+ else:
138
+ raise PydanticCustomError('pattern_type', 'Input should be a valid pattern')
139
+
140
+
141
+ def pattern_str_validator(input_value: Any, /) -> re.Pattern[str]:
142
+ if isinstance(input_value, re.Pattern):
143
+ if isinstance(input_value.pattern, str):
144
+ return input_value
145
+ else:
146
+ raise PydanticCustomError('pattern_str_type', 'Input should be a string pattern')
147
+ elif isinstance(input_value, str):
148
+ return compile_pattern(input_value)
149
+ elif isinstance(input_value, bytes):
150
+ raise PydanticCustomError('pattern_str_type', 'Input should be a string pattern')
151
+ else:
152
+ raise PydanticCustomError('pattern_type', 'Input should be a valid pattern')
153
+
154
+
155
+ def pattern_bytes_validator(input_value: Any, /) -> re.Pattern[bytes]:
156
+ if isinstance(input_value, re.Pattern):
157
+ if isinstance(input_value.pattern, bytes):
158
+ return input_value
159
+ else:
160
+ raise PydanticCustomError('pattern_bytes_type', 'Input should be a bytes pattern')
161
+ elif isinstance(input_value, bytes):
162
+ return compile_pattern(input_value)
163
+ elif isinstance(input_value, str):
164
+ raise PydanticCustomError('pattern_bytes_type', 'Input should be a bytes pattern')
165
+ else:
166
+ raise PydanticCustomError('pattern_type', 'Input should be a valid pattern')
167
+
168
+
169
+ PatternType = TypeVar('PatternType', str, bytes)
170
+
171
+
172
+ def compile_pattern(pattern: PatternType) -> re.Pattern[PatternType]:
173
+ try:
174
+ return re.compile(pattern)
175
+ except re.error:
176
+ raise PydanticCustomError('pattern_regex', 'Input should be a valid regular expression')
177
+
178
+
179
+ def ip_v4_address_validator(input_value: Any, /) -> IPv4Address:
180
+ if isinstance(input_value, IPv4Address):
181
+ return input_value
182
+
183
+ try:
184
+ return IPv4Address(input_value)
185
+ except ValueError:
186
+ raise PydanticCustomError('ip_v4_address', 'Input is not a valid IPv4 address')
187
+
188
+
189
+ def ip_v6_address_validator(input_value: Any, /) -> IPv6Address:
190
+ if isinstance(input_value, IPv6Address):
191
+ return input_value
192
+
193
+ try:
194
+ return IPv6Address(input_value)
195
+ except ValueError:
196
+ raise PydanticCustomError('ip_v6_address', 'Input is not a valid IPv6 address')
197
+
198
+
199
+ def ip_v4_network_validator(input_value: Any, /) -> IPv4Network:
200
+ """Assume IPv4Network initialised with a default `strict` argument.
201
+
202
+ See more:
203
+ https://docs.python.org/library/ipaddress.html#ipaddress.IPv4Network
204
+ """
205
+ if isinstance(input_value, IPv4Network):
206
+ return input_value
207
+
208
+ try:
209
+ return IPv4Network(input_value)
210
+ except ValueError:
211
+ raise PydanticCustomError('ip_v4_network', 'Input is not a valid IPv4 network')
212
+
213
+
214
+ def ip_v6_network_validator(input_value: Any, /) -> IPv6Network:
215
+ """Assume IPv6Network initialised with a default `strict` argument.
216
+
217
+ See more:
218
+ https://docs.python.org/library/ipaddress.html#ipaddress.IPv6Network
219
+ """
220
+ if isinstance(input_value, IPv6Network):
221
+ return input_value
222
+
223
+ try:
224
+ return IPv6Network(input_value)
225
+ except ValueError:
226
+ raise PydanticCustomError('ip_v6_network', 'Input is not a valid IPv6 network')
227
+
228
+
229
+ def ip_v4_interface_validator(input_value: Any, /) -> IPv4Interface:
230
+ if isinstance(input_value, IPv4Interface):
231
+ return input_value
232
+
233
+ try:
234
+ return IPv4Interface(input_value)
235
+ except ValueError:
236
+ raise PydanticCustomError('ip_v4_interface', 'Input is not a valid IPv4 interface')
237
+
238
+
239
+ def ip_v6_interface_validator(input_value: Any, /) -> IPv6Interface:
240
+ if isinstance(input_value, IPv6Interface):
241
+ return input_value
242
+
243
+ try:
244
+ return IPv6Interface(input_value)
245
+ except ValueError:
246
+ raise PydanticCustomError('ip_v6_interface', 'Input is not a valid IPv6 interface')
247
+
248
+
249
+ def fraction_validator(input_value: Any, /) -> Fraction:
250
+ if isinstance(input_value, Fraction):
251
+ return input_value
252
+
253
+ try:
254
+ return Fraction(input_value)
255
+ except ValueError:
256
+ raise PydanticCustomError('fraction_parsing', 'Input is not a valid fraction')
257
+
258
+
259
+ def forbid_inf_nan_check(x: Any) -> Any:
260
+ if not math.isfinite(x):
261
+ raise PydanticKnownError('finite_number')
262
+ return x
263
+
264
+
265
+ def _safe_repr(v: Any) -> int | float | str:
266
+ """The context argument for `PydanticKnownError` requires a number or str type, so we do a simple repr() coercion for types like timedelta.
267
+
268
+ See tests/test_types.py::test_annotated_metadata_any_order for some context.
269
+ """
270
+ if isinstance(v, (int, float, str)):
271
+ return v
272
+ return repr(v)
273
+
274
+
275
+ def greater_than_validator(x: Any, gt: Any) -> Any:
276
+ try:
277
+ if not (x > gt):
278
+ raise PydanticKnownError('greater_than', {'gt': _safe_repr(gt)})
279
+ return x
280
+ except TypeError:
281
+ raise TypeError(f"Unable to apply constraint 'gt' to supplied value {x}")
282
+
283
+
284
+ def greater_than_or_equal_validator(x: Any, ge: Any) -> Any:
285
+ try:
286
+ if not (x >= ge):
287
+ raise PydanticKnownError('greater_than_equal', {'ge': _safe_repr(ge)})
288
+ return x
289
+ except TypeError:
290
+ raise TypeError(f"Unable to apply constraint 'ge' to supplied value {x}")
291
+
292
+
293
+ def less_than_validator(x: Any, lt: Any) -> Any:
294
+ try:
295
+ if not (x < lt):
296
+ raise PydanticKnownError('less_than', {'lt': _safe_repr(lt)})
297
+ return x
298
+ except TypeError:
299
+ raise TypeError(f"Unable to apply constraint 'lt' to supplied value {x}")
300
+
301
+
302
+ def less_than_or_equal_validator(x: Any, le: Any) -> Any:
303
+ try:
304
+ if not (x <= le):
305
+ raise PydanticKnownError('less_than_equal', {'le': _safe_repr(le)})
306
+ return x
307
+ except TypeError:
308
+ raise TypeError(f"Unable to apply constraint 'le' to supplied value {x}")
309
+
310
+
311
+ def multiple_of_validator(x: Any, multiple_of: Any) -> Any:
312
+ try:
313
+ if x % multiple_of:
314
+ raise PydanticKnownError('multiple_of', {'multiple_of': _safe_repr(multiple_of)})
315
+ return x
316
+ except TypeError:
317
+ raise TypeError(f"Unable to apply constraint 'multiple_of' to supplied value {x}")
318
+
319
+
320
+ def min_length_validator(x: Any, min_length: Any) -> Any:
321
+ try:
322
+ if not (len(x) >= min_length):
323
+ raise PydanticKnownError(
324
+ 'too_short', {'field_type': 'Value', 'min_length': min_length, 'actual_length': len(x)}
325
+ )
326
+ return x
327
+ except TypeError:
328
+ raise TypeError(f"Unable to apply constraint 'min_length' to supplied value {x}")
329
+
330
+
331
+ def max_length_validator(x: Any, max_length: Any) -> Any:
332
+ try:
333
+ if len(x) > max_length:
334
+ raise PydanticKnownError(
335
+ 'too_long',
336
+ {'field_type': 'Value', 'max_length': max_length, 'actual_length': len(x)},
337
+ )
338
+ return x
339
+ except TypeError:
340
+ raise TypeError(f"Unable to apply constraint 'max_length' to supplied value {x}")
341
+
342
+
343
+ def _extract_decimal_digits_info(decimal: Decimal) -> tuple[int, int]:
344
+ """Compute the total number of digits and decimal places for a given [`Decimal`][decimal.Decimal] instance.
345
+
346
+ This function handles both normalized and non-normalized Decimal instances.
347
+ Example: Decimal('1.230') -> 4 digits, 3 decimal places
348
+
349
+ Args:
350
+ decimal (Decimal): The decimal number to analyze.
351
+
352
+ Returns:
353
+ tuple[int, int]: A tuple containing the number of decimal places and total digits.
354
+
355
+ Though this could be divided into two separate functions, the logic is easier to follow if we couple the computation
356
+ of the number of decimals and digits together.
357
+ """
358
+ try:
359
+ decimal_tuple = decimal.as_tuple()
360
+
361
+ assert isinstance(decimal_tuple.exponent, int)
362
+
363
+ exponent = decimal_tuple.exponent
364
+ num_digits = len(decimal_tuple.digits)
365
+
366
+ if exponent >= 0:
367
+ # A positive exponent adds that many trailing zeros
368
+ # Ex: digit_tuple=(1, 2, 3), exponent=2 -> 12300 -> 0 decimal places, 5 digits
369
+ num_digits += exponent
370
+ decimal_places = 0
371
+ else:
372
+ # If the absolute value of the negative exponent is larger than the
373
+ # number of digits, then it's the same as the number of digits,
374
+ # because it'll consume all the digits in digit_tuple and then
375
+ # add abs(exponent) - len(digit_tuple) leading zeros after the decimal point.
376
+ # Ex: digit_tuple=(1, 2, 3), exponent=-2 -> 1.23 -> 2 decimal places, 3 digits
377
+ # Ex: digit_tuple=(1, 2, 3), exponent=-4 -> 0.0123 -> 4 decimal places, 4 digits
378
+ decimal_places = abs(exponent)
379
+ num_digits = max(num_digits, decimal_places)
380
+
381
+ return decimal_places, num_digits
382
+ except (AssertionError, AttributeError):
383
+ raise TypeError(f'Unable to extract decimal digits info from supplied value {decimal}')
384
+
385
+
386
+ def max_digits_validator(x: Any, max_digits: Any) -> Any:
387
+ try:
388
+ _, num_digits = _extract_decimal_digits_info(x)
389
+ _, normalized_num_digits = _extract_decimal_digits_info(x.normalize())
390
+ if (num_digits > max_digits) and (normalized_num_digits > max_digits):
391
+ raise PydanticKnownError(
392
+ 'decimal_max_digits',
393
+ {'max_digits': max_digits},
394
+ )
395
+ return x
396
+ except TypeError:
397
+ raise TypeError(f"Unable to apply constraint 'max_digits' to supplied value {x}")
398
+
399
+
400
+ def decimal_places_validator(x: Any, decimal_places: Any) -> Any:
401
+ try:
402
+ decimal_places_, _ = _extract_decimal_digits_info(x)
403
+ if decimal_places_ > decimal_places:
404
+ normalized_decimal_places, _ = _extract_decimal_digits_info(x.normalize())
405
+ if normalized_decimal_places > decimal_places:
406
+ raise PydanticKnownError(
407
+ 'decimal_max_places',
408
+ {'decimal_places': decimal_places},
409
+ )
410
+ return x
411
+ except TypeError:
412
+ raise TypeError(f"Unable to apply constraint 'decimal_places' to supplied value {x}")
413
+
414
+
415
+ def deque_validator(input_value: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> collections.deque[Any]:
416
+ return collections.deque(handler(input_value), maxlen=getattr(input_value, 'maxlen', None))
417
+
418
+
419
+ def defaultdict_validator(
420
+ input_value: Any, handler: core_schema.ValidatorFunctionWrapHandler, default_default_factory: Callable[[], Any]
421
+ ) -> collections.defaultdict[Any, Any]:
422
+ if isinstance(input_value, collections.defaultdict):
423
+ default_factory = input_value.default_factory
424
+ return collections.defaultdict(default_factory, handler(input_value))
425
+ else:
426
+ return collections.defaultdict(default_default_factory, handler(input_value))
427
+
428
+
429
+ def get_defaultdict_default_default_factory(values_source_type: Any) -> Callable[[], Any]:
430
+ FieldInfo = import_cached_field_info()
431
+
432
+ values_type_origin = get_origin(values_source_type)
433
+
434
+ def infer_default() -> Callable[[], Any]:
435
+ allowed_default_types: dict[Any, Any] = {
436
+ tuple: tuple,
437
+ collections.abc.Sequence: tuple,
438
+ collections.abc.MutableSequence: list,
439
+ list: list,
440
+ typing.Sequence: list,
441
+ set: set,
442
+ typing.MutableSet: set,
443
+ collections.abc.MutableSet: set,
444
+ collections.abc.Set: frozenset,
445
+ typing.MutableMapping: dict,
446
+ typing.Mapping: dict,
447
+ collections.abc.Mapping: dict,
448
+ collections.abc.MutableMapping: dict,
449
+ float: float,
450
+ int: int,
451
+ str: str,
452
+ bool: bool,
453
+ }
454
+ values_type = values_type_origin or values_source_type
455
+ instructions = 'set using `DefaultDict[..., Annotated[..., Field(default_factory=...)]]`'
456
+ if typing_objects.is_typevar(values_type):
457
+
458
+ def type_var_default_factory() -> None:
459
+ raise RuntimeError(
460
+ 'Generic defaultdict cannot be used without a concrete value type or an'
461
+ ' explicit default factory, ' + instructions
462
+ )
463
+
464
+ return type_var_default_factory
465
+ elif values_type not in allowed_default_types:
466
+ # a somewhat subjective set of types that have reasonable default values
467
+ allowed_msg = ', '.join([t.__name__ for t in set(allowed_default_types.values())])
468
+ raise PydanticSchemaGenerationError(
469
+ f'Unable to infer a default factory for keys of type {values_source_type}.'
470
+ f' Only {allowed_msg} are supported, other types require an explicit default factory'
471
+ ' ' + instructions
472
+ )
473
+ return allowed_default_types[values_type]
474
+
475
+ # Assume Annotated[..., Field(...)]
476
+ if typing_objects.is_annotated(values_type_origin):
477
+ field_info = next((v for v in get_args(values_source_type) if isinstance(v, FieldInfo)), None)
478
+ else:
479
+ field_info = None
480
+ if field_info and field_info.default_factory:
481
+ # Assume the default factory does not take any argument:
482
+ default_default_factory = cast(Callable[[], Any], field_info.default_factory)
483
+ else:
484
+ default_default_factory = infer_default()
485
+ return default_default_factory
486
+
487
+
488
+ def validate_str_is_valid_iana_tz(value: Any, /) -> ZoneInfo:
489
+ if isinstance(value, ZoneInfo):
490
+ return value
491
+ try:
492
+ return ZoneInfo(value)
493
+ except (ZoneInfoNotFoundError, ValueError, TypeError):
494
+ raise PydanticCustomError('zoneinfo_str', 'invalid timezone: {value}', {'value': value})
495
+
496
+
497
+ NUMERIC_VALIDATOR_LOOKUP: dict[str, Callable] = {
498
+ 'gt': greater_than_validator,
499
+ 'ge': greater_than_or_equal_validator,
500
+ 'lt': less_than_validator,
501
+ 'le': less_than_or_equal_validator,
502
+ 'multiple_of': multiple_of_validator,
503
+ 'min_length': min_length_validator,
504
+ 'max_length': max_length_validator,
505
+ 'max_digits': max_digits_validator,
506
+ 'decimal_places': decimal_places_validator,
507
+ }
508
+
509
+ IpType = Union[IPv4Address, IPv6Address, IPv4Network, IPv6Network, IPv4Interface, IPv6Interface]
510
+
511
+ IP_VALIDATOR_LOOKUP: dict[type[IpType], Callable] = {
512
+ IPv4Address: ip_v4_address_validator,
513
+ IPv6Address: ip_v6_address_validator,
514
+ IPv4Network: ip_v4_network_validator,
515
+ IPv6Network: ip_v6_network_validator,
516
+ IPv4Interface: ip_v4_interface_validator,
517
+ IPv6Interface: ip_v6_interface_validator,
518
+ }
519
+
520
+ MAPPING_ORIGIN_MAP: dict[Any, Any] = {
521
+ typing.DefaultDict: collections.defaultdict, # noqa: UP006
522
+ collections.defaultdict: collections.defaultdict,
523
+ typing.OrderedDict: collections.OrderedDict, # noqa: UP006
524
+ collections.OrderedDict: collections.OrderedDict,
525
+ typing_extensions.OrderedDict: collections.OrderedDict,
526
+ typing.Counter: collections.Counter,
527
+ collections.Counter: collections.Counter,
528
+ # this doesn't handle subclasses of these
529
+ typing.Mapping: dict,
530
+ typing.MutableMapping: dict,
531
+ # parametrized typing.{Mutable}Mapping creates one of these
532
+ collections.abc.Mapping: dict,
533
+ collections.abc.MutableMapping: dict,
534
+ }
.mcp-venv/lib/python3.13/site-packages/pydantic/_migration.py ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from typing import Any, Callable
3
+
4
+ from pydantic.warnings import PydanticDeprecatedSince20
5
+
6
+ from .version import version_short
7
+
8
+ MOVED_IN_V2 = {
9
+ 'pydantic.utils:version_info': 'pydantic.version:version_info',
10
+ 'pydantic.error_wrappers:ValidationError': 'pydantic:ValidationError',
11
+ 'pydantic.utils:to_camel': 'pydantic.alias_generators:to_pascal',
12
+ 'pydantic.utils:to_lower_camel': 'pydantic.alias_generators:to_camel',
13
+ 'pydantic:PyObject': 'pydantic.types:ImportString',
14
+ 'pydantic.types:PyObject': 'pydantic.types:ImportString',
15
+ 'pydantic.generics:GenericModel': 'pydantic.BaseModel',
16
+ }
17
+
18
+ DEPRECATED_MOVED_IN_V2 = {
19
+ 'pydantic.tools:schema_of': 'pydantic.deprecated.tools:schema_of',
20
+ 'pydantic.tools:parse_obj_as': 'pydantic.deprecated.tools:parse_obj_as',
21
+ 'pydantic.tools:schema_json_of': 'pydantic.deprecated.tools:schema_json_of',
22
+ 'pydantic.json:pydantic_encoder': 'pydantic.deprecated.json:pydantic_encoder',
23
+ 'pydantic:validate_arguments': 'pydantic.deprecated.decorator:validate_arguments',
24
+ 'pydantic.json:custom_pydantic_encoder': 'pydantic.deprecated.json:custom_pydantic_encoder',
25
+ 'pydantic.json:timedelta_isoformat': 'pydantic.deprecated.json:timedelta_isoformat',
26
+ 'pydantic.decorator:validate_arguments': 'pydantic.deprecated.decorator:validate_arguments',
27
+ 'pydantic.class_validators:validator': 'pydantic.deprecated.class_validators:validator',
28
+ 'pydantic.class_validators:root_validator': 'pydantic.deprecated.class_validators:root_validator',
29
+ 'pydantic.config:BaseConfig': 'pydantic.deprecated.config:BaseConfig',
30
+ 'pydantic.config:Extra': 'pydantic.deprecated.config:Extra',
31
+ }
32
+
33
+ REDIRECT_TO_V1 = {
34
+ f'pydantic.utils:{obj}': f'pydantic.v1.utils:{obj}'
35
+ for obj in (
36
+ 'deep_update',
37
+ 'GetterDict',
38
+ 'lenient_issubclass',
39
+ 'lenient_isinstance',
40
+ 'is_valid_field',
41
+ 'update_not_none',
42
+ 'import_string',
43
+ 'Representation',
44
+ 'ROOT_KEY',
45
+ 'smart_deepcopy',
46
+ 'sequence_like',
47
+ )
48
+ }
49
+
50
+
51
+ REMOVED_IN_V2 = {
52
+ 'pydantic:ConstrainedBytes',
53
+ 'pydantic:ConstrainedDate',
54
+ 'pydantic:ConstrainedDecimal',
55
+ 'pydantic:ConstrainedFloat',
56
+ 'pydantic:ConstrainedFrozenSet',
57
+ 'pydantic:ConstrainedInt',
58
+ 'pydantic:ConstrainedList',
59
+ 'pydantic:ConstrainedSet',
60
+ 'pydantic:ConstrainedStr',
61
+ 'pydantic:JsonWrapper',
62
+ 'pydantic:NoneBytes',
63
+ 'pydantic:NoneStr',
64
+ 'pydantic:NoneStrBytes',
65
+ 'pydantic:Protocol',
66
+ 'pydantic:Required',
67
+ 'pydantic:StrBytes',
68
+ 'pydantic:compiled',
69
+ 'pydantic.config:get_config',
70
+ 'pydantic.config:inherit_config',
71
+ 'pydantic.config:prepare_config',
72
+ 'pydantic:create_model_from_namedtuple',
73
+ 'pydantic:create_model_from_typeddict',
74
+ 'pydantic.dataclasses:create_pydantic_model_from_dataclass',
75
+ 'pydantic.dataclasses:make_dataclass_validator',
76
+ 'pydantic.dataclasses:set_validation',
77
+ 'pydantic.datetime_parse:parse_date',
78
+ 'pydantic.datetime_parse:parse_time',
79
+ 'pydantic.datetime_parse:parse_datetime',
80
+ 'pydantic.datetime_parse:parse_duration',
81
+ 'pydantic.error_wrappers:ErrorWrapper',
82
+ 'pydantic.errors:AnyStrMaxLengthError',
83
+ 'pydantic.errors:AnyStrMinLengthError',
84
+ 'pydantic.errors:ArbitraryTypeError',
85
+ 'pydantic.errors:BoolError',
86
+ 'pydantic.errors:BytesError',
87
+ 'pydantic.errors:CallableError',
88
+ 'pydantic.errors:ClassError',
89
+ 'pydantic.errors:ColorError',
90
+ 'pydantic.errors:ConfigError',
91
+ 'pydantic.errors:DataclassTypeError',
92
+ 'pydantic.errors:DateError',
93
+ 'pydantic.errors:DateNotInTheFutureError',
94
+ 'pydantic.errors:DateNotInThePastError',
95
+ 'pydantic.errors:DateTimeError',
96
+ 'pydantic.errors:DecimalError',
97
+ 'pydantic.errors:DecimalIsNotFiniteError',
98
+ 'pydantic.errors:DecimalMaxDigitsError',
99
+ 'pydantic.errors:DecimalMaxPlacesError',
100
+ 'pydantic.errors:DecimalWholeDigitsError',
101
+ 'pydantic.errors:DictError',
102
+ 'pydantic.errors:DurationError',
103
+ 'pydantic.errors:EmailError',
104
+ 'pydantic.errors:EnumError',
105
+ 'pydantic.errors:EnumMemberError',
106
+ 'pydantic.errors:ExtraError',
107
+ 'pydantic.errors:FloatError',
108
+ 'pydantic.errors:FrozenSetError',
109
+ 'pydantic.errors:FrozenSetMaxLengthError',
110
+ 'pydantic.errors:FrozenSetMinLengthError',
111
+ 'pydantic.errors:HashableError',
112
+ 'pydantic.errors:IPv4AddressError',
113
+ 'pydantic.errors:IPv4InterfaceError',
114
+ 'pydantic.errors:IPv4NetworkError',
115
+ 'pydantic.errors:IPv6AddressError',
116
+ 'pydantic.errors:IPv6InterfaceError',
117
+ 'pydantic.errors:IPv6NetworkError',
118
+ 'pydantic.errors:IPvAnyAddressError',
119
+ 'pydantic.errors:IPvAnyInterfaceError',
120
+ 'pydantic.errors:IPvAnyNetworkError',
121
+ 'pydantic.errors:IntEnumError',
122
+ 'pydantic.errors:IntegerError',
123
+ 'pydantic.errors:InvalidByteSize',
124
+ 'pydantic.errors:InvalidByteSizeUnit',
125
+ 'pydantic.errors:InvalidDiscriminator',
126
+ 'pydantic.errors:InvalidLengthForBrand',
127
+ 'pydantic.errors:JsonError',
128
+ 'pydantic.errors:JsonTypeError',
129
+ 'pydantic.errors:ListError',
130
+ 'pydantic.errors:ListMaxLengthError',
131
+ 'pydantic.errors:ListMinLengthError',
132
+ 'pydantic.errors:ListUniqueItemsError',
133
+ 'pydantic.errors:LuhnValidationError',
134
+ 'pydantic.errors:MissingDiscriminator',
135
+ 'pydantic.errors:MissingError',
136
+ 'pydantic.errors:NoneIsAllowedError',
137
+ 'pydantic.errors:NoneIsNotAllowedError',
138
+ 'pydantic.errors:NotDigitError',
139
+ 'pydantic.errors:NotNoneError',
140
+ 'pydantic.errors:NumberNotGeError',
141
+ 'pydantic.errors:NumberNotGtError',
142
+ 'pydantic.errors:NumberNotLeError',
143
+ 'pydantic.errors:NumberNotLtError',
144
+ 'pydantic.errors:NumberNotMultipleError',
145
+ 'pydantic.errors:PathError',
146
+ 'pydantic.errors:PathNotADirectoryError',
147
+ 'pydantic.errors:PathNotAFileError',
148
+ 'pydantic.errors:PathNotExistsError',
149
+ 'pydantic.errors:PatternError',
150
+ 'pydantic.errors:PyObjectError',
151
+ 'pydantic.errors:PydanticTypeError',
152
+ 'pydantic.errors:PydanticValueError',
153
+ 'pydantic.errors:SequenceError',
154
+ 'pydantic.errors:SetError',
155
+ 'pydantic.errors:SetMaxLengthError',
156
+ 'pydantic.errors:SetMinLengthError',
157
+ 'pydantic.errors:StrError',
158
+ 'pydantic.errors:StrRegexError',
159
+ 'pydantic.errors:StrictBoolError',
160
+ 'pydantic.errors:SubclassError',
161
+ 'pydantic.errors:TimeError',
162
+ 'pydantic.errors:TupleError',
163
+ 'pydantic.errors:TupleLengthError',
164
+ 'pydantic.errors:UUIDError',
165
+ 'pydantic.errors:UUIDVersionError',
166
+ 'pydantic.errors:UrlError',
167
+ 'pydantic.errors:UrlExtraError',
168
+ 'pydantic.errors:UrlHostError',
169
+ 'pydantic.errors:UrlHostTldError',
170
+ 'pydantic.errors:UrlPortError',
171
+ 'pydantic.errors:UrlSchemeError',
172
+ 'pydantic.errors:UrlSchemePermittedError',
173
+ 'pydantic.errors:UrlUserInfoError',
174
+ 'pydantic.errors:WrongConstantError',
175
+ 'pydantic.main:validate_model',
176
+ 'pydantic.networks:stricturl',
177
+ 'pydantic:parse_file_as',
178
+ 'pydantic:parse_raw_as',
179
+ 'pydantic:stricturl',
180
+ 'pydantic.tools:parse_file_as',
181
+ 'pydantic.tools:parse_raw_as',
182
+ 'pydantic.types:ConstrainedBytes',
183
+ 'pydantic.types:ConstrainedDate',
184
+ 'pydantic.types:ConstrainedDecimal',
185
+ 'pydantic.types:ConstrainedFloat',
186
+ 'pydantic.types:ConstrainedFrozenSet',
187
+ 'pydantic.types:ConstrainedInt',
188
+ 'pydantic.types:ConstrainedList',
189
+ 'pydantic.types:ConstrainedSet',
190
+ 'pydantic.types:ConstrainedStr',
191
+ 'pydantic.types:JsonWrapper',
192
+ 'pydantic.types:NoneBytes',
193
+ 'pydantic.types:NoneStr',
194
+ 'pydantic.types:NoneStrBytes',
195
+ 'pydantic.types:StrBytes',
196
+ 'pydantic.typing:evaluate_forwardref',
197
+ 'pydantic.typing:AbstractSetIntStr',
198
+ 'pydantic.typing:AnyCallable',
199
+ 'pydantic.typing:AnyClassMethod',
200
+ 'pydantic.typing:CallableGenerator',
201
+ 'pydantic.typing:DictAny',
202
+ 'pydantic.typing:DictIntStrAny',
203
+ 'pydantic.typing:DictStrAny',
204
+ 'pydantic.typing:IntStr',
205
+ 'pydantic.typing:ListStr',
206
+ 'pydantic.typing:MappingIntStrAny',
207
+ 'pydantic.typing:NoArgAnyCallable',
208
+ 'pydantic.typing:NoneType',
209
+ 'pydantic.typing:ReprArgs',
210
+ 'pydantic.typing:SetStr',
211
+ 'pydantic.typing:StrPath',
212
+ 'pydantic.typing:TupleGenerator',
213
+ 'pydantic.typing:WithArgsTypes',
214
+ 'pydantic.typing:all_literal_values',
215
+ 'pydantic.typing:display_as_type',
216
+ 'pydantic.typing:get_all_type_hints',
217
+ 'pydantic.typing:get_args',
218
+ 'pydantic.typing:get_origin',
219
+ 'pydantic.typing:get_sub_types',
220
+ 'pydantic.typing:is_callable_type',
221
+ 'pydantic.typing:is_classvar',
222
+ 'pydantic.typing:is_finalvar',
223
+ 'pydantic.typing:is_literal_type',
224
+ 'pydantic.typing:is_namedtuple',
225
+ 'pydantic.typing:is_new_type',
226
+ 'pydantic.typing:is_none_type',
227
+ 'pydantic.typing:is_typeddict',
228
+ 'pydantic.typing:is_typeddict_special',
229
+ 'pydantic.typing:is_union',
230
+ 'pydantic.typing:new_type_supertype',
231
+ 'pydantic.typing:resolve_annotations',
232
+ 'pydantic.typing:typing_base',
233
+ 'pydantic.typing:update_field_forward_refs',
234
+ 'pydantic.typing:update_model_forward_refs',
235
+ 'pydantic.utils:ClassAttribute',
236
+ 'pydantic.utils:DUNDER_ATTRIBUTES',
237
+ 'pydantic.utils:PyObjectStr',
238
+ 'pydantic.utils:ValueItems',
239
+ 'pydantic.utils:almost_equal_floats',
240
+ 'pydantic.utils:get_discriminator_alias_and_values',
241
+ 'pydantic.utils:get_model',
242
+ 'pydantic.utils:get_unique_discriminator_alias',
243
+ 'pydantic.utils:in_ipython',
244
+ 'pydantic.utils:is_valid_identifier',
245
+ 'pydantic.utils:path_type',
246
+ 'pydantic.utils:validate_field_name',
247
+ 'pydantic:validate_model',
248
+ }
249
+
250
+
251
+ def getattr_migration(module: str) -> Callable[[str], Any]:
252
+ """Implement PEP 562 for objects that were either moved or removed on the migration
253
+ to V2.
254
+
255
+ Args:
256
+ module: The module name.
257
+
258
+ Returns:
259
+ A callable that will raise an error if the object is not found.
260
+ """
261
+ # This avoids circular import with errors.py.
262
+ from .errors import PydanticImportError
263
+
264
+ def wrapper(name: str) -> object:
265
+ """Raise an error if the object is not found, or warn if it was moved.
266
+
267
+ In case it was moved, it still returns the object.
268
+
269
+ Args:
270
+ name: The object name.
271
+
272
+ Returns:
273
+ The object.
274
+ """
275
+ if name == '__path__':
276
+ raise AttributeError(f'module {module!r} has no attribute {name!r}')
277
+
278
+ import warnings
279
+
280
+ from ._internal._validators import import_string
281
+
282
+ import_path = f'{module}:{name}'
283
+ if import_path in MOVED_IN_V2.keys():
284
+ new_location = MOVED_IN_V2[import_path]
285
+ warnings.warn(
286
+ f'`{import_path}` has been moved to `{new_location}`.',
287
+ category=PydanticDeprecatedSince20,
288
+ stacklevel=2,
289
+ )
290
+ return import_string(MOVED_IN_V2[import_path])
291
+ if import_path in DEPRECATED_MOVED_IN_V2:
292
+ # skip the warning here because a deprecation warning will be raised elsewhere
293
+ return import_string(DEPRECATED_MOVED_IN_V2[import_path])
294
+ if import_path in REDIRECT_TO_V1:
295
+ new_location = REDIRECT_TO_V1[import_path]
296
+ warnings.warn(
297
+ f'`{import_path}` has been removed. We are importing from `{new_location}` instead.'
298
+ 'See the migration guide for more details: https://docs.pydantic.dev/latest/migration/',
299
+ category=PydanticDeprecatedSince20,
300
+ stacklevel=2,
301
+ )
302
+ return import_string(REDIRECT_TO_V1[import_path])
303
+ if import_path == 'pydantic:BaseSettings':
304
+ raise PydanticImportError(
305
+ '`BaseSettings` has been moved to the `pydantic-settings` package. '
306
+ f'See https://docs.pydantic.dev/{version_short()}/migration/#basesettings-has-moved-to-pydantic-settings '
307
+ 'for more details.'
308
+ )
309
+ if import_path in REMOVED_IN_V2:
310
+ raise PydanticImportError(f'`{import_path}` has been removed in V2.')
311
+ globals: dict[str, Any] = sys.modules[module].__dict__
312
+ if name in globals:
313
+ return globals[name]
314
+ raise AttributeError(f'module {module!r} has no attribute {name!r}')
315
+
316
+ return wrapper
.mcp-venv/lib/python3.13/site-packages/pydantic/alias_generators.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Alias generators for converting between different capitalization conventions."""
2
+
3
+ import re
4
+
5
+ __all__ = ('to_pascal', 'to_camel', 'to_snake')
6
+
7
+ # TODO: in V3, change the argument names to be more descriptive
8
+ # Generally, don't only convert from snake_case, or name the functions
9
+ # more specifically like snake_to_camel.
10
+
11
+
12
+ def to_pascal(snake: str) -> str:
13
+ """Convert a snake_case string to PascalCase.
14
+
15
+ Args:
16
+ snake: The string to convert.
17
+
18
+ Returns:
19
+ The PascalCase string.
20
+ """
21
+ camel = snake.title()
22
+ return re.sub('([0-9A-Za-z])_(?=[0-9A-Z])', lambda m: m.group(1), camel)
23
+
24
+
25
+ def to_camel(snake: str) -> str:
26
+ """Convert a snake_case string to camelCase.
27
+
28
+ Args:
29
+ snake: The string to convert.
30
+
31
+ Returns:
32
+ The converted camelCase string.
33
+ """
34
+ # If the string is already in camelCase and does not contain a digit followed
35
+ # by a lowercase letter, return it as it is
36
+ if re.match('^[a-z]+[A-Za-z0-9]*$', snake) and not re.search(r'\d[a-z]', snake):
37
+ return snake
38
+
39
+ camel = to_pascal(snake)
40
+ return re.sub('(^_*[A-Z])', lambda m: m.group(1).lower(), camel)
41
+
42
+
43
+ def to_snake(camel: str) -> str:
44
+ """Convert a PascalCase, camelCase, or kebab-case string to snake_case.
45
+
46
+ Args:
47
+ camel: The string to convert.
48
+
49
+ Returns:
50
+ The converted string in snake_case.
51
+ """
52
+ # Handle the sequence of uppercase letters followed by a lowercase letter
53
+ snake = re.sub(r'([A-Z]+)([A-Z][a-z])', lambda m: f'{m.group(1)}_{m.group(2)}', camel)
54
+ # Insert an underscore between a lowercase letter and an uppercase letter
55
+ snake = re.sub(r'([a-z])([A-Z])', lambda m: f'{m.group(1)}_{m.group(2)}', snake)
56
+ # Insert an underscore between a digit and an uppercase letter
57
+ snake = re.sub(r'([0-9])([A-Z])', lambda m: f'{m.group(1)}_{m.group(2)}', snake)
58
+ # Insert an underscore between a lowercase letter and a digit
59
+ snake = re.sub(r'([a-z])([0-9])', lambda m: f'{m.group(1)}_{m.group(2)}', snake)
60
+ # Replace hyphens with underscores to handle kebab-case
61
+ snake = snake.replace('-', '_')
62
+ return snake.lower()
.mcp-venv/lib/python3.13/site-packages/pydantic/aliases.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Support for alias configurations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ from typing import Any, Callable, Literal
7
+
8
+ from pydantic_core import PydanticUndefined
9
+
10
+ from ._internal import _internal_dataclass
11
+
12
+ __all__ = ('AliasGenerator', 'AliasPath', 'AliasChoices')
13
+
14
+
15
+ @dataclasses.dataclass(**_internal_dataclass.slots_true)
16
+ class AliasPath:
17
+ """!!! abstract "Usage Documentation"
18
+ [`AliasPath` and `AliasChoices`](../concepts/alias.md#aliaspath-and-aliaschoices)
19
+
20
+ A data class used by `validation_alias` as a convenience to create aliases.
21
+
22
+ Attributes:
23
+ path: A list of string or integer aliases.
24
+ """
25
+
26
+ path: list[int | str]
27
+
28
+ def __init__(self, first_arg: str, *args: str | int) -> None:
29
+ self.path = [first_arg] + list(args)
30
+
31
+ def convert_to_aliases(self) -> list[str | int]:
32
+ """Converts arguments to a list of string or integer aliases.
33
+
34
+ Returns:
35
+ The list of aliases.
36
+ """
37
+ return self.path
38
+
39
+ def search_dict_for_path(self, d: dict) -> Any:
40
+ """Searches a dictionary for the path specified by the alias.
41
+
42
+ Returns:
43
+ The value at the specified path, or `PydanticUndefined` if the path is not found.
44
+ """
45
+ v = d
46
+ for k in self.path:
47
+ if isinstance(v, str):
48
+ # disallow indexing into a str, like for AliasPath('x', 0) and x='abc'
49
+ return PydanticUndefined
50
+ try:
51
+ v = v[k]
52
+ except (KeyError, IndexError, TypeError):
53
+ return PydanticUndefined
54
+ return v
55
+
56
+
57
+ @dataclasses.dataclass(**_internal_dataclass.slots_true)
58
+ class AliasChoices:
59
+ """!!! abstract "Usage Documentation"
60
+ [`AliasPath` and `AliasChoices`](../concepts/alias.md#aliaspath-and-aliaschoices)
61
+
62
+ A data class used by `validation_alias` as a convenience to create aliases.
63
+
64
+ Attributes:
65
+ choices: A list containing a string or `AliasPath`.
66
+ """
67
+
68
+ choices: list[str | AliasPath]
69
+
70
+ def __init__(self, first_choice: str | AliasPath, *choices: str | AliasPath) -> None:
71
+ self.choices = [first_choice] + list(choices)
72
+
73
+ def convert_to_aliases(self) -> list[list[str | int]]:
74
+ """Converts arguments to a list of lists containing string or integer aliases.
75
+
76
+ Returns:
77
+ The list of aliases.
78
+ """
79
+ aliases: list[list[str | int]] = []
80
+ for c in self.choices:
81
+ if isinstance(c, AliasPath):
82
+ aliases.append(c.convert_to_aliases())
83
+ else:
84
+ aliases.append([c])
85
+ return aliases
86
+
87
+
88
+ @dataclasses.dataclass(**_internal_dataclass.slots_true)
89
+ class AliasGenerator:
90
+ """!!! abstract "Usage Documentation"
91
+ [Using an `AliasGenerator`](../concepts/alias.md#using-an-aliasgenerator)
92
+
93
+ A data class used by `alias_generator` as a convenience to create various aliases.
94
+
95
+ Attributes:
96
+ alias: A callable that takes a field name and returns an alias for it.
97
+ validation_alias: A callable that takes a field name and returns a validation alias for it.
98
+ serialization_alias: A callable that takes a field name and returns a serialization alias for it.
99
+ """
100
+
101
+ alias: Callable[[str], str] | None = None
102
+ validation_alias: Callable[[str], str | AliasPath | AliasChoices] | None = None
103
+ serialization_alias: Callable[[str], str] | None = None
104
+
105
+ def _generate_alias(
106
+ self,
107
+ alias_kind: Literal['alias', 'validation_alias', 'serialization_alias'],
108
+ allowed_types: tuple[type[str] | type[AliasPath] | type[AliasChoices], ...],
109
+ field_name: str,
110
+ ) -> str | AliasPath | AliasChoices | None:
111
+ """Generate an alias of the specified kind. Returns None if the alias generator is None.
112
+
113
+ Raises:
114
+ TypeError: If the alias generator produces an invalid type.
115
+ """
116
+ alias = None
117
+ if alias_generator := getattr(self, alias_kind):
118
+ alias = alias_generator(field_name)
119
+ if alias and not isinstance(alias, allowed_types):
120
+ raise TypeError(
121
+ f'Invalid `{alias_kind}` type. `{alias_kind}` generator must produce one of `{allowed_types}`'
122
+ )
123
+ return alias
124
+
125
+ def generate_aliases(self, field_name: str) -> tuple[str | None, str | AliasPath | AliasChoices | None, str | None]:
126
+ """Generate `alias`, `validation_alias`, and `serialization_alias` for a field.
127
+
128
+ Returns:
129
+ A tuple of three aliases - validation, alias, and serialization.
130
+ """
131
+ alias = self._generate_alias('alias', (str,), field_name)
132
+ validation_alias = self._generate_alias('validation_alias', (str, AliasChoices, AliasPath), field_name)
133
+ serialization_alias = self._generate_alias('serialization_alias', (str,), field_name)
134
+
135
+ return alias, validation_alias, serialization_alias # type: ignore
.mcp-venv/lib/python3.13/site-packages/pydantic/annotated_handlers.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Type annotations to use with `__get_pydantic_core_schema__` and `__get_pydantic_json_schema__`."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ from typing import TYPE_CHECKING, Any, Union
6
+
7
+ from pydantic_core import core_schema
8
+
9
+ if TYPE_CHECKING:
10
+ from ._internal._namespace_utils import NamespacesTuple
11
+ from .json_schema import JsonSchemaMode, JsonSchemaValue
12
+
13
+ CoreSchemaOrField = Union[
14
+ core_schema.CoreSchema,
15
+ core_schema.ModelField,
16
+ core_schema.DataclassField,
17
+ core_schema.TypedDictField,
18
+ core_schema.ComputedField,
19
+ ]
20
+
21
+ __all__ = 'GetJsonSchemaHandler', 'GetCoreSchemaHandler'
22
+
23
+
24
+ class GetJsonSchemaHandler:
25
+ """Handler to call into the next JSON schema generation function.
26
+
27
+ Attributes:
28
+ mode: Json schema mode, can be `validation` or `serialization`.
29
+ """
30
+
31
+ mode: JsonSchemaMode
32
+
33
+ def __call__(self, core_schema: CoreSchemaOrField, /) -> JsonSchemaValue:
34
+ """Call the inner handler and get the JsonSchemaValue it returns.
35
+ This will call the next JSON schema modifying function up until it calls
36
+ into `pydantic.json_schema.GenerateJsonSchema`, which will raise a
37
+ `pydantic.errors.PydanticInvalidForJsonSchema` error if it cannot generate
38
+ a JSON schema.
39
+
40
+ Args:
41
+ core_schema: A `pydantic_core.core_schema.CoreSchema`.
42
+
43
+ Returns:
44
+ JsonSchemaValue: The JSON schema generated by the inner JSON schema modify
45
+ functions.
46
+ """
47
+ raise NotImplementedError
48
+
49
+ def resolve_ref_schema(self, maybe_ref_json_schema: JsonSchemaValue, /) -> JsonSchemaValue:
50
+ """Get the real schema for a `{"$ref": ...}` schema.
51
+ If the schema given is not a `$ref` schema, it will be returned as is.
52
+ This means you don't have to check before calling this function.
53
+
54
+ Args:
55
+ maybe_ref_json_schema: A JsonSchemaValue which may be a `$ref` schema.
56
+
57
+ Raises:
58
+ LookupError: If the ref is not found.
59
+
60
+ Returns:
61
+ JsonSchemaValue: A JsonSchemaValue that has no `$ref`.
62
+ """
63
+ raise NotImplementedError
64
+
65
+
66
+ class GetCoreSchemaHandler:
67
+ """Handler to call into the next CoreSchema schema generation function."""
68
+
69
+ def __call__(self, source_type: Any, /) -> core_schema.CoreSchema:
70
+ """Call the inner handler and get the CoreSchema it returns.
71
+ This will call the next CoreSchema modifying function up until it calls
72
+ into Pydantic's internal schema generation machinery, which will raise a
73
+ `pydantic.errors.PydanticSchemaGenerationError` error if it cannot generate
74
+ a CoreSchema for the given source type.
75
+
76
+ Args:
77
+ source_type: The input type.
78
+
79
+ Returns:
80
+ CoreSchema: The `pydantic-core` CoreSchema generated.
81
+ """
82
+ raise NotImplementedError
83
+
84
+ def generate_schema(self, source_type: Any, /) -> core_schema.CoreSchema:
85
+ """Generate a schema unrelated to the current context.
86
+ Use this function if e.g. you are handling schema generation for a sequence
87
+ and want to generate a schema for its items.
88
+ Otherwise, you may end up doing something like applying a `min_length` constraint
89
+ that was intended for the sequence itself to its items!
90
+
91
+ Args:
92
+ source_type: The input type.
93
+
94
+ Returns:
95
+ CoreSchema: The `pydantic-core` CoreSchema generated.
96
+ """
97
+ raise NotImplementedError
98
+
99
+ def resolve_ref_schema(self, maybe_ref_schema: core_schema.CoreSchema, /) -> core_schema.CoreSchema:
100
+ """Get the real schema for a `definition-ref` schema.
101
+ If the schema given is not a `definition-ref` schema, it will be returned as is.
102
+ This means you don't have to check before calling this function.
103
+
104
+ Args:
105
+ maybe_ref_schema: A `CoreSchema`, `ref`-based or not.
106
+
107
+ Raises:
108
+ LookupError: If the `ref` is not found.
109
+
110
+ Returns:
111
+ A concrete `CoreSchema`.
112
+ """
113
+ raise NotImplementedError
114
+
115
+ @property
116
+ def field_name(self) -> str | None:
117
+ """Get the name of the closest field to this validator."""
118
+ raise NotImplementedError
119
+
120
+ def _get_types_namespace(self) -> NamespacesTuple:
121
+ """Internal method used during type resolution for serializer annotations."""
122
+ raise NotImplementedError
.mcp-venv/lib/python3.13/site-packages/pydantic/class_validators.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """`class_validators` module is a backport module from V1."""
2
+
3
+ from ._migration import getattr_migration
4
+
5
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/color.py ADDED
@@ -0,0 +1,604 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Color definitions are used as per the CSS3
2
+ [CSS Color Module Level 3](http://www.w3.org/TR/css3-color/#svg-color) specification.
3
+
4
+ A few colors have multiple names referring to the sames colors, eg. `grey` and `gray` or `aqua` and `cyan`.
5
+
6
+ In these cases the _last_ color when sorted alphabetically takes preferences,
7
+ eg. `Color((0, 255, 255)).as_named() == 'cyan'` because "cyan" comes after "aqua".
8
+
9
+ Warning: Deprecated
10
+ The `Color` class is deprecated, use `pydantic_extra_types` instead.
11
+ See [`pydantic-extra-types.Color`](../usage/types/extra_types/color_types.md)
12
+ for more information.
13
+ """
14
+
15
+ import math
16
+ import re
17
+ from colorsys import hls_to_rgb, rgb_to_hls
18
+ from typing import Any, Callable, Optional, Union, cast
19
+
20
+ from pydantic_core import CoreSchema, PydanticCustomError, core_schema
21
+ from typing_extensions import deprecated
22
+
23
+ from ._internal import _repr
24
+ from ._internal._schema_generation_shared import GetJsonSchemaHandler as _GetJsonSchemaHandler
25
+ from .json_schema import JsonSchemaValue
26
+ from .warnings import PydanticDeprecatedSince20
27
+
28
+ ColorTuple = Union[tuple[int, int, int], tuple[int, int, int, float]]
29
+ ColorType = Union[ColorTuple, str]
30
+ HslColorTuple = Union[tuple[float, float, float], tuple[float, float, float, float]]
31
+
32
+
33
+ class RGBA:
34
+ """Internal use only as a representation of a color."""
35
+
36
+ __slots__ = 'r', 'g', 'b', 'alpha', '_tuple'
37
+
38
+ def __init__(self, r: float, g: float, b: float, alpha: Optional[float]):
39
+ self.r = r
40
+ self.g = g
41
+ self.b = b
42
+ self.alpha = alpha
43
+
44
+ self._tuple: tuple[float, float, float, Optional[float]] = (r, g, b, alpha)
45
+
46
+ def __getitem__(self, item: Any) -> Any:
47
+ return self._tuple[item]
48
+
49
+
50
+ # these are not compiled here to avoid import slowdown, they'll be compiled the first time they're used, then cached
51
+ _r_255 = r'(\d{1,3}(?:\.\d+)?)'
52
+ _r_comma = r'\s*,\s*'
53
+ _r_alpha = r'(\d(?:\.\d+)?|\.\d+|\d{1,2}%)'
54
+ _r_h = r'(-?\d+(?:\.\d+)?|-?\.\d+)(deg|rad|turn)?'
55
+ _r_sl = r'(\d{1,3}(?:\.\d+)?)%'
56
+ r_hex_short = r'\s*(?:#|0x)?([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?\s*'
57
+ r_hex_long = r'\s*(?:#|0x)?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?\s*'
58
+ # CSS3 RGB examples: rgb(0, 0, 0), rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 50%)
59
+ r_rgb = rf'\s*rgba?\(\s*{_r_255}{_r_comma}{_r_255}{_r_comma}{_r_255}(?:{_r_comma}{_r_alpha})?\s*\)\s*'
60
+ # CSS3 HSL examples: hsl(270, 60%, 50%), hsla(270, 60%, 50%, 0.5), hsla(270, 60%, 50%, 50%)
61
+ r_hsl = rf'\s*hsla?\(\s*{_r_h}{_r_comma}{_r_sl}{_r_comma}{_r_sl}(?:{_r_comma}{_r_alpha})?\s*\)\s*'
62
+ # CSS4 RGB examples: rgb(0 0 0), rgb(0 0 0 / 0.5), rgb(0 0 0 / 50%), rgba(0 0 0 / 50%)
63
+ r_rgb_v4_style = rf'\s*rgba?\(\s*{_r_255}\s+{_r_255}\s+{_r_255}(?:\s*/\s*{_r_alpha})?\s*\)\s*'
64
+ # CSS4 HSL examples: hsl(270 60% 50%), hsl(270 60% 50% / 0.5), hsl(270 60% 50% / 50%), hsla(270 60% 50% / 50%)
65
+ r_hsl_v4_style = rf'\s*hsla?\(\s*{_r_h}\s+{_r_sl}\s+{_r_sl}(?:\s*/\s*{_r_alpha})?\s*\)\s*'
66
+
67
+ # colors where the two hex characters are the same, if all colors match this the short version of hex colors can be used
68
+ repeat_colors = {int(c * 2, 16) for c in '0123456789abcdef'}
69
+ rads = 2 * math.pi
70
+
71
+
72
+ @deprecated(
73
+ 'The `Color` class is deprecated, use `pydantic_extra_types` instead. '
74
+ 'See https://docs.pydantic.dev/latest/api/pydantic_extra_types_color/.',
75
+ category=PydanticDeprecatedSince20,
76
+ )
77
+ class Color(_repr.Representation):
78
+ """Represents a color."""
79
+
80
+ __slots__ = '_original', '_rgba'
81
+
82
+ def __init__(self, value: ColorType) -> None:
83
+ self._rgba: RGBA
84
+ self._original: ColorType
85
+ if isinstance(value, (tuple, list)):
86
+ self._rgba = parse_tuple(value)
87
+ elif isinstance(value, str):
88
+ self._rgba = parse_str(value)
89
+ elif isinstance(value, Color):
90
+ self._rgba = value._rgba
91
+ value = value._original
92
+ else:
93
+ raise PydanticCustomError(
94
+ 'color_error', 'value is not a valid color: value must be a tuple, list or string'
95
+ )
96
+
97
+ # if we've got here value must be a valid color
98
+ self._original = value
99
+
100
+ @classmethod
101
+ def __get_pydantic_json_schema__(
102
+ cls, core_schema: core_schema.CoreSchema, handler: _GetJsonSchemaHandler
103
+ ) -> JsonSchemaValue:
104
+ field_schema = {}
105
+ field_schema.update(type='string', format='color')
106
+ return field_schema
107
+
108
+ def original(self) -> ColorType:
109
+ """Original value passed to `Color`."""
110
+ return self._original
111
+
112
+ def as_named(self, *, fallback: bool = False) -> str:
113
+ """Returns the name of the color if it can be found in `COLORS_BY_VALUE` dictionary,
114
+ otherwise returns the hexadecimal representation of the color or raises `ValueError`.
115
+
116
+ Args:
117
+ fallback: If True, falls back to returning the hexadecimal representation of
118
+ the color instead of raising a ValueError when no named color is found.
119
+
120
+ Returns:
121
+ The name of the color, or the hexadecimal representation of the color.
122
+
123
+ Raises:
124
+ ValueError: When no named color is found and fallback is `False`.
125
+ """
126
+ if self._rgba.alpha is None:
127
+ rgb = cast(tuple[int, int, int], self.as_rgb_tuple())
128
+ try:
129
+ return COLORS_BY_VALUE[rgb]
130
+ except KeyError as e:
131
+ if fallback:
132
+ return self.as_hex()
133
+ else:
134
+ raise ValueError('no named color found, use fallback=True, as_hex() or as_rgb()') from e
135
+ else:
136
+ return self.as_hex()
137
+
138
+ def as_hex(self) -> str:
139
+ """Returns the hexadecimal representation of the color.
140
+
141
+ Hex string representing the color can be 3, 4, 6, or 8 characters depending on whether the string
142
+ a "short" representation of the color is possible and whether there's an alpha channel.
143
+
144
+ Returns:
145
+ The hexadecimal representation of the color.
146
+ """
147
+ values = [float_to_255(c) for c in self._rgba[:3]]
148
+ if self._rgba.alpha is not None:
149
+ values.append(float_to_255(self._rgba.alpha))
150
+
151
+ as_hex = ''.join(f'{v:02x}' for v in values)
152
+ if all(c in repeat_colors for c in values):
153
+ as_hex = ''.join(as_hex[c] for c in range(0, len(as_hex), 2))
154
+ return '#' + as_hex
155
+
156
+ def as_rgb(self) -> str:
157
+ """Color as an `rgb(<r>, <g>, <b>)` or `rgba(<r>, <g>, <b>, <a>)` string."""
158
+ if self._rgba.alpha is None:
159
+ return f'rgb({float_to_255(self._rgba.r)}, {float_to_255(self._rgba.g)}, {float_to_255(self._rgba.b)})'
160
+ else:
161
+ return (
162
+ f'rgba({float_to_255(self._rgba.r)}, {float_to_255(self._rgba.g)}, {float_to_255(self._rgba.b)}, '
163
+ f'{round(self._alpha_float(), 2)})'
164
+ )
165
+
166
+ def as_rgb_tuple(self, *, alpha: Optional[bool] = None) -> ColorTuple:
167
+ """Returns the color as an RGB or RGBA tuple.
168
+
169
+ Args:
170
+ alpha: Whether to include the alpha channel. There are three options for this input:
171
+
172
+ - `None` (default): Include alpha only if it's set. (e.g. not `None`)
173
+ - `True`: Always include alpha.
174
+ - `False`: Always omit alpha.
175
+
176
+ Returns:
177
+ A tuple that contains the values of the red, green, and blue channels in the range 0 to 255.
178
+ If alpha is included, it is in the range 0 to 1.
179
+ """
180
+ r, g, b = (float_to_255(c) for c in self._rgba[:3])
181
+ if alpha is None:
182
+ if self._rgba.alpha is None:
183
+ return r, g, b
184
+ else:
185
+ return r, g, b, self._alpha_float()
186
+ elif alpha:
187
+ return r, g, b, self._alpha_float()
188
+ else:
189
+ # alpha is False
190
+ return r, g, b
191
+
192
+ def as_hsl(self) -> str:
193
+ """Color as an `hsl(<h>, <s>, <l>)` or `hsl(<h>, <s>, <l>, <a>)` string."""
194
+ if self._rgba.alpha is None:
195
+ h, s, li = self.as_hsl_tuple(alpha=False) # type: ignore
196
+ return f'hsl({h * 360:0.0f}, {s:0.0%}, {li:0.0%})'
197
+ else:
198
+ h, s, li, a = self.as_hsl_tuple(alpha=True) # type: ignore
199
+ return f'hsl({h * 360:0.0f}, {s:0.0%}, {li:0.0%}, {round(a, 2)})'
200
+
201
+ def as_hsl_tuple(self, *, alpha: Optional[bool] = None) -> HslColorTuple:
202
+ """Returns the color as an HSL or HSLA tuple.
203
+
204
+ Args:
205
+ alpha: Whether to include the alpha channel.
206
+
207
+ - `None` (default): Include the alpha channel only if it's set (e.g. not `None`).
208
+ - `True`: Always include alpha.
209
+ - `False`: Always omit alpha.
210
+
211
+ Returns:
212
+ The color as a tuple of hue, saturation, lightness, and alpha (if included).
213
+ All elements are in the range 0 to 1.
214
+
215
+ Note:
216
+ This is HSL as used in HTML and most other places, not HLS as used in Python's `colorsys`.
217
+ """
218
+ h, l, s = rgb_to_hls(self._rgba.r, self._rgba.g, self._rgba.b) # noqa: E741
219
+ if alpha is None:
220
+ if self._rgba.alpha is None:
221
+ return h, s, l
222
+ else:
223
+ return h, s, l, self._alpha_float()
224
+ if alpha:
225
+ return h, s, l, self._alpha_float()
226
+ else:
227
+ # alpha is False
228
+ return h, s, l
229
+
230
+ def _alpha_float(self) -> float:
231
+ return 1 if self._rgba.alpha is None else self._rgba.alpha
232
+
233
+ @classmethod
234
+ def __get_pydantic_core_schema__(
235
+ cls, source: type[Any], handler: Callable[[Any], CoreSchema]
236
+ ) -> core_schema.CoreSchema:
237
+ return core_schema.with_info_plain_validator_function(
238
+ cls._validate, serialization=core_schema.to_string_ser_schema()
239
+ )
240
+
241
+ @classmethod
242
+ def _validate(cls, __input_value: Any, _: Any) -> 'Color':
243
+ return cls(__input_value)
244
+
245
+ def __str__(self) -> str:
246
+ return self.as_named(fallback=True)
247
+
248
+ def __repr_args__(self) -> '_repr.ReprArgs':
249
+ return [(None, self.as_named(fallback=True))] + [('rgb', self.as_rgb_tuple())]
250
+
251
+ def __eq__(self, other: Any) -> bool:
252
+ return isinstance(other, Color) and self.as_rgb_tuple() == other.as_rgb_tuple()
253
+
254
+ def __hash__(self) -> int:
255
+ return hash(self.as_rgb_tuple())
256
+
257
+
258
+ def parse_tuple(value: tuple[Any, ...]) -> RGBA:
259
+ """Parse a tuple or list to get RGBA values.
260
+
261
+ Args:
262
+ value: A tuple or list.
263
+
264
+ Returns:
265
+ An `RGBA` tuple parsed from the input tuple.
266
+
267
+ Raises:
268
+ PydanticCustomError: If tuple is not valid.
269
+ """
270
+ if len(value) == 3:
271
+ r, g, b = (parse_color_value(v) for v in value)
272
+ return RGBA(r, g, b, None)
273
+ elif len(value) == 4:
274
+ r, g, b = (parse_color_value(v) for v in value[:3])
275
+ return RGBA(r, g, b, parse_float_alpha(value[3]))
276
+ else:
277
+ raise PydanticCustomError('color_error', 'value is not a valid color: tuples must have length 3 or 4')
278
+
279
+
280
+ def parse_str(value: str) -> RGBA:
281
+ """Parse a string representing a color to an RGBA tuple.
282
+
283
+ Possible formats for the input string include:
284
+
285
+ * named color, see `COLORS_BY_NAME`
286
+ * hex short eg. `<prefix>fff` (prefix can be `#`, `0x` or nothing)
287
+ * hex long eg. `<prefix>ffffff` (prefix can be `#`, `0x` or nothing)
288
+ * `rgb(<r>, <g>, <b>)`
289
+ * `rgba(<r>, <g>, <b>, <a>)`
290
+
291
+ Args:
292
+ value: A string representing a color.
293
+
294
+ Returns:
295
+ An `RGBA` tuple parsed from the input string.
296
+
297
+ Raises:
298
+ ValueError: If the input string cannot be parsed to an RGBA tuple.
299
+ """
300
+ value_lower = value.lower()
301
+ try:
302
+ r, g, b = COLORS_BY_NAME[value_lower]
303
+ except KeyError:
304
+ pass
305
+ else:
306
+ return ints_to_rgba(r, g, b, None)
307
+
308
+ m = re.fullmatch(r_hex_short, value_lower)
309
+ if m:
310
+ *rgb, a = m.groups()
311
+ r, g, b = (int(v * 2, 16) for v in rgb)
312
+ if a:
313
+ alpha: Optional[float] = int(a * 2, 16) / 255
314
+ else:
315
+ alpha = None
316
+ return ints_to_rgba(r, g, b, alpha)
317
+
318
+ m = re.fullmatch(r_hex_long, value_lower)
319
+ if m:
320
+ *rgb, a = m.groups()
321
+ r, g, b = (int(v, 16) for v in rgb)
322
+ if a:
323
+ alpha = int(a, 16) / 255
324
+ else:
325
+ alpha = None
326
+ return ints_to_rgba(r, g, b, alpha)
327
+
328
+ m = re.fullmatch(r_rgb, value_lower) or re.fullmatch(r_rgb_v4_style, value_lower)
329
+ if m:
330
+ return ints_to_rgba(*m.groups()) # type: ignore
331
+
332
+ m = re.fullmatch(r_hsl, value_lower) or re.fullmatch(r_hsl_v4_style, value_lower)
333
+ if m:
334
+ return parse_hsl(*m.groups()) # type: ignore
335
+
336
+ raise PydanticCustomError('color_error', 'value is not a valid color: string not recognised as a valid color')
337
+
338
+
339
+ def ints_to_rgba(r: Union[int, str], g: Union[int, str], b: Union[int, str], alpha: Optional[float] = None) -> RGBA:
340
+ """Converts integer or string values for RGB color and an optional alpha value to an `RGBA` object.
341
+
342
+ Args:
343
+ r: An integer or string representing the red color value.
344
+ g: An integer or string representing the green color value.
345
+ b: An integer or string representing the blue color value.
346
+ alpha: A float representing the alpha value. Defaults to None.
347
+
348
+ Returns:
349
+ An instance of the `RGBA` class with the corresponding color and alpha values.
350
+ """
351
+ return RGBA(parse_color_value(r), parse_color_value(g), parse_color_value(b), parse_float_alpha(alpha))
352
+
353
+
354
+ def parse_color_value(value: Union[int, str], max_val: int = 255) -> float:
355
+ """Parse the color value provided and return a number between 0 and 1.
356
+
357
+ Args:
358
+ value: An integer or string color value.
359
+ max_val: Maximum range value. Defaults to 255.
360
+
361
+ Raises:
362
+ PydanticCustomError: If the value is not a valid color.
363
+
364
+ Returns:
365
+ A number between 0 and 1.
366
+ """
367
+ try:
368
+ color = float(value)
369
+ except ValueError:
370
+ raise PydanticCustomError('color_error', 'value is not a valid color: color values must be a valid number')
371
+ if 0 <= color <= max_val:
372
+ return color / max_val
373
+ else:
374
+ raise PydanticCustomError(
375
+ 'color_error',
376
+ 'value is not a valid color: color values must be in the range 0 to {max_val}',
377
+ {'max_val': max_val},
378
+ )
379
+
380
+
381
+ def parse_float_alpha(value: Union[None, str, float, int]) -> Optional[float]:
382
+ """Parse an alpha value checking it's a valid float in the range 0 to 1.
383
+
384
+ Args:
385
+ value: The input value to parse.
386
+
387
+ Returns:
388
+ The parsed value as a float, or `None` if the value was None or equal 1.
389
+
390
+ Raises:
391
+ PydanticCustomError: If the input value cannot be successfully parsed as a float in the expected range.
392
+ """
393
+ if value is None:
394
+ return None
395
+ try:
396
+ if isinstance(value, str) and value.endswith('%'):
397
+ alpha = float(value[:-1]) / 100
398
+ else:
399
+ alpha = float(value)
400
+ except ValueError:
401
+ raise PydanticCustomError('color_error', 'value is not a valid color: alpha values must be a valid float')
402
+
403
+ if math.isclose(alpha, 1):
404
+ return None
405
+ elif 0 <= alpha <= 1:
406
+ return alpha
407
+ else:
408
+ raise PydanticCustomError('color_error', 'value is not a valid color: alpha values must be in the range 0 to 1')
409
+
410
+
411
+ def parse_hsl(h: str, h_units: str, sat: str, light: str, alpha: Optional[float] = None) -> RGBA:
412
+ """Parse raw hue, saturation, lightness, and alpha values and convert to RGBA.
413
+
414
+ Args:
415
+ h: The hue value.
416
+ h_units: The unit for hue value.
417
+ sat: The saturation value.
418
+ light: The lightness value.
419
+ alpha: Alpha value.
420
+
421
+ Returns:
422
+ An instance of `RGBA`.
423
+ """
424
+ s_value, l_value = parse_color_value(sat, 100), parse_color_value(light, 100)
425
+
426
+ h_value = float(h)
427
+ if h_units in {None, 'deg'}:
428
+ h_value = h_value % 360 / 360
429
+ elif h_units == 'rad':
430
+ h_value = h_value % rads / rads
431
+ else:
432
+ # turns
433
+ h_value = h_value % 1
434
+
435
+ r, g, b = hls_to_rgb(h_value, l_value, s_value)
436
+ return RGBA(r, g, b, parse_float_alpha(alpha))
437
+
438
+
439
+ def float_to_255(c: float) -> int:
440
+ """Converts a float value between 0 and 1 (inclusive) to an integer between 0 and 255 (inclusive).
441
+
442
+ Args:
443
+ c: The float value to be converted. Must be between 0 and 1 (inclusive).
444
+
445
+ Returns:
446
+ The integer equivalent of the given float value rounded to the nearest whole number.
447
+
448
+ Raises:
449
+ ValueError: If the given float value is outside the acceptable range of 0 to 1 (inclusive).
450
+ """
451
+ return int(round(c * 255))
452
+
453
+
454
+ COLORS_BY_NAME = {
455
+ 'aliceblue': (240, 248, 255),
456
+ 'antiquewhite': (250, 235, 215),
457
+ 'aqua': (0, 255, 255),
458
+ 'aquamarine': (127, 255, 212),
459
+ 'azure': (240, 255, 255),
460
+ 'beige': (245, 245, 220),
461
+ 'bisque': (255, 228, 196),
462
+ 'black': (0, 0, 0),
463
+ 'blanchedalmond': (255, 235, 205),
464
+ 'blue': (0, 0, 255),
465
+ 'blueviolet': (138, 43, 226),
466
+ 'brown': (165, 42, 42),
467
+ 'burlywood': (222, 184, 135),
468
+ 'cadetblue': (95, 158, 160),
469
+ 'chartreuse': (127, 255, 0),
470
+ 'chocolate': (210, 105, 30),
471
+ 'coral': (255, 127, 80),
472
+ 'cornflowerblue': (100, 149, 237),
473
+ 'cornsilk': (255, 248, 220),
474
+ 'crimson': (220, 20, 60),
475
+ 'cyan': (0, 255, 255),
476
+ 'darkblue': (0, 0, 139),
477
+ 'darkcyan': (0, 139, 139),
478
+ 'darkgoldenrod': (184, 134, 11),
479
+ 'darkgray': (169, 169, 169),
480
+ 'darkgreen': (0, 100, 0),
481
+ 'darkgrey': (169, 169, 169),
482
+ 'darkkhaki': (189, 183, 107),
483
+ 'darkmagenta': (139, 0, 139),
484
+ 'darkolivegreen': (85, 107, 47),
485
+ 'darkorange': (255, 140, 0),
486
+ 'darkorchid': (153, 50, 204),
487
+ 'darkred': (139, 0, 0),
488
+ 'darksalmon': (233, 150, 122),
489
+ 'darkseagreen': (143, 188, 143),
490
+ 'darkslateblue': (72, 61, 139),
491
+ 'darkslategray': (47, 79, 79),
492
+ 'darkslategrey': (47, 79, 79),
493
+ 'darkturquoise': (0, 206, 209),
494
+ 'darkviolet': (148, 0, 211),
495
+ 'deeppink': (255, 20, 147),
496
+ 'deepskyblue': (0, 191, 255),
497
+ 'dimgray': (105, 105, 105),
498
+ 'dimgrey': (105, 105, 105),
499
+ 'dodgerblue': (30, 144, 255),
500
+ 'firebrick': (178, 34, 34),
501
+ 'floralwhite': (255, 250, 240),
502
+ 'forestgreen': (34, 139, 34),
503
+ 'fuchsia': (255, 0, 255),
504
+ 'gainsboro': (220, 220, 220),
505
+ 'ghostwhite': (248, 248, 255),
506
+ 'gold': (255, 215, 0),
507
+ 'goldenrod': (218, 165, 32),
508
+ 'gray': (128, 128, 128),
509
+ 'green': (0, 128, 0),
510
+ 'greenyellow': (173, 255, 47),
511
+ 'grey': (128, 128, 128),
512
+ 'honeydew': (240, 255, 240),
513
+ 'hotpink': (255, 105, 180),
514
+ 'indianred': (205, 92, 92),
515
+ 'indigo': (75, 0, 130),
516
+ 'ivory': (255, 255, 240),
517
+ 'khaki': (240, 230, 140),
518
+ 'lavender': (230, 230, 250),
519
+ 'lavenderblush': (255, 240, 245),
520
+ 'lawngreen': (124, 252, 0),
521
+ 'lemonchiffon': (255, 250, 205),
522
+ 'lightblue': (173, 216, 230),
523
+ 'lightcoral': (240, 128, 128),
524
+ 'lightcyan': (224, 255, 255),
525
+ 'lightgoldenrodyellow': (250, 250, 210),
526
+ 'lightgray': (211, 211, 211),
527
+ 'lightgreen': (144, 238, 144),
528
+ 'lightgrey': (211, 211, 211),
529
+ 'lightpink': (255, 182, 193),
530
+ 'lightsalmon': (255, 160, 122),
531
+ 'lightseagreen': (32, 178, 170),
532
+ 'lightskyblue': (135, 206, 250),
533
+ 'lightslategray': (119, 136, 153),
534
+ 'lightslategrey': (119, 136, 153),
535
+ 'lightsteelblue': (176, 196, 222),
536
+ 'lightyellow': (255, 255, 224),
537
+ 'lime': (0, 255, 0),
538
+ 'limegreen': (50, 205, 50),
539
+ 'linen': (250, 240, 230),
540
+ 'magenta': (255, 0, 255),
541
+ 'maroon': (128, 0, 0),
542
+ 'mediumaquamarine': (102, 205, 170),
543
+ 'mediumblue': (0, 0, 205),
544
+ 'mediumorchid': (186, 85, 211),
545
+ 'mediumpurple': (147, 112, 219),
546
+ 'mediumseagreen': (60, 179, 113),
547
+ 'mediumslateblue': (123, 104, 238),
548
+ 'mediumspringgreen': (0, 250, 154),
549
+ 'mediumturquoise': (72, 209, 204),
550
+ 'mediumvioletred': (199, 21, 133),
551
+ 'midnightblue': (25, 25, 112),
552
+ 'mintcream': (245, 255, 250),
553
+ 'mistyrose': (255, 228, 225),
554
+ 'moccasin': (255, 228, 181),
555
+ 'navajowhite': (255, 222, 173),
556
+ 'navy': (0, 0, 128),
557
+ 'oldlace': (253, 245, 230),
558
+ 'olive': (128, 128, 0),
559
+ 'olivedrab': (107, 142, 35),
560
+ 'orange': (255, 165, 0),
561
+ 'orangered': (255, 69, 0),
562
+ 'orchid': (218, 112, 214),
563
+ 'palegoldenrod': (238, 232, 170),
564
+ 'palegreen': (152, 251, 152),
565
+ 'paleturquoise': (175, 238, 238),
566
+ 'palevioletred': (219, 112, 147),
567
+ 'papayawhip': (255, 239, 213),
568
+ 'peachpuff': (255, 218, 185),
569
+ 'peru': (205, 133, 63),
570
+ 'pink': (255, 192, 203),
571
+ 'plum': (221, 160, 221),
572
+ 'powderblue': (176, 224, 230),
573
+ 'purple': (128, 0, 128),
574
+ 'red': (255, 0, 0),
575
+ 'rosybrown': (188, 143, 143),
576
+ 'royalblue': (65, 105, 225),
577
+ 'saddlebrown': (139, 69, 19),
578
+ 'salmon': (250, 128, 114),
579
+ 'sandybrown': (244, 164, 96),
580
+ 'seagreen': (46, 139, 87),
581
+ 'seashell': (255, 245, 238),
582
+ 'sienna': (160, 82, 45),
583
+ 'silver': (192, 192, 192),
584
+ 'skyblue': (135, 206, 235),
585
+ 'slateblue': (106, 90, 205),
586
+ 'slategray': (112, 128, 144),
587
+ 'slategrey': (112, 128, 144),
588
+ 'snow': (255, 250, 250),
589
+ 'springgreen': (0, 255, 127),
590
+ 'steelblue': (70, 130, 180),
591
+ 'tan': (210, 180, 140),
592
+ 'teal': (0, 128, 128),
593
+ 'thistle': (216, 191, 216),
594
+ 'tomato': (255, 99, 71),
595
+ 'turquoise': (64, 224, 208),
596
+ 'violet': (238, 130, 238),
597
+ 'wheat': (245, 222, 179),
598
+ 'white': (255, 255, 255),
599
+ 'whitesmoke': (245, 245, 245),
600
+ 'yellow': (255, 255, 0),
601
+ 'yellowgreen': (154, 205, 50),
602
+ }
603
+
604
+ COLORS_BY_VALUE = {v: k for k, v in COLORS_BY_NAME.items()}
.mcp-venv/lib/python3.13/site-packages/pydantic/config.py ADDED
@@ -0,0 +1,1296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration for Pydantic models."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ import warnings
6
+ from re import Pattern
7
+ from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, Union, cast, overload
8
+
9
+ from typing_extensions import TypeAlias, TypedDict, Unpack, deprecated
10
+
11
+ from ._migration import getattr_migration
12
+ from .aliases import AliasGenerator
13
+ from .errors import PydanticUserError
14
+ from .warnings import PydanticDeprecatedSince211
15
+
16
+ if TYPE_CHECKING:
17
+ from ._internal._generate_schema import GenerateSchema as _GenerateSchema
18
+ from .fields import ComputedFieldInfo, FieldInfo
19
+
20
+ __all__ = ('ConfigDict', 'with_config')
21
+
22
+
23
+ JsonValue: TypeAlias = Union[int, float, str, bool, None, list['JsonValue'], 'JsonDict']
24
+ JsonDict: TypeAlias = dict[str, JsonValue]
25
+
26
+ JsonEncoder = Callable[[Any], Any]
27
+
28
+ JsonSchemaExtraCallable: TypeAlias = Union[
29
+ Callable[[JsonDict], None],
30
+ Callable[[JsonDict, type[Any]], None],
31
+ ]
32
+
33
+ ExtraValues = Literal['allow', 'ignore', 'forbid']
34
+
35
+
36
+ class ConfigDict(TypedDict, total=False):
37
+ """A TypedDict for configuring Pydantic behaviour."""
38
+
39
+ title: str | None
40
+ """The title for the generated JSON schema, defaults to the model's name"""
41
+
42
+ model_title_generator: Callable[[type], str] | None
43
+ """A callable that takes a model class and returns the title for it. Defaults to `None`."""
44
+
45
+ field_title_generator: Callable[[str, FieldInfo | ComputedFieldInfo], str] | None
46
+ """A callable that takes a field's name and info and returns title for it. Defaults to `None`."""
47
+
48
+ str_to_lower: bool
49
+ """Whether to convert all characters to lowercase for str types. Defaults to `False`."""
50
+
51
+ str_to_upper: bool
52
+ """Whether to convert all characters to uppercase for str types. Defaults to `False`."""
53
+
54
+ str_strip_whitespace: bool
55
+ """Whether to strip leading and trailing whitespace for str types."""
56
+
57
+ str_min_length: int
58
+ """The minimum length for str types. Defaults to `None`."""
59
+
60
+ str_max_length: int | None
61
+ """The maximum length for str types. Defaults to `None`."""
62
+
63
+ extra: ExtraValues | None
64
+ '''
65
+ Whether to ignore, allow, or forbid extra data during model initialization. Defaults to `'ignore'`.
66
+
67
+ Three configuration values are available:
68
+
69
+ - `'ignore'`: Providing extra data is ignored (the default):
70
+ ```python
71
+ from pydantic import BaseModel, ConfigDict
72
+
73
+ class User(BaseModel):
74
+ model_config = ConfigDict(extra='ignore') # (1)!
75
+
76
+ name: str
77
+
78
+ user = User(name='John Doe', age=20) # (2)!
79
+ print(user)
80
+ #> name='John Doe'
81
+ ```
82
+
83
+ 1. This is the default behaviour.
84
+ 2. The `age` argument is ignored.
85
+
86
+ - `'forbid'`: Providing extra data is not permitted, and a [`ValidationError`][pydantic_core.ValidationError]
87
+ will be raised if this is the case:
88
+ ```python
89
+ from pydantic import BaseModel, ConfigDict, ValidationError
90
+
91
+
92
+ class Model(BaseModel):
93
+ x: int
94
+
95
+ model_config = ConfigDict(extra='forbid')
96
+
97
+
98
+ try:
99
+ Model(x=1, y='a')
100
+ except ValidationError as exc:
101
+ print(exc)
102
+ """
103
+ 1 validation error for Model
104
+ y
105
+ Extra inputs are not permitted [type=extra_forbidden, input_value='a', input_type=str]
106
+ """
107
+ ```
108
+
109
+ - `'allow'`: Providing extra data is allowed and stored in the `__pydantic_extra__` dictionary attribute:
110
+ ```python
111
+ from pydantic import BaseModel, ConfigDict
112
+
113
+
114
+ class Model(BaseModel):
115
+ x: int
116
+
117
+ model_config = ConfigDict(extra='allow')
118
+
119
+
120
+ m = Model(x=1, y='a')
121
+ assert m.__pydantic_extra__ == {'y': 'a'}
122
+ ```
123
+ By default, no validation will be applied to these extra items, but you can set a type for the values by overriding
124
+ the type annotation for `__pydantic_extra__`:
125
+ ```python
126
+ from pydantic import BaseModel, ConfigDict, Field, ValidationError
127
+
128
+
129
+ class Model(BaseModel):
130
+ __pydantic_extra__: dict[str, int] = Field(init=False) # (1)!
131
+
132
+ x: int
133
+
134
+ model_config = ConfigDict(extra='allow')
135
+
136
+
137
+ try:
138
+ Model(x=1, y='a')
139
+ except ValidationError as exc:
140
+ print(exc)
141
+ """
142
+ 1 validation error for Model
143
+ y
144
+ Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str]
145
+ """
146
+
147
+ m = Model(x=1, y='2')
148
+ assert m.x == 1
149
+ assert m.y == 2
150
+ assert m.model_dump() == {'x': 1, 'y': 2}
151
+ assert m.__pydantic_extra__ == {'y': 2}
152
+ ```
153
+
154
+ 1. The `= Field(init=False)` does not have any effect at runtime, but prevents the `__pydantic_extra__` field from
155
+ being included as a parameter to the model's `__init__` method by type checkers.
156
+
157
+ As well as specifying an `extra` configuration value on the model, you can also provide it as an argument to the validation methods.
158
+ This will override any `extra` configuration value set on the model:
159
+ ```python
160
+ from pydantic import BaseModel, ConfigDict, ValidationError
161
+
162
+ class Model(BaseModel):
163
+ x: int
164
+ model_config = ConfigDict(extra="allow")
165
+
166
+ try:
167
+ # Override model config and forbid extra fields just this time
168
+ Model.model_validate({"x": 1, "y": 2}, extra="forbid")
169
+ except ValidationError as exc:
170
+ print(exc)
171
+ """
172
+ 1 validation error for Model
173
+ y
174
+ Extra inputs are not permitted [type=extra_forbidden, input_value=2, input_type=int]
175
+ """
176
+ ```
177
+ '''
178
+
179
+ frozen: bool
180
+ """
181
+ Whether models are faux-immutable, i.e. whether `__setattr__` is allowed, and also generates
182
+ a `__hash__()` method for the model. This makes instances of the model potentially hashable if all the
183
+ attributes are hashable. Defaults to `False`.
184
+
185
+ Note:
186
+ On V1, the inverse of this setting was called `allow_mutation`, and was `True` by default.
187
+ """
188
+
189
+ populate_by_name: bool
190
+ """
191
+ Whether an aliased field may be populated by its name as given by the model
192
+ attribute, as well as the alias. Defaults to `False`.
193
+
194
+ !!! warning
195
+ `populate_by_name` usage is not recommended in v2.11+ and will be deprecated in v3.
196
+ Instead, you should use the [`validate_by_name`][pydantic.config.ConfigDict.validate_by_name] configuration setting.
197
+
198
+ When `validate_by_name=True` and `validate_by_alias=True`, this is strictly equivalent to the
199
+ previous behavior of `populate_by_name=True`.
200
+
201
+ In v2.11, we also introduced a [`validate_by_alias`][pydantic.config.ConfigDict.validate_by_alias] setting that introduces more fine grained
202
+ control for validation behavior.
203
+
204
+ Here's how you might go about using the new settings to achieve the same behavior:
205
+
206
+ ```python
207
+ from pydantic import BaseModel, ConfigDict, Field
208
+
209
+ class Model(BaseModel):
210
+ model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
211
+
212
+ my_field: str = Field(alias='my_alias') # (1)!
213
+
214
+ m = Model(my_alias='foo') # (2)!
215
+ print(m)
216
+ #> my_field='foo'
217
+
218
+ m = Model(my_field='foo') # (3)!
219
+ print(m)
220
+ #> my_field='foo'
221
+ ```
222
+
223
+ 1. The field `'my_field'` has an alias `'my_alias'`.
224
+ 2. The model is populated by the alias `'my_alias'`.
225
+ 3. The model is populated by the attribute name `'my_field'`.
226
+ """
227
+
228
+ use_enum_values: bool
229
+ """
230
+ Whether to populate models with the `value` property of enums, rather than the raw enum.
231
+ This may be useful if you want to serialize `model.model_dump()` later. Defaults to `False`.
232
+
233
+ !!! note
234
+ If you have an `Optional[Enum]` value that you set a default for, you need to use `validate_default=True`
235
+ for said Field to ensure that the `use_enum_values` flag takes effect on the default, as extracting an
236
+ enum's value occurs during validation, not serialization.
237
+
238
+ ```python
239
+ from enum import Enum
240
+ from typing import Optional
241
+
242
+ from pydantic import BaseModel, ConfigDict, Field
243
+
244
+ class SomeEnum(Enum):
245
+ FOO = 'foo'
246
+ BAR = 'bar'
247
+ BAZ = 'baz'
248
+
249
+ class SomeModel(BaseModel):
250
+ model_config = ConfigDict(use_enum_values=True)
251
+
252
+ some_enum: SomeEnum
253
+ another_enum: Optional[SomeEnum] = Field(
254
+ default=SomeEnum.FOO, validate_default=True
255
+ )
256
+
257
+ model1 = SomeModel(some_enum=SomeEnum.BAR)
258
+ print(model1.model_dump())
259
+ #> {'some_enum': 'bar', 'another_enum': 'foo'}
260
+
261
+ model2 = SomeModel(some_enum=SomeEnum.BAR, another_enum=SomeEnum.BAZ)
262
+ print(model2.model_dump())
263
+ #> {'some_enum': 'bar', 'another_enum': 'baz'}
264
+ ```
265
+ """
266
+
267
+ validate_assignment: bool
268
+ """
269
+ Whether to validate the data when the model is changed. Defaults to `False`.
270
+
271
+ The default behavior of Pydantic is to validate the data when the model is created.
272
+
273
+ In case the user changes the data after the model is created, the model is _not_ revalidated.
274
+
275
+ ```python
276
+ from pydantic import BaseModel
277
+
278
+ class User(BaseModel):
279
+ name: str
280
+
281
+ user = User(name='John Doe') # (1)!
282
+ print(user)
283
+ #> name='John Doe'
284
+ user.name = 123 # (1)!
285
+ print(user)
286
+ #> name=123
287
+ ```
288
+
289
+ 1. The validation happens only when the model is created.
290
+ 2. The validation does not happen when the data is changed.
291
+
292
+ In case you want to revalidate the model when the data is changed, you can use `validate_assignment=True`:
293
+
294
+ ```python
295
+ from pydantic import BaseModel, ValidationError
296
+
297
+ class User(BaseModel, validate_assignment=True): # (1)!
298
+ name: str
299
+
300
+ user = User(name='John Doe') # (2)!
301
+ print(user)
302
+ #> name='John Doe'
303
+ try:
304
+ user.name = 123 # (3)!
305
+ except ValidationError as e:
306
+ print(e)
307
+ '''
308
+ 1 validation error for User
309
+ name
310
+ Input should be a valid string [type=string_type, input_value=123, input_type=int]
311
+ '''
312
+ ```
313
+
314
+ 1. You can either use class keyword arguments, or `model_config` to set `validate_assignment=True`.
315
+ 2. The validation happens when the model is created.
316
+ 3. The validation _also_ happens when the data is changed.
317
+ """
318
+
319
+ arbitrary_types_allowed: bool
320
+ """
321
+ Whether arbitrary types are allowed for field types. Defaults to `False`.
322
+
323
+ ```python
324
+ from pydantic import BaseModel, ConfigDict, ValidationError
325
+
326
+ # This is not a pydantic model, it's an arbitrary class
327
+ class Pet:
328
+ def __init__(self, name: str):
329
+ self.name = name
330
+
331
+ class Model(BaseModel):
332
+ model_config = ConfigDict(arbitrary_types_allowed=True)
333
+
334
+ pet: Pet
335
+ owner: str
336
+
337
+ pet = Pet(name='Hedwig')
338
+ # A simple check of instance type is used to validate the data
339
+ model = Model(owner='Harry', pet=pet)
340
+ print(model)
341
+ #> pet=<__main__.Pet object at 0x0123456789ab> owner='Harry'
342
+ print(model.pet)
343
+ #> <__main__.Pet object at 0x0123456789ab>
344
+ print(model.pet.name)
345
+ #> Hedwig
346
+ print(type(model.pet))
347
+ #> <class '__main__.Pet'>
348
+ try:
349
+ # If the value is not an instance of the type, it's invalid
350
+ Model(owner='Harry', pet='Hedwig')
351
+ except ValidationError as e:
352
+ print(e)
353
+ '''
354
+ 1 validation error for Model
355
+ pet
356
+ Input should be an instance of Pet [type=is_instance_of, input_value='Hedwig', input_type=str]
357
+ '''
358
+
359
+ # Nothing in the instance of the arbitrary type is checked
360
+ # Here name probably should have been a str, but it's not validated
361
+ pet2 = Pet(name=42)
362
+ model2 = Model(owner='Harry', pet=pet2)
363
+ print(model2)
364
+ #> pet=<__main__.Pet object at 0x0123456789ab> owner='Harry'
365
+ print(model2.pet)
366
+ #> <__main__.Pet object at 0x0123456789ab>
367
+ print(model2.pet.name)
368
+ #> 42
369
+ print(type(model2.pet))
370
+ #> <class '__main__.Pet'>
371
+ ```
372
+ """
373
+
374
+ from_attributes: bool
375
+ """
376
+ Whether to build models and look up discriminators of tagged unions using python object attributes.
377
+ """
378
+
379
+ loc_by_alias: bool
380
+ """Whether to use the actual key provided in the data (e.g. alias) for error `loc`s rather than the field's name. Defaults to `True`."""
381
+
382
+ alias_generator: Callable[[str], str] | AliasGenerator | None
383
+ """
384
+ A callable that takes a field name and returns an alias for it
385
+ or an instance of [`AliasGenerator`][pydantic.aliases.AliasGenerator]. Defaults to `None`.
386
+
387
+ When using a callable, the alias generator is used for both validation and serialization.
388
+ If you want to use different alias generators for validation and serialization, you can use
389
+ [`AliasGenerator`][pydantic.aliases.AliasGenerator] instead.
390
+
391
+ If data source field names do not match your code style (e.g. CamelCase fields),
392
+ you can automatically generate aliases using `alias_generator`. Here's an example with
393
+ a basic callable:
394
+
395
+ ```python
396
+ from pydantic import BaseModel, ConfigDict
397
+ from pydantic.alias_generators import to_pascal
398
+
399
+ class Voice(BaseModel):
400
+ model_config = ConfigDict(alias_generator=to_pascal)
401
+
402
+ name: str
403
+ language_code: str
404
+
405
+ voice = Voice(Name='Filiz', LanguageCode='tr-TR')
406
+ print(voice.language_code)
407
+ #> tr-TR
408
+ print(voice.model_dump(by_alias=True))
409
+ #> {'Name': 'Filiz', 'LanguageCode': 'tr-TR'}
410
+ ```
411
+
412
+ If you want to use different alias generators for validation and serialization, you can use
413
+ [`AliasGenerator`][pydantic.aliases.AliasGenerator].
414
+
415
+ ```python
416
+ from pydantic import AliasGenerator, BaseModel, ConfigDict
417
+ from pydantic.alias_generators import to_camel, to_pascal
418
+
419
+ class Athlete(BaseModel):
420
+ first_name: str
421
+ last_name: str
422
+ sport: str
423
+
424
+ model_config = ConfigDict(
425
+ alias_generator=AliasGenerator(
426
+ validation_alias=to_camel,
427
+ serialization_alias=to_pascal,
428
+ )
429
+ )
430
+
431
+ athlete = Athlete(firstName='John', lastName='Doe', sport='track')
432
+ print(athlete.model_dump(by_alias=True))
433
+ #> {'FirstName': 'John', 'LastName': 'Doe', 'Sport': 'track'}
434
+ ```
435
+
436
+ Note:
437
+ Pydantic offers three built-in alias generators: [`to_pascal`][pydantic.alias_generators.to_pascal],
438
+ [`to_camel`][pydantic.alias_generators.to_camel], and [`to_snake`][pydantic.alias_generators.to_snake].
439
+ """
440
+
441
+ ignored_types: tuple[type, ...]
442
+ """A tuple of types that may occur as values of class attributes without annotations. This is
443
+ typically used for custom descriptors (classes that behave like `property`). If an attribute is set on a
444
+ class without an annotation and has a type that is not in this tuple (or otherwise recognized by
445
+ _pydantic_), an error will be raised. Defaults to `()`.
446
+ """
447
+
448
+ allow_inf_nan: bool
449
+ """Whether to allow infinity (`+inf` an `-inf`) and NaN values to float and decimal fields. Defaults to `True`."""
450
+
451
+ json_schema_extra: JsonDict | JsonSchemaExtraCallable | None
452
+ """A dict or callable to provide extra JSON schema properties. Defaults to `None`."""
453
+
454
+ json_encoders: dict[type[object], JsonEncoder] | None
455
+ """
456
+ A `dict` of custom JSON encoders for specific types. Defaults to `None`.
457
+
458
+ /// version-deprecated | v2
459
+ This configuration option is a carryover from v1. We originally planned to remove it in v2 but didn't have a 1:1 replacement
460
+ so we are keeping it for now. It is still deprecated and will likely be removed in the future.
461
+ ///
462
+ """
463
+
464
+ # new in V2
465
+ strict: bool
466
+ """
467
+ Whether strict validation is applied to all fields on the model.
468
+
469
+ By default, Pydantic attempts to coerce values to the correct type, when possible.
470
+
471
+ There are situations in which you may want to disable this behavior, and instead raise an error if a value's type
472
+ does not match the field's type annotation.
473
+
474
+ To configure strict mode for all fields on a model, you can set `strict=True` on the model.
475
+
476
+ ```python
477
+ from pydantic import BaseModel, ConfigDict
478
+
479
+ class Model(BaseModel):
480
+ model_config = ConfigDict(strict=True)
481
+
482
+ name: str
483
+ age: int
484
+ ```
485
+
486
+ See [Strict Mode](../concepts/strict_mode.md) for more details.
487
+
488
+ See the [Conversion Table](../concepts/conversion_table.md) for more details on how Pydantic converts data in both
489
+ strict and lax modes.
490
+
491
+ /// version-added | v2
492
+ ///
493
+ """
494
+ # whether instances of models and dataclasses (including subclass instances) should re-validate, default 'never'
495
+ revalidate_instances: Literal['always', 'never', 'subclass-instances']
496
+ """
497
+ When and how to revalidate models and dataclasses during validation. Can be one of:
498
+
499
+ - `'never'`: will *not* revalidate models and dataclasses during validation
500
+ - `'always'`: will revalidate models and dataclasses during validation
501
+ - `'subclass-instances'`: will revalidate models and dataclasses during validation if the instance is a
502
+ subclass of the model or dataclass
503
+
504
+ The default is `'never'` (no revalidation).
505
+
506
+ This configuration only affects *the current model* it is applied on, and does *not* propagate to the models
507
+ referenced in fields.
508
+
509
+ ```python
510
+ from pydantic import BaseModel
511
+
512
+ class User(BaseModel, revalidate_instances='never'): # (1)!
513
+ name: str
514
+
515
+ class Transaction(BaseModel):
516
+ user: User
517
+
518
+ my_user = User(name='John')
519
+ t = Transaction(user=my_user)
520
+
521
+ my_user.name = 1 # (2)!
522
+ t = Transaction(user=my_user) # (3)!
523
+ print(t)
524
+ #> user=User(name=1)
525
+ ```
526
+
527
+ 1. This is the default behavior.
528
+ 2. The assignment is *not* validated, unless you set [`validate_assignment`][pydantic.ConfigDict.validate_assignment] in the configuration.
529
+ 3. Since `revalidate_instances` is set to `'never'`, the user instance is not revalidated.
530
+
531
+ Here is an example demonstrating the behavior of `'subclass-instances'`:
532
+
533
+ ```python
534
+ from pydantic import BaseModel
535
+
536
+ class User(BaseModel, revalidate_instances='subclass-instances'):
537
+ name: str
538
+
539
+ class SubUser(User):
540
+ age: int
541
+
542
+ class Transaction(BaseModel):
543
+ user: User
544
+
545
+ my_user = User(name='John')
546
+ my_user.name = 1 # (1)!
547
+ t = Transaction(user=my_user) # (2)!
548
+ print(t)
549
+ #> user=User(name=1)
550
+
551
+ my_sub_user = SubUser(name='John', age=20)
552
+ t = Transaction(user=my_sub_user)
553
+ print(t) # (3)!
554
+ #> user=User(name='John')
555
+ ```
556
+
557
+ 1. The assignment is *not* validated, unless you set [`validate_assignment`][pydantic.ConfigDict.validate_assignment] in the configuration.
558
+ 2. Because `my_user` is a "direct" instance of `User`, it is *not* being revalidated. It would have been the case if
559
+ `revalidate_instances` was set to `'always'`.
560
+ 3. Because `my_sub_user` is an instance of a `User` subclass, it is being revalidated. In this case, Pydantic coerces `my_sub_user` to the defined
561
+ `User` class defined on `Transaction`. If one of its fields had an invalid value, a validation error would have been raised.
562
+
563
+ /// version-added | v2
564
+ ///
565
+ """
566
+
567
+ ser_json_timedelta: Literal['iso8601', 'float']
568
+ """
569
+ The format of JSON serialized timedeltas. Accepts the string values of `'iso8601'` and
570
+ `'float'`. Defaults to `'iso8601'`.
571
+
572
+ - `'iso8601'` will serialize timedeltas to [ISO 8601 text format](https://en.wikipedia.org/wiki/ISO_8601#Durations).
573
+ - `'float'` will serialize timedeltas to the total number of seconds.
574
+
575
+ /// version-changed | v2.12
576
+ It is now recommended to use the [`ser_json_temporal`][pydantic.config.ConfigDict.ser_json_temporal]
577
+ setting. `ser_json_timedelta` will be deprecated in v3.
578
+ ///
579
+ """
580
+
581
+ ser_json_temporal: Literal['iso8601', 'seconds', 'milliseconds']
582
+ """
583
+ The format of JSON serialized temporal types from the [`datetime`][] module. This includes:
584
+
585
+ - [`datetime.datetime`][]
586
+ - [`datetime.date`][]
587
+ - [`datetime.time`][]
588
+ - [`datetime.timedelta`][]
589
+
590
+ Can be one of:
591
+
592
+ - `'iso8601'` will serialize date-like types to [ISO 8601 text format](https://en.wikipedia.org/wiki/ISO_8601#Durations).
593
+ - `'milliseconds'` will serialize date-like types to a floating point number of milliseconds since the epoch.
594
+ - `'seconds'` will serialize date-like types to a floating point number of seconds since the epoch.
595
+
596
+ Defaults to `'iso8601'`.
597
+
598
+ /// version-added | v2.12
599
+ This setting replaces [`ser_json_timedelta`][pydantic.config.ConfigDict.ser_json_timedelta],
600
+ which will be deprecated in v3. `ser_json_temporal` adds more configurability for the other temporal types.
601
+ ///
602
+ """
603
+
604
+ val_temporal_unit: Literal['seconds', 'milliseconds', 'infer']
605
+ """
606
+ The unit to assume for validating numeric input for datetime-like types ([`datetime.datetime`][] and [`datetime.date`][]). Can be one of:
607
+
608
+ - `'seconds'` will validate date or time numeric inputs as seconds since the [epoch].
609
+ - `'milliseconds'` will validate date or time numeric inputs as milliseconds since the [epoch].
610
+ - `'infer'` will infer the unit from the string numeric input on unix time as:
611
+
612
+ * seconds since the [epoch] if $-2^{10} <= v <= 2^{10}$
613
+ * milliseconds since the [epoch] (if $v < -2^{10}$ or $v > 2^{10}$).
614
+
615
+ Defaults to `'infer'`.
616
+
617
+ /// version-added | v2.12
618
+ ///
619
+
620
+ [epoch]: https://en.wikipedia.org/wiki/Unix_time
621
+ """
622
+
623
+ ser_json_bytes: Literal['utf8', 'base64', 'hex']
624
+ """
625
+ The encoding of JSON serialized bytes. Defaults to `'utf8'`.
626
+ Set equal to `val_json_bytes` to get back an equal value after serialization round trip.
627
+
628
+ - `'utf8'` will serialize bytes to UTF-8 strings.
629
+ - `'base64'` will serialize bytes to URL safe base64 strings.
630
+ - `'hex'` will serialize bytes to hexadecimal strings.
631
+ """
632
+
633
+ val_json_bytes: Literal['utf8', 'base64', 'hex']
634
+ """
635
+ /// version-added | v2.9
636
+ ///
637
+
638
+ The encoding of JSON serialized bytes to decode. Defaults to `'utf8'`.
639
+ Set equal to `ser_json_bytes` to get back an equal value after serialization round trip.
640
+
641
+ - `'utf8'` will deserialize UTF-8 strings to bytes.
642
+ - `'base64'` will deserialize URL safe base64 strings to bytes.
643
+ - `'hex'` will deserialize hexadecimal strings to bytes.
644
+ """
645
+
646
+ ser_json_inf_nan: Literal['null', 'constants', 'strings']
647
+ """
648
+ The encoding of JSON serialized infinity and NaN float values. Defaults to `'null'`.
649
+
650
+ - `'null'` will serialize infinity and NaN values as `null`.
651
+ - `'constants'` will serialize infinity and NaN values as `Infinity` and `NaN`.
652
+ - `'strings'` will serialize infinity as string `"Infinity"` and NaN as string `"NaN"`.
653
+ """
654
+
655
+ # whether to validate default values during validation, default False
656
+ validate_default: bool
657
+ """Whether to validate default values during validation. Defaults to `False`."""
658
+
659
+ validate_return: bool
660
+ """Whether to validate the return value from call validators. Defaults to `False`."""
661
+
662
+ protected_namespaces: tuple[str | Pattern[str], ...]
663
+ """
664
+ A tuple of strings and/or regex patterns that prevent models from having fields with names that conflict with its existing members/methods.
665
+
666
+ Strings are matched on a prefix basis. For instance, with `'dog'`, having a field named `'dog_name'` will be disallowed.
667
+
668
+ Regex patterns are matched on the entire field name. For instance, with the pattern `'^dog$'`, having a field named `'dog'` will be disallowed,
669
+ but `'dog_name'` will be accepted.
670
+
671
+ Defaults to `('model_validate', 'model_dump')`. This default is used to prevent collisions with the existing (and possibly future)
672
+ [validation](../concepts/models.md#validating-data) and [serialization](../concepts/serialization.md#serializing-data) methods.
673
+
674
+ ```python
675
+ import warnings
676
+
677
+ from pydantic import BaseModel
678
+
679
+ warnings.filterwarnings('error') # Raise warnings as errors
680
+
681
+ try:
682
+
683
+ class Model(BaseModel):
684
+ model_dump_something: str
685
+
686
+ except UserWarning as e:
687
+ print(e)
688
+ '''
689
+ Field 'model_dump_something' in 'Model' conflicts with protected namespace 'model_dump'.
690
+
691
+ You may be able to solve this by setting the 'protected_namespaces' configuration to ('model_validate',).
692
+ '''
693
+ ```
694
+
695
+ You can customize this behavior using the `protected_namespaces` setting:
696
+
697
+ ```python {test="skip"}
698
+ import re
699
+ import warnings
700
+
701
+ from pydantic import BaseModel, ConfigDict
702
+
703
+ with warnings.catch_warnings(record=True) as caught_warnings:
704
+ warnings.simplefilter('always') # Catch all warnings
705
+
706
+ class Model(BaseModel):
707
+ safe_field: str
708
+ also_protect_field: str
709
+ protect_this: str
710
+
711
+ model_config = ConfigDict(
712
+ protected_namespaces=(
713
+ 'protect_me_',
714
+ 'also_protect_',
715
+ re.compile('^protect_this$'),
716
+ )
717
+ )
718
+
719
+ for warning in caught_warnings:
720
+ print(f'{warning.message}')
721
+ '''
722
+ Field 'also_protect_field' in 'Model' conflicts with protected namespace 'also_protect_'.
723
+ You may be able to solve this by setting the 'protected_namespaces' configuration to ('protect_me_', re.compile('^protect_this$'))`.
724
+
725
+ Field 'protect_this' in 'Model' conflicts with protected namespace 're.compile('^protect_this$')'.
726
+ You may be able to solve this by setting the 'protected_namespaces' configuration to ('protect_me_', 'also_protect_')`.
727
+ '''
728
+ ```
729
+
730
+ While Pydantic will only emit a warning when an item is in a protected namespace but does not actually have a collision,
731
+ an error _is_ raised if there is an actual collision with an existing attribute:
732
+
733
+ ```python
734
+ from pydantic import BaseModel, ConfigDict
735
+
736
+ try:
737
+
738
+ class Model(BaseModel):
739
+ model_validate: str
740
+
741
+ model_config = ConfigDict(protected_namespaces=('model_',))
742
+
743
+ except ValueError as e:
744
+ print(e)
745
+ '''
746
+ Field 'model_validate' conflicts with member <bound method BaseModel.model_validate of <class 'pydantic.main.BaseModel'>> of protected namespace 'model_'.
747
+ '''
748
+ ```
749
+
750
+ /// version-changed | v2.10
751
+ The default protected namespaces was changed from `('model_',)` to `('model_validate', 'model_dump')`, to allow
752
+ for fields like `model_id`, `model_name` to be used.
753
+ ///
754
+ """
755
+
756
+ hide_input_in_errors: bool
757
+ """
758
+ Whether to hide inputs when printing errors. Defaults to `False`.
759
+
760
+ Pydantic shows the input value and type when it raises `ValidationError` during the validation.
761
+
762
+ ```python
763
+ from pydantic import BaseModel, ValidationError
764
+
765
+ class Model(BaseModel):
766
+ a: str
767
+
768
+ try:
769
+ Model(a=123)
770
+ except ValidationError as e:
771
+ print(e)
772
+ '''
773
+ 1 validation error for Model
774
+ a
775
+ Input should be a valid string [type=string_type, input_value=123, input_type=int]
776
+ '''
777
+ ```
778
+
779
+ You can hide the input value and type by setting the `hide_input_in_errors` config to `True`.
780
+
781
+ ```python
782
+ from pydantic import BaseModel, ConfigDict, ValidationError
783
+
784
+ class Model(BaseModel):
785
+ a: str
786
+ model_config = ConfigDict(hide_input_in_errors=True)
787
+
788
+ try:
789
+ Model(a=123)
790
+ except ValidationError as e:
791
+ print(e)
792
+ '''
793
+ 1 validation error for Model
794
+ a
795
+ Input should be a valid string [type=string_type]
796
+ '''
797
+ ```
798
+ """
799
+
800
+ defer_build: bool
801
+ """
802
+ Whether to defer model validator and serializer construction until the first model validation. Defaults to False.
803
+
804
+ This can be useful to avoid the overhead of building models which are only
805
+ used nested within other models, or when you want to manually define type namespace via
806
+ [`Model.model_rebuild(_types_namespace=...)`][pydantic.BaseModel.model_rebuild].
807
+
808
+ /// version-changed | v2.10
809
+ The setting also applies to [Pydantic dataclasses](../concepts/dataclasses.md) and [type adapters](../concepts/type_adapter.md).
810
+ ///
811
+ """
812
+
813
+ plugin_settings: dict[str, object] | None
814
+ """A `dict` of settings for plugins. Defaults to `None`."""
815
+
816
+ schema_generator: type[_GenerateSchema] | None
817
+ """
818
+ The `GenerateSchema` class to use during core schema generation.
819
+
820
+ /// version-deprecated | v2.10
821
+ The `GenerateSchema` class is private and highly subject to change.
822
+ ///
823
+ """
824
+
825
+ json_schema_serialization_defaults_required: bool
826
+ """
827
+ Whether fields with default values should be marked as required in the serialization schema. Defaults to `False`.
828
+
829
+ This ensures that the serialization schema will reflect the fact a field with a default will always be present
830
+ when serializing the model, even though it is not required for validation.
831
+
832
+ However, there are scenarios where this may be undesirable β€” in particular, if you want to share the schema
833
+ between validation and serialization, and don't mind fields with defaults being marked as not required during
834
+ serialization. See [#7209](https://github.com/pydantic/pydantic/issues/7209) for more details.
835
+
836
+ ```python
837
+ from pydantic import BaseModel, ConfigDict
838
+
839
+ class Model(BaseModel):
840
+ a: str = 'a'
841
+
842
+ model_config = ConfigDict(json_schema_serialization_defaults_required=True)
843
+
844
+ print(Model.model_json_schema(mode='validation'))
845
+ '''
846
+ {
847
+ 'properties': {'a': {'default': 'a', 'title': 'A', 'type': 'string'}},
848
+ 'title': 'Model',
849
+ 'type': 'object',
850
+ }
851
+ '''
852
+ print(Model.model_json_schema(mode='serialization'))
853
+ '''
854
+ {
855
+ 'properties': {'a': {'default': 'a', 'title': 'A', 'type': 'string'}},
856
+ 'required': ['a'],
857
+ 'title': 'Model',
858
+ 'type': 'object',
859
+ }
860
+ '''
861
+ ```
862
+
863
+ /// version-added | v2.4
864
+ ///
865
+ """
866
+
867
+ json_schema_mode_override: Literal['validation', 'serialization', None]
868
+ """
869
+ If not `None`, the specified mode will be used to generate the JSON schema regardless of what `mode` was passed to
870
+ the function call. Defaults to `None`.
871
+
872
+ This provides a way to force the JSON schema generation to reflect a specific mode, e.g., to always use the
873
+ validation schema.
874
+
875
+ It can be useful when using frameworks (such as FastAPI) that may generate different schemas for validation
876
+ and serialization that must both be referenced from the same schema; when this happens, we automatically append
877
+ `-Input` to the definition reference for the validation schema and `-Output` to the definition reference for the
878
+ serialization schema. By specifying a `json_schema_mode_override` though, this prevents the conflict between
879
+ the validation and serialization schemas (since both will use the specified schema), and so prevents the suffixes
880
+ from being added to the definition references.
881
+
882
+ ```python
883
+ from pydantic import BaseModel, ConfigDict, Json
884
+
885
+ class Model(BaseModel):
886
+ a: Json[int] # requires a string to validate, but will dump an int
887
+
888
+ print(Model.model_json_schema(mode='serialization'))
889
+ '''
890
+ {
891
+ 'properties': {'a': {'title': 'A', 'type': 'integer'}},
892
+ 'required': ['a'],
893
+ 'title': 'Model',
894
+ 'type': 'object',
895
+ }
896
+ '''
897
+
898
+ class ForceInputModel(Model):
899
+ # the following ensures that even with mode='serialization', we
900
+ # will get the schema that would be generated for validation.
901
+ model_config = ConfigDict(json_schema_mode_override='validation')
902
+
903
+ print(ForceInputModel.model_json_schema(mode='serialization'))
904
+ '''
905
+ {
906
+ 'properties': {
907
+ 'a': {
908
+ 'contentMediaType': 'application/json',
909
+ 'contentSchema': {'type': 'integer'},
910
+ 'title': 'A',
911
+ 'type': 'string',
912
+ }
913
+ },
914
+ 'required': ['a'],
915
+ 'title': 'ForceInputModel',
916
+ 'type': 'object',
917
+ }
918
+ '''
919
+ ```
920
+
921
+ /// version-added | v2.4
922
+ ///
923
+ """
924
+
925
+ coerce_numbers_to_str: bool
926
+ """
927
+ If `True`, enables automatic coercion of any `Number` type to `str` in "lax" (non-strict) mode. Defaults to `False`.
928
+
929
+ Pydantic doesn't allow number types (`int`, `float`, `Decimal`) to be coerced as type `str` by default.
930
+
931
+ ```python
932
+ from decimal import Decimal
933
+
934
+ from pydantic import BaseModel, ConfigDict, ValidationError
935
+
936
+ class Model(BaseModel):
937
+ value: str
938
+
939
+ try:
940
+ print(Model(value=42))
941
+ except ValidationError as e:
942
+ print(e)
943
+ '''
944
+ 1 validation error for Model
945
+ value
946
+ Input should be a valid string [type=string_type, input_value=42, input_type=int]
947
+ '''
948
+
949
+ class Model(BaseModel):
950
+ model_config = ConfigDict(coerce_numbers_to_str=True)
951
+
952
+ value: str
953
+
954
+ repr(Model(value=42).value)
955
+ #> "42"
956
+ repr(Model(value=42.13).value)
957
+ #> "42.13"
958
+ repr(Model(value=Decimal('42.13')).value)
959
+ #> "42.13"
960
+ ```
961
+ """
962
+
963
+ regex_engine: Literal['rust-regex', 'python-re']
964
+ """
965
+ The regex engine to be used for pattern validation.
966
+ Defaults to `'rust-regex'`.
967
+
968
+ - `'rust-regex'` uses the [`regex`](https://docs.rs/regex) Rust crate,
969
+ which is non-backtracking and therefore more DDoS resistant, but does not support all regex features.
970
+ - `'python-re'` use the [`re`][] module, which supports all regex features, but may be slower.
971
+
972
+ !!! note
973
+ If you use a compiled regex pattern, the `'python-re'` engine will be used regardless of this setting.
974
+ This is so that flags such as [`re.IGNORECASE`][] are respected.
975
+
976
+ ```python
977
+ from pydantic import BaseModel, ConfigDict, Field, ValidationError
978
+
979
+ class Model(BaseModel):
980
+ model_config = ConfigDict(regex_engine='python-re')
981
+
982
+ value: str = Field(pattern=r'^abc(?=def)')
983
+
984
+ print(Model(value='abcdef').value)
985
+ #> abcdef
986
+
987
+ try:
988
+ print(Model(value='abxyzcdef'))
989
+ except ValidationError as e:
990
+ print(e)
991
+ '''
992
+ 1 validation error for Model
993
+ value
994
+ String should match pattern '^abc(?=def)' [type=string_pattern_mismatch, input_value='abxyzcdef', input_type=str]
995
+ '''
996
+ ```
997
+
998
+ /// version-added | v2.5
999
+ ///
1000
+ """
1001
+
1002
+ validation_error_cause: bool
1003
+ """
1004
+ If `True`, Python exceptions that were part of a validation failure will be shown as an exception group as a cause. Can be useful for debugging. Defaults to `False`.
1005
+
1006
+ Note:
1007
+ Python 3.10 and older don't support exception groups natively. <=3.10, backport must be installed: `pip install exceptiongroup`.
1008
+
1009
+ Note:
1010
+ The structure of validation errors are likely to change in future Pydantic versions. Pydantic offers no guarantees about their structure. Should be used for visual traceback debugging only.
1011
+
1012
+ /// version-added | v2.5
1013
+ ///
1014
+ """
1015
+
1016
+ use_attribute_docstrings: bool
1017
+ '''
1018
+ Whether docstrings of attributes (bare string literals immediately following the attribute declaration)
1019
+ should be used for field descriptions. Defaults to `False`.
1020
+
1021
+ ```python
1022
+ from pydantic import BaseModel, ConfigDict, Field
1023
+
1024
+
1025
+ class Model(BaseModel):
1026
+ model_config = ConfigDict(use_attribute_docstrings=True)
1027
+
1028
+ x: str
1029
+ """
1030
+ Example of an attribute docstring
1031
+ """
1032
+
1033
+ y: int = Field(description="Description in Field")
1034
+ """
1035
+ Description in Field overrides attribute docstring
1036
+ """
1037
+
1038
+
1039
+ print(Model.model_fields["x"].description)
1040
+ # > Example of an attribute docstring
1041
+ print(Model.model_fields["y"].description)
1042
+ # > Description in Field
1043
+ ```
1044
+ This requires the source code of the class to be available at runtime (and so won't work in the interactive interpreter shell).
1045
+
1046
+ !!! warning "Usage with `TypedDict` and stdlib dataclasses"
1047
+ Due to current limitations, attribute docstrings detection may not work as expected when using
1048
+ [`TypedDict`][typing.TypedDict] and stdlib dataclasses, in particular when:
1049
+
1050
+ - inheritance is being used.
1051
+ - multiple classes have the same name in the same source file (unless Python 3.13 or greater is used).
1052
+
1053
+ /// version-added | v2.7
1054
+ ///
1055
+ '''
1056
+
1057
+ cache_strings: bool | Literal['all', 'keys', 'none']
1058
+ """
1059
+ Whether to cache strings to avoid constructing new Python objects. Defaults to True.
1060
+
1061
+ Enabling this setting should significantly improve validation performance while increasing memory usage slightly.
1062
+
1063
+ - `True` or `'all'` (the default): cache all strings
1064
+ - `'keys'`: cache only dictionary keys
1065
+ - `False` or `'none'`: no caching
1066
+
1067
+ !!! note
1068
+ `True` or `'all'` is required to cache strings during general validation because
1069
+ validators don't know if they're in a key or a value.
1070
+
1071
+ !!! tip
1072
+ If repeated strings are rare, it's recommended to use `'keys'` or `'none'` to reduce memory usage,
1073
+ as the performance difference is minimal if repeated strings are rare.
1074
+
1075
+ /// version-added | v2.7
1076
+ ///
1077
+ """
1078
+
1079
+ validate_by_alias: bool
1080
+ """
1081
+ Whether an aliased field may be populated by its alias. Defaults to `True`.
1082
+
1083
+ Here's an example of disabling validation by alias:
1084
+
1085
+ ```py
1086
+ from pydantic import BaseModel, ConfigDict, Field
1087
+
1088
+ class Model(BaseModel):
1089
+ model_config = ConfigDict(validate_by_name=True, validate_by_alias=False)
1090
+
1091
+ my_field: str = Field(validation_alias='my_alias') # (1)!
1092
+
1093
+ m = Model(my_field='foo') # (2)!
1094
+ print(m)
1095
+ #> my_field='foo'
1096
+ ```
1097
+
1098
+ 1. The field `'my_field'` has an alias `'my_alias'`.
1099
+ 2. The model can only be populated by the attribute name `'my_field'`.
1100
+
1101
+ !!! warning
1102
+ You cannot set both `validate_by_alias` and `validate_by_name` to `False`.
1103
+ This would make it impossible to populate an attribute.
1104
+
1105
+ See [usage errors](../errors/usage_errors.md#validate-by-alias-and-name-false) for an example.
1106
+
1107
+ If you set `validate_by_alias` to `False`, under the hood, Pydantic dynamically sets
1108
+ `validate_by_name` to `True` to ensure that validation can still occur.
1109
+
1110
+ /// version-added | v2.11
1111
+ This setting was introduced in conjunction with [`validate_by_name`][pydantic.ConfigDict.validate_by_name]
1112
+ to empower users with more fine grained validation control.
1113
+ ///
1114
+ """
1115
+
1116
+ validate_by_name: bool
1117
+ """
1118
+ Whether an aliased field may be populated by its name as given by the model
1119
+ attribute. Defaults to `False`.
1120
+
1121
+ ```python
1122
+ from pydantic import BaseModel, ConfigDict, Field
1123
+
1124
+ class Model(BaseModel):
1125
+ model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
1126
+
1127
+ my_field: str = Field(validation_alias='my_alias') # (1)!
1128
+
1129
+ m = Model(my_alias='foo') # (2)!
1130
+ print(m)
1131
+ #> my_field='foo'
1132
+
1133
+ m = Model(my_field='foo') # (3)!
1134
+ print(m)
1135
+ #> my_field='foo'
1136
+ ```
1137
+
1138
+ 1. The field `'my_field'` has an alias `'my_alias'`.
1139
+ 2. The model is populated by the alias `'my_alias'`.
1140
+ 3. The model is populated by the attribute name `'my_field'`.
1141
+
1142
+ !!! warning
1143
+ You cannot set both `validate_by_alias` and `validate_by_name` to `False`.
1144
+ This would make it impossible to populate an attribute.
1145
+
1146
+ See [usage errors](../errors/usage_errors.md#validate-by-alias-and-name-false) for an example.
1147
+
1148
+ /// version-added | v2.11
1149
+ This setting was introduced in conjunction with [`validate_by_alias`][pydantic.ConfigDict.validate_by_alias]
1150
+ to empower users with more fine grained validation control. It is an alternative to [`populate_by_name`][pydantic.ConfigDict.populate_by_name],
1151
+ that enables validation by name **and** by alias.
1152
+ ///
1153
+ """
1154
+
1155
+ serialize_by_alias: bool
1156
+ """
1157
+ Whether an aliased field should be serialized by its alias. Defaults to `False`.
1158
+
1159
+ Note: In v2.11, `serialize_by_alias` was introduced to address the
1160
+ [popular request](https://github.com/pydantic/pydantic/issues/8379)
1161
+ for consistency with alias behavior for validation and serialization settings.
1162
+ In v3, the default value is expected to change to `True` for consistency with the validation default.
1163
+
1164
+ ```python
1165
+ from pydantic import BaseModel, ConfigDict, Field
1166
+
1167
+ class Model(BaseModel):
1168
+ model_config = ConfigDict(serialize_by_alias=True)
1169
+
1170
+ my_field: str = Field(serialization_alias='my_alias') # (1)!
1171
+
1172
+ m = Model(my_field='foo')
1173
+ print(m.model_dump()) # (2)!
1174
+ #> {'my_alias': 'foo'}
1175
+ ```
1176
+
1177
+ 1. The field `'my_field'` has an alias `'my_alias'`.
1178
+ 2. The model is serialized using the alias `'my_alias'` for the `'my_field'` attribute.
1179
+
1180
+
1181
+ /// version-added | v2.11
1182
+ This setting was introduced to address the [popular request](https://github.com/pydantic/pydantic/issues/8379)
1183
+ for consistency with alias behavior for validation and serialization.
1184
+
1185
+ In v3, the default value is expected to change to `True` for consistency with the validation default.
1186
+ ///
1187
+ """
1188
+
1189
+ url_preserve_empty_path: bool
1190
+ """
1191
+ Whether to preserve empty URL paths when validating values for a URL type. Defaults to `False`.
1192
+
1193
+ ```python
1194
+ from pydantic import AnyUrl, BaseModel, ConfigDict
1195
+
1196
+ class Model(BaseModel):
1197
+ model_config = ConfigDict(url_preserve_empty_path=True)
1198
+
1199
+ url: AnyUrl
1200
+
1201
+ m = Model(url='http://example.com')
1202
+ print(m.url)
1203
+ #> http://example.com
1204
+ ```
1205
+
1206
+ /// version-added | v2.12
1207
+ ///
1208
+ """
1209
+
1210
+ polymorphic_serialization: bool
1211
+ """
1212
+ Whether to use polymorphic serialization for subclasses of the model or Pydantic dataclass. Defaults to `False`.
1213
+ """
1214
+
1215
+
1216
+ _TypeT = TypeVar('_TypeT', bound=type)
1217
+
1218
+
1219
+ @overload
1220
+ @deprecated('Passing `config` as a keyword argument is deprecated. Pass `config` as a positional argument instead.')
1221
+ def with_config(*, config: ConfigDict) -> Callable[[_TypeT], _TypeT]: ...
1222
+
1223
+
1224
+ @overload
1225
+ def with_config(config: ConfigDict, /) -> Callable[[_TypeT], _TypeT]: ...
1226
+
1227
+
1228
+ @overload
1229
+ def with_config(**config: Unpack[ConfigDict]) -> Callable[[_TypeT], _TypeT]: ...
1230
+
1231
+
1232
+ def with_config(config: ConfigDict | None = None, /, **kwargs: Any) -> Callable[[_TypeT], _TypeT]:
1233
+ """!!! abstract "Usage Documentation"
1234
+ [Configuration with other types](../concepts/config.md#configuration-on-other-supported-types)
1235
+
1236
+ A convenience decorator to set a [Pydantic configuration](config.md) on a `TypedDict` or a `dataclass` from the standard library.
1237
+
1238
+ Although the configuration can be set using the `__pydantic_config__` attribute, it does not play well with type checkers,
1239
+ especially with `TypedDict`.
1240
+
1241
+ !!! example "Usage"
1242
+
1243
+ ```python
1244
+ from typing_extensions import TypedDict
1245
+
1246
+ from pydantic import ConfigDict, TypeAdapter, with_config
1247
+
1248
+ @with_config(ConfigDict(str_to_lower=True))
1249
+ class TD(TypedDict):
1250
+ x: str
1251
+
1252
+ ta = TypeAdapter(TD)
1253
+
1254
+ print(ta.validate_python({'x': 'ABC'}))
1255
+ #> {'x': 'abc'}
1256
+ ```
1257
+
1258
+ /// deprecated-removed | v2.11 v3
1259
+ Passing `config` as a keyword argument.
1260
+ ///
1261
+
1262
+ /// version-changed | v2.11
1263
+ Keyword arguments can be provided directly instead of a config dictionary.
1264
+ ///
1265
+ """
1266
+ if config is not None and kwargs:
1267
+ raise ValueError('Cannot specify both `config` and keyword arguments')
1268
+
1269
+ if len(kwargs) == 1 and (kwargs_conf := kwargs.get('config')) is not None:
1270
+ warnings.warn(
1271
+ 'Passing `config` as a keyword argument is deprecated. Pass `config` as a positional argument instead',
1272
+ category=PydanticDeprecatedSince211,
1273
+ stacklevel=2,
1274
+ )
1275
+ final_config = cast(ConfigDict, kwargs_conf)
1276
+ else:
1277
+ final_config = config if config is not None else cast(ConfigDict, kwargs)
1278
+
1279
+ def inner(class_: _TypeT, /) -> _TypeT:
1280
+ # Ideally, we would check for `class_` to either be a `TypedDict` or a stdlib dataclass.
1281
+ # However, the `@with_config` decorator can be applied *after* `@dataclass`. To avoid
1282
+ # common mistakes, we at least check for `class_` to not be a Pydantic model.
1283
+ from ._internal._utils import is_model_class
1284
+
1285
+ if is_model_class(class_):
1286
+ raise PydanticUserError(
1287
+ f'Cannot use `with_config` on {class_.__name__} as it is a Pydantic model',
1288
+ code='with-config-on-model',
1289
+ )
1290
+ class_.__pydantic_config__ = final_config
1291
+ return class_
1292
+
1293
+ return inner
1294
+
1295
+
1296
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/dataclasses.py ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Provide an enhanced dataclass that performs validation."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ import dataclasses
6
+ import functools
7
+ import sys
8
+ import types
9
+ from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, NoReturn, TypeVar, overload
10
+ from warnings import warn
11
+
12
+ from typing_extensions import TypeGuard, dataclass_transform
13
+
14
+ from ._internal import _config, _decorators, _mock_val_ser, _namespace_utils, _typing_extra
15
+ from ._internal import _dataclasses as _pydantic_dataclasses
16
+ from ._migration import getattr_migration
17
+ from .config import ConfigDict
18
+ from .errors import PydanticUserError
19
+ from .fields import Field, FieldInfo, PrivateAttr
20
+
21
+ if TYPE_CHECKING:
22
+ from ._internal._dataclasses import PydanticDataclass
23
+ from ._internal._namespace_utils import MappingNamespace
24
+
25
+ __all__ = 'dataclass', 'rebuild_dataclass'
26
+
27
+ _T = TypeVar('_T')
28
+
29
+ if sys.version_info >= (3, 10):
30
+
31
+ @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr))
32
+ @overload
33
+ def dataclass(
34
+ *,
35
+ init: Literal[False] = False,
36
+ repr: bool = True,
37
+ eq: bool = True,
38
+ order: bool = False,
39
+ unsafe_hash: bool = False,
40
+ frozen: bool = False,
41
+ config: ConfigDict | type[object] | None = None,
42
+ validate_on_init: bool | None = None,
43
+ kw_only: bool = ...,
44
+ slots: bool = ...,
45
+ ) -> Callable[[type[_T]], type[PydanticDataclass]]: # type: ignore
46
+ ...
47
+
48
+ @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr))
49
+ @overload
50
+ def dataclass(
51
+ _cls: type[_T], # type: ignore
52
+ *,
53
+ init: Literal[False] = False,
54
+ repr: bool = True,
55
+ eq: bool = True,
56
+ order: bool = False,
57
+ unsafe_hash: bool = False,
58
+ frozen: bool | None = None,
59
+ config: ConfigDict | type[object] | None = None,
60
+ validate_on_init: bool | None = None,
61
+ kw_only: bool = ...,
62
+ slots: bool = ...,
63
+ ) -> type[PydanticDataclass]: ...
64
+
65
+ else:
66
+
67
+ @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr))
68
+ @overload
69
+ def dataclass(
70
+ *,
71
+ init: Literal[False] = False,
72
+ repr: bool = True,
73
+ eq: bool = True,
74
+ order: bool = False,
75
+ unsafe_hash: bool = False,
76
+ frozen: bool | None = None,
77
+ config: ConfigDict | type[object] | None = None,
78
+ validate_on_init: bool | None = None,
79
+ ) -> Callable[[type[_T]], type[PydanticDataclass]]: # type: ignore
80
+ ...
81
+
82
+ @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr))
83
+ @overload
84
+ def dataclass(
85
+ _cls: type[_T], # type: ignore
86
+ *,
87
+ init: Literal[False] = False,
88
+ repr: bool = True,
89
+ eq: bool = True,
90
+ order: bool = False,
91
+ unsafe_hash: bool = False,
92
+ frozen: bool | None = None,
93
+ config: ConfigDict | type[object] | None = None,
94
+ validate_on_init: bool | None = None,
95
+ ) -> type[PydanticDataclass]: ...
96
+
97
+
98
+ @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr))
99
+ def dataclass(
100
+ _cls: type[_T] | None = None,
101
+ *,
102
+ init: Literal[False] = False,
103
+ repr: bool = True,
104
+ eq: bool = True,
105
+ order: bool = False,
106
+ unsafe_hash: bool = False,
107
+ frozen: bool | None = None,
108
+ config: ConfigDict | type[object] | None = None,
109
+ validate_on_init: bool | None = None,
110
+ kw_only: bool = False,
111
+ slots: bool = False,
112
+ ) -> Callable[[type[_T]], type[PydanticDataclass]] | type[PydanticDataclass]:
113
+ """!!! abstract "Usage Documentation"
114
+ [`dataclasses`](../concepts/dataclasses.md)
115
+
116
+ A decorator used to create a Pydantic-enhanced dataclass, similar to the standard Python `dataclass`,
117
+ but with added validation.
118
+
119
+ This function should be used similarly to `dataclasses.dataclass`.
120
+
121
+ Args:
122
+ _cls: The target `dataclass`.
123
+ init: Included for signature compatibility with `dataclasses.dataclass`, and is passed through to
124
+ `dataclasses.dataclass` when appropriate. If specified, must be set to `False`, as pydantic inserts its
125
+ own `__init__` function.
126
+ repr: A boolean indicating whether to include the field in the `__repr__` output.
127
+ eq: Determines if a `__eq__` method should be generated for the class.
128
+ order: Determines if comparison magic methods should be generated, such as `__lt__`, but not `__eq__`.
129
+ unsafe_hash: Determines if a `__hash__` method should be included in the class, as in `dataclasses.dataclass`.
130
+ frozen: Determines if the generated class should be a 'frozen' `dataclass`, which does not allow its
131
+ attributes to be modified after it has been initialized. If not set, the value from the provided `config` argument will be used (and will default to `False` otherwise).
132
+ config: The Pydantic config to use for the `dataclass`.
133
+ validate_on_init: A deprecated parameter included for backwards compatibility; in V2, all Pydantic dataclasses
134
+ are validated on init.
135
+ kw_only: Determines if `__init__` method parameters must be specified by keyword only. Defaults to `False`.
136
+ slots: Determines if the generated class should be a 'slots' `dataclass`, which does not allow the addition of
137
+ new attributes after instantiation.
138
+
139
+ Returns:
140
+ A decorator that accepts a class as its argument and returns a Pydantic `dataclass`.
141
+
142
+ Raises:
143
+ AssertionError: Raised if `init` is not `False` or `validate_on_init` is `False`.
144
+ """
145
+ assert init is False, 'pydantic.dataclasses.dataclass only supports init=False'
146
+ assert validate_on_init is not False, 'validate_on_init=False is no longer supported'
147
+
148
+ if sys.version_info >= (3, 10):
149
+ kwargs = {'kw_only': kw_only, 'slots': slots}
150
+ else:
151
+ kwargs = {}
152
+
153
+ def create_dataclass(cls: type[Any]) -> type[PydanticDataclass]:
154
+ """Create a Pydantic dataclass from a regular dataclass.
155
+
156
+ Args:
157
+ cls: The class to create the Pydantic dataclass from.
158
+
159
+ Returns:
160
+ A Pydantic dataclass.
161
+ """
162
+ from ._internal._utils import is_model_class
163
+
164
+ if is_model_class(cls):
165
+ raise PydanticUserError(
166
+ f'Cannot create a Pydantic dataclass from {cls.__name__} as it is already a Pydantic model',
167
+ code='dataclass-on-model',
168
+ )
169
+
170
+ original_cls = cls
171
+
172
+ # we warn on conflicting config specifications, but only if the class doesn't have a dataclass base
173
+ # because a dataclass base might provide a __pydantic_config__ attribute that we don't want to warn about
174
+ has_dataclass_base = any(dataclasses.is_dataclass(base) for base in cls.__bases__)
175
+ if not has_dataclass_base and config is not None and hasattr(cls, '__pydantic_config__'):
176
+ warn(
177
+ f'`config` is set via both the `dataclass` decorator and `__pydantic_config__` for dataclass {cls.__name__}. '
178
+ f'The `config` specification from `dataclass` decorator will take priority.',
179
+ category=UserWarning,
180
+ stacklevel=2,
181
+ )
182
+
183
+ # if config is not explicitly provided, try to read it from the type
184
+ config_dict = config if config is not None else getattr(cls, '__pydantic_config__', None)
185
+ config_wrapper = _config.ConfigWrapper(config_dict)
186
+ decorators = _decorators.DecoratorInfos.build(cls, replace_wrapped_methods=True)
187
+ decorators.update_from_config(config_wrapper)
188
+
189
+ # Keep track of the original __doc__ so that we can restore it after applying the dataclasses decorator
190
+ # Otherwise, classes with no __doc__ will have their signature added into the JSON schema description,
191
+ # since dataclasses.dataclass will set this as the __doc__
192
+ original_doc = cls.__doc__
193
+
194
+ if _pydantic_dataclasses.is_stdlib_dataclass(cls):
195
+ # Vanilla dataclasses include a default docstring (representing the class signature),
196
+ # which we don't want to preserve.
197
+ original_doc = None
198
+
199
+ # We don't want to add validation to the existing std lib dataclass, so we will subclass it
200
+ # If the class is generic, we need to make sure the subclass also inherits from Generic
201
+ # with all the same parameters.
202
+ bases = (cls,)
203
+ if issubclass(cls, Generic):
204
+ generic_base = Generic[cls.__parameters__] # type: ignore
205
+ bases = bases + (generic_base,)
206
+ cls = types.new_class(cls.__name__, bases)
207
+
208
+ # Respect frozen setting from dataclass constructor and fallback to config setting if not provided
209
+ if frozen is not None:
210
+ frozen_ = frozen
211
+ if config_wrapper.frozen:
212
+ # It's not recommended to define both, as the setting from the dataclass decorator will take priority.
213
+ warn(
214
+ f'`frozen` is set via both the `dataclass` decorator and `config` for dataclass {cls.__name__!r}.'
215
+ 'This is not recommended. The `frozen` specification on `dataclass` will take priority.',
216
+ category=UserWarning,
217
+ stacklevel=2,
218
+ )
219
+ else:
220
+ frozen_ = config_wrapper.frozen or False
221
+
222
+ # Make Pydantic's `Field()` function compatible with stdlib dataclasses. As we'll decorate
223
+ # `cls` with the stdlib `@dataclass` decorator first, there are two attributes, `kw_only` and
224
+ # `repr` that need to be understood *during* the stdlib creation. We do so in two steps:
225
+
226
+ # 1. On the decorated class, wrap `Field()` assignment with `dataclass.field()`, with the
227
+ # two attributes set (done in `as_dataclass_field()`)
228
+ cls_anns = _typing_extra.safe_get_annotations(cls)
229
+ for field_name in cls_anns:
230
+ # We should look for assignments in `__dict__` instead, but for now we follow
231
+ # the same behavior as stdlib dataclasses (see https://github.com/python/cpython/issues/88609)
232
+ field_value = getattr(cls, field_name, None)
233
+ if isinstance(field_value, FieldInfo):
234
+ setattr(cls, field_name, _pydantic_dataclasses.as_dataclass_field(field_value))
235
+
236
+ # 2. For bases of `cls` that are stdlib dataclasses, we temporarily patch their fields
237
+ # (see the docstring of the context manager):
238
+ with _pydantic_dataclasses.patch_base_fields(cls):
239
+ cls = dataclasses.dataclass( # pyright: ignore[reportCallIssue]
240
+ cls,
241
+ # the value of init here doesn't affect anything except that it makes it easier to generate a signature
242
+ init=True,
243
+ repr=repr,
244
+ eq=eq,
245
+ order=order,
246
+ unsafe_hash=unsafe_hash,
247
+ frozen=frozen_,
248
+ **kwargs,
249
+ )
250
+
251
+ if config_wrapper.validate_assignment:
252
+ original_setattr = cls.__setattr__
253
+
254
+ @functools.wraps(cls.__setattr__)
255
+ def validated_setattr(instance: PydanticDataclass, name: str, value: Any, /) -> None:
256
+ if frozen_:
257
+ return original_setattr(instance, name, value) # pyright: ignore[reportCallIssue]
258
+ inst_cls = type(instance)
259
+ attr = getattr(inst_cls, name, None)
260
+
261
+ if isinstance(attr, property):
262
+ attr.__set__(instance, value)
263
+ elif isinstance(attr, functools.cached_property):
264
+ instance.__dict__.__setitem__(name, value)
265
+ else:
266
+ inst_cls.__pydantic_validator__.validate_assignment(instance, name, value)
267
+
268
+ cls.__setattr__ = validated_setattr.__get__(None, cls) # type: ignore
269
+
270
+ if slots and not hasattr(cls, '__setstate__'):
271
+ # If slots is set, `pickle` (relied on by `copy.copy()`) will use
272
+ # `__setattr__()` to reconstruct the dataclass. However, the custom
273
+ # `__setattr__()` set above relies on `validate_assignment()`, which
274
+ # in turn expects all the field values to be already present on the
275
+ # instance, resulting in attribute errors.
276
+ # As such, we make use of `object.__setattr__()` instead.
277
+ # Note that we do so only if `__setstate__()` isn't already set (this is the
278
+ # case if on top of `slots`, `frozen` is used).
279
+
280
+ # Taken from `dataclasses._dataclass_get/setstate()`:
281
+ def _dataclass_getstate(self: Any) -> list[Any]:
282
+ return [getattr(self, f.name) for f in dataclasses.fields(self)]
283
+
284
+ def _dataclass_setstate(self: Any, state: list[Any]) -> None:
285
+ for field, value in zip(dataclasses.fields(self), state):
286
+ object.__setattr__(self, field.name, value)
287
+
288
+ cls.__getstate__ = _dataclass_getstate # pyright: ignore[reportAttributeAccessIssue]
289
+ cls.__setstate__ = _dataclass_setstate # pyright: ignore[reportAttributeAccessIssue]
290
+
291
+ # This is an undocumented attribute to distinguish stdlib/Pydantic dataclasses.
292
+ # It should be set as early as possible:
293
+ cls.__is_pydantic_dataclass__ = True
294
+ cls.__pydantic_decorators__ = decorators # type: ignore
295
+ cls.__doc__ = original_doc
296
+ # Can be non-existent for dynamically created classes:
297
+ firstlineno = getattr(original_cls, '__firstlineno__', None)
298
+ cls.__module__ = original_cls.__module__
299
+ if sys.version_info >= (3, 13) and firstlineno is not None:
300
+ # As per https://docs.python.org/3/reference/datamodel.html#type.__firstlineno__:
301
+ # Setting the `__module__` attribute removes the `__firstlineno__` item from the type’s dictionary.
302
+ original_cls.__firstlineno__ = firstlineno
303
+ cls.__firstlineno__ = firstlineno
304
+ cls.__qualname__ = original_cls.__qualname__
305
+ cls.__pydantic_fields_complete__ = classmethod(_pydantic_fields_complete)
306
+ cls.__pydantic_complete__ = False # `complete_dataclass` will set it to `True` if successful.
307
+ # TODO `parent_namespace` is currently None, but we could do the same thing as Pydantic models:
308
+ # fetch the parent ns using `parent_frame_namespace` (if the dataclass was defined in a function),
309
+ # and possibly cache it (see the `__pydantic_parent_namespace__` logic for models).
310
+ _pydantic_dataclasses.complete_dataclass(cls, config_wrapper, raise_errors=False)
311
+ return cls
312
+
313
+ return create_dataclass if _cls is None else create_dataclass(_cls)
314
+
315
+
316
+ def _pydantic_fields_complete(cls: type[PydanticDataclass]) -> bool:
317
+ """Return whether the fields were successfully collected (i.e. type hints were successfully resolved).
318
+
319
+ This is a private helper, not meant to be used outside Pydantic.
320
+ """
321
+ return all(field_info._complete for field_info in cls.__pydantic_fields__.values())
322
+
323
+
324
+ __getattr__ = getattr_migration(__name__)
325
+
326
+ if sys.version_info < (3, 11):
327
+ # Monkeypatch dataclasses.InitVar so that typing doesn't error if it occurs as a type when evaluating type hints
328
+ # Starting in 3.11, typing.get_type_hints will not raise an error if the retrieved type hints are not callable.
329
+
330
+ def _call_initvar(*args: Any, **kwargs: Any) -> NoReturn:
331
+ """This function does nothing but raise an error that is as similar as possible to what you'd get
332
+ if you were to try calling `InitVar[int]()` without this monkeypatch. The whole purpose is just
333
+ to ensure typing._type_check does not error if the type hint evaluates to `InitVar[<parameter>]`.
334
+ """
335
+ raise TypeError("'InitVar' object is not callable")
336
+
337
+ dataclasses.InitVar.__call__ = _call_initvar
338
+
339
+
340
+ def rebuild_dataclass(
341
+ cls: type[PydanticDataclass],
342
+ *,
343
+ force: bool = False,
344
+ raise_errors: bool = True,
345
+ _parent_namespace_depth: int = 2,
346
+ _types_namespace: MappingNamespace | None = None,
347
+ ) -> bool | None:
348
+ """Try to rebuild the pydantic-core schema for the dataclass.
349
+
350
+ This may be necessary when one of the annotations is a ForwardRef which could not be resolved during
351
+ the initial attempt to build the schema, and automatic rebuilding fails.
352
+
353
+ This is analogous to `BaseModel.model_rebuild`.
354
+
355
+ Args:
356
+ cls: The class to rebuild the pydantic-core schema for.
357
+ force: Whether to force the rebuilding of the schema, defaults to `False`.
358
+ raise_errors: Whether to raise errors, defaults to `True`.
359
+ _parent_namespace_depth: The depth level of the parent namespace, defaults to 2.
360
+ _types_namespace: The types namespace, defaults to `None`.
361
+
362
+ Returns:
363
+ Returns `None` if the schema is already "complete" and rebuilding was not required.
364
+ If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`.
365
+ """
366
+ if not force and cls.__pydantic_complete__:
367
+ return None
368
+
369
+ for attr in ('__pydantic_core_schema__', '__pydantic_validator__', '__pydantic_serializer__'):
370
+ if attr in cls.__dict__ and not isinstance(getattr(cls, attr), _mock_val_ser.MockValSer):
371
+ # Deleting the validator/serializer is necessary as otherwise they can get reused in
372
+ # pydantic-core. Same applies for the core schema that can be reused in schema generation.
373
+ delattr(cls, attr)
374
+
375
+ cls.__pydantic_complete__ = False
376
+
377
+ if _types_namespace is not None:
378
+ rebuild_ns = _types_namespace
379
+ elif _parent_namespace_depth > 0:
380
+ rebuild_ns = _typing_extra.parent_frame_namespace(parent_depth=_parent_namespace_depth, force=True) or {}
381
+ else:
382
+ rebuild_ns = {}
383
+
384
+ ns_resolver = _namespace_utils.NsResolver(
385
+ parent_namespace=rebuild_ns,
386
+ )
387
+
388
+ return _pydantic_dataclasses.complete_dataclass(
389
+ cls,
390
+ _config.ConfigWrapper(cls.__pydantic_config__, check=False),
391
+ raise_errors=raise_errors,
392
+ ns_resolver=ns_resolver,
393
+ # We could provide a different config instead (with `'defer_build'` set to `True`)
394
+ # of this explicit `_force_build` argument, but because config can come from the
395
+ # decorator parameter or the `__pydantic_config__` attribute, `complete_dataclass`
396
+ # will overwrite `__pydantic_config__` with the provided config above:
397
+ _force_build=True,
398
+ )
399
+
400
+
401
+ def is_pydantic_dataclass(class_: type[Any], /) -> TypeGuard[type[PydanticDataclass]]:
402
+ """Whether a class is a pydantic dataclass.
403
+
404
+ Args:
405
+ class_: The class.
406
+
407
+ Returns:
408
+ `True` if the class is a pydantic dataclass, `False` otherwise.
409
+ """
410
+ try:
411
+ return '__is_pydantic_dataclass__' in class_.__dict__ and dataclasses.is_dataclass(class_)
412
+ except AttributeError:
413
+ return False
.mcp-venv/lib/python3.13/site-packages/pydantic/datetime_parse.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """The `datetime_parse` module is a backport module from V1."""
2
+
3
+ from ._migration import getattr_migration
4
+
5
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/decorator.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """The `decorator` module is a backport module from V1."""
2
+
3
+ from ._migration import getattr_migration
4
+
5
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/__init__.py ADDED
File without changes
.mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/class_validators.py ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Old `@validator` and `@root_validator` function validators from V1."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ from functools import partial, partialmethod
6
+ from types import FunctionType
7
+ from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, Union, overload
8
+ from warnings import warn
9
+
10
+ from typing_extensions import Protocol, TypeAlias, deprecated
11
+
12
+ from .._internal import _decorators, _decorators_v1
13
+ from ..errors import PydanticUserError
14
+ from ..warnings import PydanticDeprecatedSince20
15
+
16
+ _ALLOW_REUSE_WARNING_MESSAGE = '`allow_reuse` is deprecated and will be ignored; it should no longer be necessary'
17
+
18
+
19
+ if TYPE_CHECKING:
20
+
21
+ class _OnlyValueValidatorClsMethod(Protocol):
22
+ def __call__(self, __cls: Any, __value: Any) -> Any: ...
23
+
24
+ class _V1ValidatorWithValuesClsMethod(Protocol):
25
+ def __call__(self, __cls: Any, __value: Any, values: dict[str, Any]) -> Any: ...
26
+
27
+ class _V1ValidatorWithValuesKwOnlyClsMethod(Protocol):
28
+ def __call__(self, __cls: Any, __value: Any, *, values: dict[str, Any]) -> Any: ...
29
+
30
+ class _V1ValidatorWithKwargsClsMethod(Protocol):
31
+ def __call__(self, __cls: Any, **kwargs: Any) -> Any: ...
32
+
33
+ class _V1ValidatorWithValuesAndKwargsClsMethod(Protocol):
34
+ def __call__(self, __cls: Any, values: dict[str, Any], **kwargs: Any) -> Any: ...
35
+
36
+ class _V1RootValidatorClsMethod(Protocol):
37
+ def __call__(
38
+ self, __cls: Any, __values: _decorators_v1.RootValidatorValues
39
+ ) -> _decorators_v1.RootValidatorValues: ...
40
+
41
+ V1Validator = Union[
42
+ _OnlyValueValidatorClsMethod,
43
+ _V1ValidatorWithValuesClsMethod,
44
+ _V1ValidatorWithValuesKwOnlyClsMethod,
45
+ _V1ValidatorWithKwargsClsMethod,
46
+ _V1ValidatorWithValuesAndKwargsClsMethod,
47
+ _decorators_v1.V1ValidatorWithValues,
48
+ _decorators_v1.V1ValidatorWithValuesKwOnly,
49
+ _decorators_v1.V1ValidatorWithKwargs,
50
+ _decorators_v1.V1ValidatorWithValuesAndKwargs,
51
+ ]
52
+
53
+ V1RootValidator = Union[
54
+ _V1RootValidatorClsMethod,
55
+ _decorators_v1.V1RootValidatorFunction,
56
+ ]
57
+
58
+ _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]]
59
+
60
+ # Allow both a V1 (assumed pre=False) or V2 (assumed mode='after') validator
61
+ # We lie to type checkers and say we return the same thing we get
62
+ # but in reality we return a proxy object that _mostly_ behaves like the wrapped thing
63
+ _V1ValidatorType = TypeVar('_V1ValidatorType', V1Validator, _PartialClsOrStaticMethod)
64
+ _V1RootValidatorFunctionType = TypeVar(
65
+ '_V1RootValidatorFunctionType',
66
+ _decorators_v1.V1RootValidatorFunction,
67
+ _V1RootValidatorClsMethod,
68
+ _PartialClsOrStaticMethod,
69
+ )
70
+ else:
71
+ # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
72
+ # and https://youtrack.jetbrains.com/issue/PY-51428
73
+ DeprecationWarning = PydanticDeprecatedSince20
74
+
75
+
76
+ @deprecated(
77
+ 'Pydantic V1 style `@validator` validators are deprecated.'
78
+ ' You should migrate to Pydantic V2 style `@field_validator` validators,'
79
+ ' see the migration guide for more details',
80
+ category=None,
81
+ )
82
+ def validator(
83
+ __field: str,
84
+ *fields: str,
85
+ pre: bool = False,
86
+ each_item: bool = False,
87
+ always: bool = False,
88
+ check_fields: bool | None = None,
89
+ allow_reuse: bool = False,
90
+ ) -> Callable[[_V1ValidatorType], _V1ValidatorType]:
91
+ """Decorate methods on the class indicating that they should be used to validate fields.
92
+
93
+ Args:
94
+ __field (str): The first field the validator should be called on; this is separate
95
+ from `fields` to ensure an error is raised if you don't pass at least one.
96
+ *fields (str): Additional field(s) the validator should be called on.
97
+ pre (bool, optional): Whether this validator should be called before the standard
98
+ validators (else after). Defaults to False.
99
+ each_item (bool, optional): For complex objects (sets, lists etc.) whether to validate
100
+ individual elements rather than the whole object. Defaults to False.
101
+ always (bool, optional): Whether this method and other validators should be called even if
102
+ the value is missing. Defaults to False.
103
+ check_fields (bool | None, optional): Whether to check that the fields actually exist on the model.
104
+ Defaults to None.
105
+ allow_reuse (bool, optional): Whether to track and raise an error if another validator refers to
106
+ the decorated function. Defaults to False.
107
+
108
+ Returns:
109
+ Callable: A decorator that can be used to decorate a
110
+ function to be used as a validator.
111
+ """
112
+ warn(
113
+ 'Pydantic V1 style `@validator` validators are deprecated.'
114
+ ' You should migrate to Pydantic V2 style `@field_validator` validators,'
115
+ ' see the migration guide for more details',
116
+ DeprecationWarning,
117
+ stacklevel=2,
118
+ )
119
+
120
+ if allow_reuse is True: # pragma: no cover
121
+ warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning, stacklevel=2)
122
+ fields = __field, *fields
123
+ if isinstance(fields[0], FunctionType):
124
+ raise PydanticUserError(
125
+ '`@validator` should be used with fields and keyword arguments, not bare. '
126
+ "E.g. usage should be `@validator('<field_name>', ...)`",
127
+ code='decorator-missing-arguments',
128
+ )
129
+ elif not all(isinstance(field, str) for field in fields):
130
+ raise PydanticUserError(
131
+ '`@validator` fields should be passed as separate string args. '
132
+ "E.g. usage should be `@validator('<field_name_1>', '<field_name_2>', ...)`",
133
+ code='decorator-invalid-fields',
134
+ )
135
+
136
+ mode: Literal['before', 'after'] = 'before' if pre is True else 'after'
137
+
138
+ def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]:
139
+ if _decorators.is_instance_method_from_sig(f):
140
+ raise PydanticUserError(
141
+ '`@validator` cannot be applied to instance methods', code='validator-instance-method'
142
+ )
143
+ # auto apply the @classmethod decorator
144
+ f = _decorators.ensure_classmethod_based_on_signature(f)
145
+ wrap = _decorators_v1.make_generic_v1_field_validator
146
+ validator_wrapper_info = _decorators.ValidatorDecoratorInfo(
147
+ fields=fields,
148
+ mode=mode,
149
+ each_item=each_item,
150
+ always=always,
151
+ check_fields=check_fields,
152
+ )
153
+ return _decorators.PydanticDescriptorProxy(f, validator_wrapper_info, shim=wrap)
154
+
155
+ return dec # type: ignore[return-value]
156
+
157
+
158
+ @overload
159
+ def root_validator(
160
+ *,
161
+ # if you don't specify `pre` the default is `pre=False`
162
+ # which means you need to specify `skip_on_failure=True`
163
+ skip_on_failure: Literal[True],
164
+ allow_reuse: bool = ...,
165
+ ) -> Callable[
166
+ [_V1RootValidatorFunctionType],
167
+ _V1RootValidatorFunctionType,
168
+ ]: ...
169
+
170
+
171
+ @overload
172
+ def root_validator(
173
+ *,
174
+ # if you specify `pre=True` then you don't need to specify
175
+ # `skip_on_failure`, in fact it is not allowed as an argument!
176
+ pre: Literal[True],
177
+ allow_reuse: bool = ...,
178
+ ) -> Callable[
179
+ [_V1RootValidatorFunctionType],
180
+ _V1RootValidatorFunctionType,
181
+ ]: ...
182
+
183
+
184
+ @overload
185
+ def root_validator(
186
+ *,
187
+ # if you explicitly specify `pre=False` then you
188
+ # MUST specify `skip_on_failure=True`
189
+ pre: Literal[False],
190
+ skip_on_failure: Literal[True],
191
+ allow_reuse: bool = ...,
192
+ ) -> Callable[
193
+ [_V1RootValidatorFunctionType],
194
+ _V1RootValidatorFunctionType,
195
+ ]: ...
196
+
197
+
198
+ @deprecated(
199
+ 'Pydantic V1 style `@root_validator` validators are deprecated.'
200
+ ' You should migrate to Pydantic V2 style `@model_validator` validators,'
201
+ ' see the migration guide for more details',
202
+ category=None,
203
+ )
204
+ def root_validator(
205
+ *__args,
206
+ pre: bool = False,
207
+ skip_on_failure: bool = False,
208
+ allow_reuse: bool = False,
209
+ ) -> Any:
210
+ """Decorate methods on a model indicating that they should be used to validate (and perhaps
211
+ modify) data either before or after standard model parsing/validation is performed.
212
+
213
+ Args:
214
+ pre (bool, optional): Whether this validator should be called before the standard
215
+ validators (else after). Defaults to False.
216
+ skip_on_failure (bool, optional): Whether to stop validation and return as soon as a
217
+ failure is encountered. Defaults to False.
218
+ allow_reuse (bool, optional): Whether to track and raise an error if another validator
219
+ refers to the decorated function. Defaults to False.
220
+
221
+ Returns:
222
+ Any: A decorator that can be used to decorate a function to be used as a root_validator.
223
+ """
224
+ warn(
225
+ 'Pydantic V1 style `@root_validator` validators are deprecated.'
226
+ ' You should migrate to Pydantic V2 style `@model_validator` validators,'
227
+ ' see the migration guide for more details',
228
+ DeprecationWarning,
229
+ stacklevel=2,
230
+ )
231
+
232
+ if __args:
233
+ # Ensure a nice error is raised if someone attempts to use the bare decorator
234
+ return root_validator()(*__args) # type: ignore
235
+
236
+ if allow_reuse is True: # pragma: no cover
237
+ warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning, stacklevel=2)
238
+ mode: Literal['before', 'after'] = 'before' if pre is True else 'after'
239
+ if pre is False and skip_on_failure is not True:
240
+ raise PydanticUserError(
241
+ 'If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`.'
242
+ ' Note that `@root_validator` is deprecated and should be replaced with `@model_validator`.',
243
+ code='root-validator-pre-skip',
244
+ )
245
+
246
+ wrap = partial(_decorators_v1.make_v1_generic_root_validator, pre=pre)
247
+
248
+ def dec(f: Callable[..., Any] | classmethod[Any, Any, Any] | staticmethod[Any, Any]) -> Any:
249
+ if _decorators.is_instance_method_from_sig(f):
250
+ raise TypeError('`@root_validator` cannot be applied to instance methods')
251
+ # auto apply the @classmethod decorator
252
+ res = _decorators.ensure_classmethod_based_on_signature(f)
253
+ dec_info = _decorators.RootValidatorDecoratorInfo(mode=mode)
254
+ return _decorators.PydanticDescriptorProxy(res, dec_info, shim=wrap)
255
+
256
+ return dec
.mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/config.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations as _annotations
2
+
3
+ import warnings
4
+ from typing import TYPE_CHECKING, Any, Literal
5
+
6
+ from typing_extensions import deprecated
7
+
8
+ from .._internal import _config
9
+ from ..warnings import PydanticDeprecatedSince20
10
+
11
+ if not TYPE_CHECKING:
12
+ # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
13
+ # and https://youtrack.jetbrains.com/issue/PY-51428
14
+ DeprecationWarning = PydanticDeprecatedSince20
15
+
16
+ __all__ = 'BaseConfig', 'Extra'
17
+
18
+
19
+ class _ConfigMetaclass(type):
20
+ def __getattr__(self, item: str) -> Any:
21
+ try:
22
+ obj = _config.config_defaults[item]
23
+ warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
24
+ return obj
25
+ except KeyError as exc:
26
+ raise AttributeError(f"type object '{self.__name__}' has no attribute {exc}") from exc
27
+
28
+
29
+ @deprecated('BaseConfig is deprecated. Use the `pydantic.ConfigDict` instead.', category=PydanticDeprecatedSince20)
30
+ class BaseConfig(metaclass=_ConfigMetaclass):
31
+ """This class is only retained for backwards compatibility.
32
+
33
+ !!! Warning "Deprecated"
34
+ BaseConfig is deprecated. Use the [`pydantic.ConfigDict`][pydantic.ConfigDict] instead.
35
+ """
36
+
37
+ def __getattr__(self, item: str) -> Any:
38
+ try:
39
+ obj = super().__getattribute__(item)
40
+ warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
41
+ return obj
42
+ except AttributeError as exc:
43
+ try:
44
+ return getattr(type(self), item)
45
+ except AttributeError:
46
+ # re-raising changes the displayed text to reflect that `self` is not a type
47
+ raise AttributeError(str(exc)) from exc
48
+
49
+ def __init_subclass__(cls, **kwargs: Any) -> None:
50
+ warnings.warn(_config.DEPRECATION_MESSAGE, DeprecationWarning)
51
+ return super().__init_subclass__(**kwargs)
52
+
53
+
54
+ class _ExtraMeta(type):
55
+ def __getattribute__(self, __name: str) -> Any:
56
+ # The @deprecated decorator accesses other attributes, so we only emit a warning for the expected ones
57
+ if __name in {'allow', 'ignore', 'forbid'}:
58
+ warnings.warn(
59
+ "`pydantic.config.Extra` is deprecated, use literal values instead (e.g. `extra='allow'`)",
60
+ DeprecationWarning,
61
+ stacklevel=2,
62
+ )
63
+ return super().__getattribute__(__name)
64
+
65
+
66
+ @deprecated(
67
+ "Extra is deprecated. Use literal values instead (e.g. `extra='allow'`)", category=PydanticDeprecatedSince20
68
+ )
69
+ class Extra(metaclass=_ExtraMeta):
70
+ allow: Literal['allow'] = 'allow'
71
+ ignore: Literal['ignore'] = 'ignore'
72
+ forbid: Literal['forbid'] = 'forbid'
.mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/copy_internals.py ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations as _annotations
2
+
3
+ import typing
4
+ from copy import deepcopy
5
+ from enum import Enum
6
+ from typing import Any
7
+
8
+ import typing_extensions
9
+
10
+ from .._internal import (
11
+ _model_construction,
12
+ _typing_extra,
13
+ _utils,
14
+ )
15
+
16
+ if typing.TYPE_CHECKING:
17
+ from .. import BaseModel
18
+ from .._internal._utils import AbstractSetIntStr, MappingIntStrAny
19
+
20
+ AnyClassMethod = classmethod[Any, Any, Any]
21
+ TupleGenerator = typing.Generator[tuple[str, Any], None, None]
22
+ Model = typing.TypeVar('Model', bound='BaseModel')
23
+ # should be `set[int] | set[str] | dict[int, IncEx] | dict[str, IncEx] | None`, but mypy can't cope
24
+ IncEx: typing_extensions.TypeAlias = 'set[int] | set[str] | dict[int, Any] | dict[str, Any] | None'
25
+
26
+ _object_setattr = _model_construction.object_setattr
27
+
28
+
29
+ def _iter(
30
+ self: BaseModel,
31
+ to_dict: bool = False,
32
+ by_alias: bool = False,
33
+ include: AbstractSetIntStr | MappingIntStrAny | None = None,
34
+ exclude: AbstractSetIntStr | MappingIntStrAny | None = None,
35
+ exclude_unset: bool = False,
36
+ exclude_defaults: bool = False,
37
+ exclude_none: bool = False,
38
+ ) -> TupleGenerator:
39
+ # Merge field set excludes with explicit exclude parameter with explicit overriding field set options.
40
+ # The extra "is not None" guards are not logically necessary but optimizes performance for the simple case.
41
+ if exclude is not None:
42
+ exclude = _utils.ValueItems.merge(
43
+ {k: v.exclude for k, v in self.__pydantic_fields__.items() if v.exclude is not None}, exclude
44
+ )
45
+
46
+ if include is not None:
47
+ include = _utils.ValueItems.merge(dict.fromkeys(self.__pydantic_fields__, True), include, intersect=True)
48
+
49
+ allowed_keys = _calculate_keys(self, include=include, exclude=exclude, exclude_unset=exclude_unset) # type: ignore
50
+ if allowed_keys is None and not (to_dict or by_alias or exclude_unset or exclude_defaults or exclude_none):
51
+ # huge boost for plain _iter()
52
+ yield from self.__dict__.items()
53
+ if self.__pydantic_extra__:
54
+ yield from self.__pydantic_extra__.items()
55
+ return
56
+
57
+ value_exclude = _utils.ValueItems(self, exclude) if exclude is not None else None
58
+ value_include = _utils.ValueItems(self, include) if include is not None else None
59
+
60
+ if self.__pydantic_extra__ is None:
61
+ items = self.__dict__.items()
62
+ else:
63
+ items = list(self.__dict__.items()) + list(self.__pydantic_extra__.items())
64
+
65
+ for field_key, v in items:
66
+ if (allowed_keys is not None and field_key not in allowed_keys) or (exclude_none and v is None):
67
+ continue
68
+
69
+ if exclude_defaults:
70
+ try:
71
+ field = self.__pydantic_fields__[field_key]
72
+ except KeyError:
73
+ pass
74
+ else:
75
+ if not field.is_required() and field.default == v:
76
+ continue
77
+
78
+ if by_alias and field_key in self.__pydantic_fields__:
79
+ dict_key = self.__pydantic_fields__[field_key].alias or field_key
80
+ else:
81
+ dict_key = field_key
82
+
83
+ if to_dict or value_include or value_exclude:
84
+ v = _get_value(
85
+ type(self),
86
+ v,
87
+ to_dict=to_dict,
88
+ by_alias=by_alias,
89
+ include=value_include and value_include.for_element(field_key),
90
+ exclude=value_exclude and value_exclude.for_element(field_key),
91
+ exclude_unset=exclude_unset,
92
+ exclude_defaults=exclude_defaults,
93
+ exclude_none=exclude_none,
94
+ )
95
+ yield dict_key, v
96
+
97
+
98
+ def _copy_and_set_values(
99
+ self: Model,
100
+ values: dict[str, Any],
101
+ fields_set: set[str],
102
+ extra: dict[str, Any] | None = None,
103
+ private: dict[str, Any] | None = None,
104
+ *,
105
+ deep: bool, # UP006
106
+ ) -> Model:
107
+ if deep:
108
+ # chances of having empty dict here are quite low for using smart_deepcopy
109
+ values = deepcopy(values)
110
+ extra = deepcopy(extra)
111
+ private = deepcopy(private)
112
+
113
+ cls = self.__class__
114
+ m = cls.__new__(cls)
115
+ _object_setattr(m, '__dict__', values)
116
+ _object_setattr(m, '__pydantic_extra__', extra)
117
+ _object_setattr(m, '__pydantic_fields_set__', fields_set)
118
+ _object_setattr(m, '__pydantic_private__', private)
119
+
120
+ return m
121
+
122
+
123
+ @typing.no_type_check
124
+ def _get_value(
125
+ cls: type[BaseModel],
126
+ v: Any,
127
+ to_dict: bool,
128
+ by_alias: bool,
129
+ include: AbstractSetIntStr | MappingIntStrAny | None,
130
+ exclude: AbstractSetIntStr | MappingIntStrAny | None,
131
+ exclude_unset: bool,
132
+ exclude_defaults: bool,
133
+ exclude_none: bool,
134
+ ) -> Any:
135
+ from .. import BaseModel
136
+
137
+ if isinstance(v, BaseModel):
138
+ if to_dict:
139
+ return v.model_dump(
140
+ by_alias=by_alias,
141
+ exclude_unset=exclude_unset,
142
+ exclude_defaults=exclude_defaults,
143
+ include=include, # type: ignore
144
+ exclude=exclude, # type: ignore
145
+ exclude_none=exclude_none,
146
+ )
147
+ else:
148
+ return v.copy(include=include, exclude=exclude)
149
+
150
+ value_exclude = _utils.ValueItems(v, exclude) if exclude else None
151
+ value_include = _utils.ValueItems(v, include) if include else None
152
+
153
+ if isinstance(v, dict):
154
+ return {
155
+ k_: _get_value(
156
+ cls,
157
+ v_,
158
+ to_dict=to_dict,
159
+ by_alias=by_alias,
160
+ exclude_unset=exclude_unset,
161
+ exclude_defaults=exclude_defaults,
162
+ include=value_include and value_include.for_element(k_),
163
+ exclude=value_exclude and value_exclude.for_element(k_),
164
+ exclude_none=exclude_none,
165
+ )
166
+ for k_, v_ in v.items()
167
+ if (not value_exclude or not value_exclude.is_excluded(k_))
168
+ and (not value_include or value_include.is_included(k_))
169
+ }
170
+
171
+ elif _utils.sequence_like(v):
172
+ seq_args = (
173
+ _get_value(
174
+ cls,
175
+ v_,
176
+ to_dict=to_dict,
177
+ by_alias=by_alias,
178
+ exclude_unset=exclude_unset,
179
+ exclude_defaults=exclude_defaults,
180
+ include=value_include and value_include.for_element(i),
181
+ exclude=value_exclude and value_exclude.for_element(i),
182
+ exclude_none=exclude_none,
183
+ )
184
+ for i, v_ in enumerate(v)
185
+ if (not value_exclude or not value_exclude.is_excluded(i))
186
+ and (not value_include or value_include.is_included(i))
187
+ )
188
+
189
+ return v.__class__(*seq_args) if _typing_extra.is_namedtuple(v.__class__) else v.__class__(seq_args)
190
+
191
+ elif isinstance(v, Enum) and getattr(cls.model_config, 'use_enum_values', False):
192
+ return v.value
193
+
194
+ else:
195
+ return v
196
+
197
+
198
+ def _calculate_keys(
199
+ self: BaseModel,
200
+ include: MappingIntStrAny | None,
201
+ exclude: MappingIntStrAny | None,
202
+ exclude_unset: bool,
203
+ update: dict[str, Any] | None = None, # noqa UP006
204
+ ) -> typing.AbstractSet[str] | None:
205
+ if include is None and exclude is None and exclude_unset is False:
206
+ return None
207
+
208
+ keys: typing.AbstractSet[str]
209
+ if exclude_unset:
210
+ keys = self.__pydantic_fields_set__.copy()
211
+ else:
212
+ keys = set(self.__dict__.keys())
213
+ keys = keys | (self.__pydantic_extra__ or {}).keys()
214
+
215
+ if include is not None:
216
+ keys &= include.keys()
217
+
218
+ if update:
219
+ keys -= update.keys()
220
+
221
+ if exclude:
222
+ keys -= {k for k, v in exclude.items() if _utils.ValueItems.is_true(v)}
223
+
224
+ return keys
.mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/decorator.py ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import warnings
2
+ from collections.abc import Mapping
3
+ from functools import wraps
4
+ from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, overload
5
+
6
+ from typing_extensions import deprecated
7
+
8
+ from .._internal import _config, _typing_extra
9
+ from ..alias_generators import to_pascal
10
+ from ..errors import PydanticUserError
11
+ from ..functional_validators import field_validator
12
+ from ..main import BaseModel, create_model
13
+ from ..warnings import PydanticDeprecatedSince20
14
+
15
+ if not TYPE_CHECKING:
16
+ # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
17
+ # and https://youtrack.jetbrains.com/issue/PY-51428
18
+ DeprecationWarning = PydanticDeprecatedSince20
19
+
20
+ __all__ = ('validate_arguments',)
21
+
22
+ if TYPE_CHECKING:
23
+ AnyCallable = Callable[..., Any]
24
+
25
+ AnyCallableT = TypeVar('AnyCallableT', bound=AnyCallable)
26
+ ConfigType = Union[None, type[Any], dict[str, Any]]
27
+
28
+
29
+ @overload
30
+ def validate_arguments(
31
+ func: None = None, *, config: 'ConfigType' = None
32
+ ) -> Callable[['AnyCallableT'], 'AnyCallableT']: ...
33
+
34
+
35
+ @overload
36
+ def validate_arguments(func: 'AnyCallableT') -> 'AnyCallableT': ...
37
+
38
+
39
+ @deprecated(
40
+ 'The `validate_arguments` method is deprecated; use `validate_call` instead.',
41
+ category=None,
42
+ )
43
+ def validate_arguments(func: Optional['AnyCallableT'] = None, *, config: 'ConfigType' = None) -> Any:
44
+ """Decorator to validate the arguments passed to a function."""
45
+ warnings.warn(
46
+ 'The `validate_arguments` method is deprecated; use `validate_call` instead.',
47
+ PydanticDeprecatedSince20,
48
+ stacklevel=2,
49
+ )
50
+
51
+ def validate(_func: 'AnyCallable') -> 'AnyCallable':
52
+ vd = ValidatedFunction(_func, config)
53
+
54
+ @wraps(_func)
55
+ def wrapper_function(*args: Any, **kwargs: Any) -> Any:
56
+ return vd.call(*args, **kwargs)
57
+
58
+ wrapper_function.vd = vd # type: ignore
59
+ wrapper_function.validate = vd.init_model_instance # type: ignore
60
+ wrapper_function.raw_function = vd.raw_function # type: ignore
61
+ wrapper_function.model = vd.model # type: ignore
62
+ return wrapper_function
63
+
64
+ if func:
65
+ return validate(func)
66
+ else:
67
+ return validate
68
+
69
+
70
+ ALT_V_ARGS = 'v__args'
71
+ ALT_V_KWARGS = 'v__kwargs'
72
+ V_POSITIONAL_ONLY_NAME = 'v__positional_only'
73
+ V_DUPLICATE_KWARGS = 'v__duplicate_kwargs'
74
+
75
+
76
+ class ValidatedFunction:
77
+ def __init__(self, function: 'AnyCallable', config: 'ConfigType'):
78
+ from inspect import Parameter, signature
79
+
80
+ parameters: Mapping[str, Parameter] = signature(function).parameters
81
+
82
+ if parameters.keys() & {ALT_V_ARGS, ALT_V_KWARGS, V_POSITIONAL_ONLY_NAME, V_DUPLICATE_KWARGS}:
83
+ raise PydanticUserError(
84
+ f'"{ALT_V_ARGS}", "{ALT_V_KWARGS}", "{V_POSITIONAL_ONLY_NAME}" and "{V_DUPLICATE_KWARGS}" '
85
+ f'are not permitted as argument names when using the "{validate_arguments.__name__}" decorator',
86
+ code=None,
87
+ )
88
+
89
+ self.raw_function = function
90
+ self.arg_mapping: dict[int, str] = {}
91
+ self.positional_only_args: set[str] = set()
92
+ self.v_args_name = 'args'
93
+ self.v_kwargs_name = 'kwargs'
94
+
95
+ type_hints = _typing_extra.get_type_hints(function, include_extras=True)
96
+ takes_args = False
97
+ takes_kwargs = False
98
+ fields: dict[str, tuple[Any, Any]] = {}
99
+ for i, (name, p) in enumerate(parameters.items()):
100
+ if p.annotation is p.empty:
101
+ annotation = Any
102
+ else:
103
+ annotation = type_hints[name]
104
+
105
+ default = ... if p.default is p.empty else p.default
106
+ if p.kind == Parameter.POSITIONAL_ONLY:
107
+ self.arg_mapping[i] = name
108
+ fields[name] = annotation, default
109
+ fields[V_POSITIONAL_ONLY_NAME] = list[str], None
110
+ self.positional_only_args.add(name)
111
+ elif p.kind == Parameter.POSITIONAL_OR_KEYWORD:
112
+ self.arg_mapping[i] = name
113
+ fields[name] = annotation, default
114
+ fields[V_DUPLICATE_KWARGS] = list[str], None
115
+ elif p.kind == Parameter.KEYWORD_ONLY:
116
+ fields[name] = annotation, default
117
+ elif p.kind == Parameter.VAR_POSITIONAL:
118
+ self.v_args_name = name
119
+ fields[name] = tuple[annotation, ...], None
120
+ takes_args = True
121
+ else:
122
+ assert p.kind == Parameter.VAR_KEYWORD, p.kind
123
+ self.v_kwargs_name = name
124
+ fields[name] = dict[str, annotation], None
125
+ takes_kwargs = True
126
+
127
+ # these checks avoid a clash between "args" and a field with that name
128
+ if not takes_args and self.v_args_name in fields:
129
+ self.v_args_name = ALT_V_ARGS
130
+
131
+ # same with "kwargs"
132
+ if not takes_kwargs and self.v_kwargs_name in fields:
133
+ self.v_kwargs_name = ALT_V_KWARGS
134
+
135
+ if not takes_args:
136
+ # we add the field so validation below can raise the correct exception
137
+ fields[self.v_args_name] = list[Any], None
138
+
139
+ if not takes_kwargs:
140
+ # same with kwargs
141
+ fields[self.v_kwargs_name] = dict[Any, Any], None
142
+
143
+ self.create_model(fields, takes_args, takes_kwargs, config)
144
+
145
+ def init_model_instance(self, *args: Any, **kwargs: Any) -> BaseModel:
146
+ values = self.build_values(args, kwargs)
147
+ return self.model(**values)
148
+
149
+ def call(self, *args: Any, **kwargs: Any) -> Any:
150
+ m = self.init_model_instance(*args, **kwargs)
151
+ return self.execute(m)
152
+
153
+ def build_values(self, args: tuple[Any, ...], kwargs: dict[str, Any]) -> dict[str, Any]:
154
+ values: dict[str, Any] = {}
155
+ if args:
156
+ arg_iter = enumerate(args)
157
+ while True:
158
+ try:
159
+ i, a = next(arg_iter)
160
+ except StopIteration:
161
+ break
162
+ arg_name = self.arg_mapping.get(i)
163
+ if arg_name is not None:
164
+ values[arg_name] = a
165
+ else:
166
+ values[self.v_args_name] = [a] + [a for _, a in arg_iter]
167
+ break
168
+
169
+ var_kwargs: dict[str, Any] = {}
170
+ wrong_positional_args = []
171
+ duplicate_kwargs = []
172
+ fields_alias = [
173
+ field.alias
174
+ for name, field in self.model.__pydantic_fields__.items()
175
+ if name not in (self.v_args_name, self.v_kwargs_name)
176
+ ]
177
+ non_var_fields = set(self.model.__pydantic_fields__) - {self.v_args_name, self.v_kwargs_name}
178
+ for k, v in kwargs.items():
179
+ if k in non_var_fields or k in fields_alias:
180
+ if k in self.positional_only_args:
181
+ wrong_positional_args.append(k)
182
+ if k in values:
183
+ duplicate_kwargs.append(k)
184
+ values[k] = v
185
+ else:
186
+ var_kwargs[k] = v
187
+
188
+ if var_kwargs:
189
+ values[self.v_kwargs_name] = var_kwargs
190
+ if wrong_positional_args:
191
+ values[V_POSITIONAL_ONLY_NAME] = wrong_positional_args
192
+ if duplicate_kwargs:
193
+ values[V_DUPLICATE_KWARGS] = duplicate_kwargs
194
+ return values
195
+
196
+ def execute(self, m: BaseModel) -> Any:
197
+ d = {
198
+ k: v
199
+ for k, v in m.__dict__.items()
200
+ if k in m.__pydantic_fields_set__ or m.__pydantic_fields__[k].default_factory
201
+ }
202
+ var_kwargs = d.pop(self.v_kwargs_name, {})
203
+
204
+ if self.v_args_name in d:
205
+ args_: list[Any] = []
206
+ in_kwargs = False
207
+ kwargs = {}
208
+ for name, value in d.items():
209
+ if in_kwargs:
210
+ kwargs[name] = value
211
+ elif name == self.v_args_name:
212
+ args_ += value
213
+ in_kwargs = True
214
+ else:
215
+ args_.append(value)
216
+ return self.raw_function(*args_, **kwargs, **var_kwargs)
217
+ elif self.positional_only_args:
218
+ args_ = []
219
+ kwargs = {}
220
+ for name, value in d.items():
221
+ if name in self.positional_only_args:
222
+ args_.append(value)
223
+ else:
224
+ kwargs[name] = value
225
+ return self.raw_function(*args_, **kwargs, **var_kwargs)
226
+ else:
227
+ return self.raw_function(**d, **var_kwargs)
228
+
229
+ def create_model(self, fields: dict[str, Any], takes_args: bool, takes_kwargs: bool, config: 'ConfigType') -> None:
230
+ pos_args = len(self.arg_mapping)
231
+
232
+ config_wrapper = _config.ConfigWrapper(config)
233
+
234
+ if config_wrapper.alias_generator:
235
+ raise PydanticUserError(
236
+ 'Setting the "alias_generator" property on custom Config for '
237
+ '@validate_arguments is not yet supported, please remove.',
238
+ code=None,
239
+ )
240
+ if config_wrapper.extra is None:
241
+ config_wrapper.config_dict['extra'] = 'forbid'
242
+
243
+ class DecoratorBaseModel(BaseModel):
244
+ @field_validator(self.v_args_name, check_fields=False)
245
+ @classmethod
246
+ def check_args(cls, v: Optional[list[Any]]) -> Optional[list[Any]]:
247
+ if takes_args or v is None:
248
+ return v
249
+
250
+ raise TypeError(f'{pos_args} positional arguments expected but {pos_args + len(v)} given')
251
+
252
+ @field_validator(self.v_kwargs_name, check_fields=False)
253
+ @classmethod
254
+ def check_kwargs(cls, v: Optional[dict[str, Any]]) -> Optional[dict[str, Any]]:
255
+ if takes_kwargs or v is None:
256
+ return v
257
+
258
+ plural = '' if len(v) == 1 else 's'
259
+ keys = ', '.join(map(repr, v.keys()))
260
+ raise TypeError(f'unexpected keyword argument{plural}: {keys}')
261
+
262
+ @field_validator(V_POSITIONAL_ONLY_NAME, check_fields=False)
263
+ @classmethod
264
+ def check_positional_only(cls, v: Optional[list[str]]) -> None:
265
+ if v is None:
266
+ return
267
+
268
+ plural = '' if len(v) == 1 else 's'
269
+ keys = ', '.join(map(repr, v))
270
+ raise TypeError(f'positional-only argument{plural} passed as keyword argument{plural}: {keys}')
271
+
272
+ @field_validator(V_DUPLICATE_KWARGS, check_fields=False)
273
+ @classmethod
274
+ def check_duplicate_kwargs(cls, v: Optional[list[str]]) -> None:
275
+ if v is None:
276
+ return
277
+
278
+ plural = '' if len(v) == 1 else 's'
279
+ keys = ', '.join(map(repr, v))
280
+ raise TypeError(f'multiple values for argument{plural}: {keys}')
281
+
282
+ model_config = config_wrapper.config_dict
283
+
284
+ self.model = create_model(to_pascal(self.raw_function.__name__), __base__=DecoratorBaseModel, **fields)
.mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/json.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ import warnings
3
+ from collections import deque
4
+ from decimal import Decimal
5
+ from enum import Enum
6
+ from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network
7
+ from pathlib import Path
8
+ from re import Pattern
9
+ from types import GeneratorType
10
+ from typing import TYPE_CHECKING, Any, Callable, Union
11
+ from uuid import UUID
12
+
13
+ from typing_extensions import deprecated
14
+
15
+ from .._internal._import_utils import import_cached_base_model
16
+ from ..color import Color
17
+ from ..networks import NameEmail
18
+ from ..types import SecretBytes, SecretStr
19
+ from ..warnings import PydanticDeprecatedSince20
20
+
21
+ if not TYPE_CHECKING:
22
+ # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
23
+ # and https://youtrack.jetbrains.com/issue/PY-51428
24
+ DeprecationWarning = PydanticDeprecatedSince20
25
+
26
+ __all__ = 'pydantic_encoder', 'custom_pydantic_encoder', 'timedelta_isoformat'
27
+
28
+
29
+ def isoformat(o: Union[datetime.date, datetime.time]) -> str:
30
+ return o.isoformat()
31
+
32
+
33
+ def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
34
+ """Encodes a Decimal as int of there's no exponent, otherwise float.
35
+
36
+ This is useful when we use ConstrainedDecimal to represent Numeric(x,0)
37
+ where a integer (but not int typed) is used. Encoding this as a float
38
+ results in failed round-tripping between encode and parse.
39
+ Our Id type is a prime example of this.
40
+
41
+ >>> decimal_encoder(Decimal("1.0"))
42
+ 1.0
43
+
44
+ >>> decimal_encoder(Decimal("1"))
45
+ 1
46
+ """
47
+ exponent = dec_value.as_tuple().exponent
48
+ if isinstance(exponent, int) and exponent >= 0:
49
+ return int(dec_value)
50
+ else:
51
+ return float(dec_value)
52
+
53
+
54
+ ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = {
55
+ bytes: lambda o: o.decode(),
56
+ Color: str,
57
+ datetime.date: isoformat,
58
+ datetime.datetime: isoformat,
59
+ datetime.time: isoformat,
60
+ datetime.timedelta: lambda td: td.total_seconds(),
61
+ Decimal: decimal_encoder,
62
+ Enum: lambda o: o.value,
63
+ frozenset: list,
64
+ deque: list,
65
+ GeneratorType: list,
66
+ IPv4Address: str,
67
+ IPv4Interface: str,
68
+ IPv4Network: str,
69
+ IPv6Address: str,
70
+ IPv6Interface: str,
71
+ IPv6Network: str,
72
+ NameEmail: str,
73
+ Path: str,
74
+ Pattern: lambda o: o.pattern,
75
+ SecretBytes: str,
76
+ SecretStr: str,
77
+ set: list,
78
+ UUID: str,
79
+ }
80
+
81
+
82
+ @deprecated(
83
+ '`pydantic_encoder` is deprecated, use `pydantic_core.to_jsonable_python` instead.',
84
+ category=None,
85
+ )
86
+ def pydantic_encoder(obj: Any) -> Any:
87
+ warnings.warn(
88
+ '`pydantic_encoder` is deprecated, use `pydantic_core.to_jsonable_python` instead.',
89
+ category=PydanticDeprecatedSince20,
90
+ stacklevel=2,
91
+ )
92
+ from dataclasses import asdict, is_dataclass
93
+
94
+ BaseModel = import_cached_base_model()
95
+
96
+ if isinstance(obj, BaseModel):
97
+ return obj.model_dump()
98
+ elif is_dataclass(obj):
99
+ return asdict(obj) # type: ignore
100
+
101
+ # Check the class type and its superclasses for a matching encoder
102
+ for base in obj.__class__.__mro__[:-1]:
103
+ try:
104
+ encoder = ENCODERS_BY_TYPE[base]
105
+ except KeyError:
106
+ continue
107
+ return encoder(obj)
108
+ else: # We have exited the for loop without finding a suitable encoder
109
+ raise TypeError(f"Object of type '{obj.__class__.__name__}' is not JSON serializable")
110
+
111
+
112
+ # TODO: Add a suggested migration path once there is a way to use custom encoders
113
+ @deprecated(
114
+ '`custom_pydantic_encoder` is deprecated, use `BaseModel.model_dump` instead.',
115
+ category=None,
116
+ )
117
+ def custom_pydantic_encoder(type_encoders: dict[Any, Callable[[type[Any]], Any]], obj: Any) -> Any:
118
+ warnings.warn(
119
+ '`custom_pydantic_encoder` is deprecated, use `BaseModel.model_dump` instead.',
120
+ category=PydanticDeprecatedSince20,
121
+ stacklevel=2,
122
+ )
123
+ # Check the class type and its superclasses for a matching encoder
124
+ for base in obj.__class__.__mro__[:-1]:
125
+ try:
126
+ encoder = type_encoders[base]
127
+ except KeyError:
128
+ continue
129
+
130
+ return encoder(obj)
131
+ else: # We have exited the for loop without finding a suitable encoder
132
+ return pydantic_encoder(obj)
133
+
134
+
135
+ @deprecated('`timedelta_isoformat` is deprecated.', category=None)
136
+ def timedelta_isoformat(td: datetime.timedelta) -> str:
137
+ """ISO 8601 encoding for Python timedelta object."""
138
+ warnings.warn('`timedelta_isoformat` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2)
139
+ minutes, seconds = divmod(td.seconds, 60)
140
+ hours, minutes = divmod(minutes, 60)
141
+ return f'{"-" if td.days < 0 else ""}P{abs(td.days)}DT{hours:d}H{minutes:d}M{seconds:d}.{td.microseconds:06d}S'
.mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/parse.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import pickle
5
+ import warnings
6
+ from enum import Enum
7
+ from pathlib import Path
8
+ from typing import TYPE_CHECKING, Any, Callable
9
+
10
+ from typing_extensions import deprecated
11
+
12
+ from ..warnings import PydanticDeprecatedSince20
13
+
14
+ if not TYPE_CHECKING:
15
+ # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
16
+ # and https://youtrack.jetbrains.com/issue/PY-51428
17
+ DeprecationWarning = PydanticDeprecatedSince20
18
+
19
+
20
+ class Protocol(str, Enum):
21
+ json = 'json'
22
+ pickle = 'pickle'
23
+
24
+
25
+ @deprecated('`load_str_bytes` is deprecated.', category=None)
26
+ def load_str_bytes(
27
+ b: str | bytes,
28
+ *,
29
+ content_type: str | None = None,
30
+ encoding: str = 'utf8',
31
+ proto: Protocol | None = None,
32
+ allow_pickle: bool = False,
33
+ json_loads: Callable[[str], Any] = json.loads,
34
+ ) -> Any:
35
+ warnings.warn('`load_str_bytes` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2)
36
+ if proto is None and content_type:
37
+ if content_type.endswith(('json', 'javascript')):
38
+ pass
39
+ elif allow_pickle and content_type.endswith('pickle'):
40
+ proto = Protocol.pickle
41
+ else:
42
+ raise TypeError(f'Unknown content-type: {content_type}')
43
+
44
+ proto = proto or Protocol.json
45
+
46
+ if proto == Protocol.json:
47
+ if isinstance(b, bytes):
48
+ b = b.decode(encoding)
49
+ return json_loads(b) # type: ignore
50
+ elif proto == Protocol.pickle:
51
+ if not allow_pickle:
52
+ raise RuntimeError('Trying to decode with pickle with allow_pickle=False')
53
+ bb = b if isinstance(b, bytes) else b.encode() # type: ignore
54
+ return pickle.loads(bb)
55
+ else:
56
+ raise TypeError(f'Unknown protocol: {proto}')
57
+
58
+
59
+ @deprecated('`load_file` is deprecated.', category=None)
60
+ def load_file(
61
+ path: str | Path,
62
+ *,
63
+ content_type: str | None = None,
64
+ encoding: str = 'utf8',
65
+ proto: Protocol | None = None,
66
+ allow_pickle: bool = False,
67
+ json_loads: Callable[[str], Any] = json.loads,
68
+ ) -> Any:
69
+ warnings.warn('`load_file` is deprecated.', category=PydanticDeprecatedSince20, stacklevel=2)
70
+ path = Path(path)
71
+ b = path.read_bytes()
72
+ if content_type is None:
73
+ if path.suffix in ('.js', '.json'):
74
+ proto = Protocol.json
75
+ elif path.suffix == '.pkl':
76
+ proto = Protocol.pickle
77
+
78
+ return load_str_bytes(
79
+ b, proto=proto, content_type=content_type, encoding=encoding, allow_pickle=allow_pickle, json_loads=json_loads
80
+ )
.mcp-venv/lib/python3.13/site-packages/pydantic/deprecated/tools.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import warnings
5
+ from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union
6
+
7
+ from typing_extensions import deprecated
8
+
9
+ from ..json_schema import DEFAULT_REF_TEMPLATE, GenerateJsonSchema
10
+ from ..type_adapter import TypeAdapter
11
+ from ..warnings import PydanticDeprecatedSince20
12
+
13
+ if not TYPE_CHECKING:
14
+ # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
15
+ # and https://youtrack.jetbrains.com/issue/PY-51428
16
+ DeprecationWarning = PydanticDeprecatedSince20
17
+
18
+ __all__ = 'parse_obj_as', 'schema_of', 'schema_json_of'
19
+
20
+ NameFactory = Union[str, Callable[[type[Any]], str]]
21
+
22
+
23
+ T = TypeVar('T')
24
+
25
+
26
+ @deprecated(
27
+ '`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.',
28
+ category=None,
29
+ )
30
+ def parse_obj_as(type_: type[T], obj: Any, type_name: NameFactory | None = None) -> T:
31
+ warnings.warn(
32
+ '`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.',
33
+ category=PydanticDeprecatedSince20,
34
+ stacklevel=2,
35
+ )
36
+ if type_name is not None: # pragma: no cover
37
+ warnings.warn(
38
+ 'The type_name parameter is deprecated. parse_obj_as no longer creates temporary models',
39
+ DeprecationWarning,
40
+ stacklevel=2,
41
+ )
42
+ return TypeAdapter(type_).validate_python(obj)
43
+
44
+
45
+ @deprecated(
46
+ '`schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
47
+ category=None,
48
+ )
49
+ def schema_of(
50
+ type_: Any,
51
+ *,
52
+ title: NameFactory | None = None,
53
+ by_alias: bool = True,
54
+ ref_template: str = DEFAULT_REF_TEMPLATE,
55
+ schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema,
56
+ ) -> dict[str, Any]:
57
+ """Generate a JSON schema (as dict) for the passed model or dynamically generated one."""
58
+ warnings.warn(
59
+ '`schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
60
+ category=PydanticDeprecatedSince20,
61
+ stacklevel=2,
62
+ )
63
+ res = TypeAdapter(type_).json_schema(
64
+ by_alias=by_alias,
65
+ schema_generator=schema_generator,
66
+ ref_template=ref_template,
67
+ )
68
+ if title is not None:
69
+ if isinstance(title, str):
70
+ res['title'] = title
71
+ else:
72
+ warnings.warn(
73
+ 'Passing a callable for the `title` parameter is deprecated and no longer supported',
74
+ DeprecationWarning,
75
+ stacklevel=2,
76
+ )
77
+ res['title'] = title(type_)
78
+ return res
79
+
80
+
81
+ @deprecated(
82
+ '`schema_json_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
83
+ category=None,
84
+ )
85
+ def schema_json_of(
86
+ type_: Any,
87
+ *,
88
+ title: NameFactory | None = None,
89
+ by_alias: bool = True,
90
+ ref_template: str = DEFAULT_REF_TEMPLATE,
91
+ schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema,
92
+ **dumps_kwargs: Any,
93
+ ) -> str:
94
+ """Generate a JSON schema (as JSON) for the passed model or dynamically generated one."""
95
+ warnings.warn(
96
+ '`schema_json_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
97
+ category=PydanticDeprecatedSince20,
98
+ stacklevel=2,
99
+ )
100
+ return json.dumps(
101
+ schema_of(type_, title=title, by_alias=by_alias, ref_template=ref_template, schema_generator=schema_generator),
102
+ **dumps_kwargs,
103
+ )
.mcp-venv/lib/python3.13/site-packages/pydantic/env_settings.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """The `env_settings` module is a backport module from V1."""
2
+
3
+ from ._migration import getattr_migration
4
+
5
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/error_wrappers.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """The `error_wrappers` module is a backport module from V1."""
2
+
3
+ from ._migration import getattr_migration
4
+
5
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/errors.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Pydantic-specific errors."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ import re
6
+ from typing import Any, ClassVar, Literal
7
+
8
+ from typing_extensions import Self
9
+ from typing_inspection.introspection import Qualifier
10
+
11
+ from pydantic._internal import _repr
12
+
13
+ from ._migration import getattr_migration
14
+ from .version import version_short
15
+
16
+ __all__ = (
17
+ 'PydanticUserError',
18
+ 'PydanticUndefinedAnnotation',
19
+ 'PydanticImportError',
20
+ 'PydanticSchemaGenerationError',
21
+ 'PydanticInvalidForJsonSchema',
22
+ 'PydanticForbiddenQualifier',
23
+ 'PydanticErrorCodes',
24
+ )
25
+
26
+ # We use this URL to allow for future flexibility about how we host the docs, while allowing for Pydantic
27
+ # code in the while with "old" URLs to still work.
28
+ # 'u' refers to "user errors" - e.g. errors caused by developers using pydantic, as opposed to validation errors.
29
+ DEV_ERROR_DOCS_URL = f'https://errors.pydantic.dev/{version_short()}/u/'
30
+ PydanticErrorCodes = Literal[
31
+ 'class-not-fully-defined',
32
+ 'custom-json-schema',
33
+ 'decorator-invalid-fields',
34
+ 'decorator-missing-arguments',
35
+ 'decorator-missing-field',
36
+ 'discriminator-no-field',
37
+ 'discriminator-alias-type',
38
+ 'discriminator-needs-literal',
39
+ 'discriminator-alias',
40
+ 'discriminator-validator',
41
+ 'callable-discriminator-no-tag',
42
+ 'typed-dict-version',
43
+ 'model-field-overridden',
44
+ 'model-field-missing-annotation',
45
+ 'config-both',
46
+ 'removed-kwargs',
47
+ 'circular-reference-schema',
48
+ 'invalid-for-json-schema',
49
+ 'json-schema-already-used',
50
+ 'base-model-instantiated',
51
+ 'undefined-annotation',
52
+ 'schema-for-unknown-type',
53
+ 'import-error',
54
+ 'create-model-field-definitions',
55
+ 'validator-instance-method',
56
+ 'validator-input-type',
57
+ 'root-validator-pre-skip',
58
+ 'model-serializer-instance-method',
59
+ 'validator-field-config-info',
60
+ 'validator-v1-signature',
61
+ 'validator-signature',
62
+ 'field-serializer-signature',
63
+ 'model-serializer-signature',
64
+ 'multiple-field-serializers',
65
+ 'invalid-annotated-type',
66
+ 'type-adapter-config-unused',
67
+ 'root-model-extra',
68
+ 'unevaluable-type-annotation',
69
+ 'dataclass-init-false-extra-allow',
70
+ 'clashing-init-and-init-var',
71
+ 'model-config-invalid-field-name',
72
+ 'with-config-on-model',
73
+ 'dataclass-on-model',
74
+ 'validate-call-type',
75
+ 'unpack-typed-dict',
76
+ 'overlapping-unpack-typed-dict',
77
+ 'invalid-self-type',
78
+ 'validate-by-alias-and-name-false',
79
+ ]
80
+
81
+
82
+ class PydanticErrorMixin:
83
+ """A mixin class for common functionality shared by all Pydantic-specific errors.
84
+
85
+ Attributes:
86
+ message: A message describing the error.
87
+ code: An optional error code from PydanticErrorCodes enum.
88
+ """
89
+
90
+ def __init__(self, message: str, *, code: PydanticErrorCodes | None) -> None:
91
+ self.message = message
92
+ self.code = code
93
+
94
+ def __str__(self) -> str:
95
+ if self.code is None:
96
+ return self.message
97
+ else:
98
+ return f'{self.message}\n\nFor further information visit {DEV_ERROR_DOCS_URL}{self.code}'
99
+
100
+
101
+ class PydanticUserError(PydanticErrorMixin, RuntimeError):
102
+ """An error raised due to incorrect use of Pydantic."""
103
+
104
+
105
+ class PydanticUndefinedAnnotation(PydanticErrorMixin, NameError):
106
+ """A subclass of `NameError` raised when handling undefined annotations during `CoreSchema` generation.
107
+
108
+ Attributes:
109
+ name: Name of the error.
110
+ message: Description of the error.
111
+ """
112
+
113
+ def __init__(self, name: str, message: str) -> None:
114
+ self.name = name
115
+ super().__init__(message=message, code='undefined-annotation')
116
+
117
+ @classmethod
118
+ def from_name_error(cls, name_error: NameError) -> Self:
119
+ """Convert a `NameError` to a `PydanticUndefinedAnnotation` error.
120
+
121
+ Args:
122
+ name_error: `NameError` to be converted.
123
+
124
+ Returns:
125
+ Converted `PydanticUndefinedAnnotation` error.
126
+ """
127
+ try:
128
+ name = name_error.name # type: ignore # python > 3.10
129
+ except AttributeError:
130
+ name = re.search(r".*'(.+?)'", str(name_error)).group(1) # type: ignore[union-attr]
131
+ return cls(name=name, message=str(name_error))
132
+
133
+
134
+ class PydanticImportError(PydanticErrorMixin, ImportError):
135
+ """An error raised when an import fails due to module changes between V1 and V2.
136
+
137
+ Attributes:
138
+ message: Description of the error.
139
+ """
140
+
141
+ def __init__(self, message: str) -> None:
142
+ super().__init__(message, code='import-error')
143
+
144
+
145
+ class PydanticSchemaGenerationError(PydanticUserError):
146
+ """An error raised during failures to generate a `CoreSchema` for some type.
147
+
148
+ Attributes:
149
+ message: Description of the error.
150
+ """
151
+
152
+ def __init__(self, message: str) -> None:
153
+ super().__init__(message, code='schema-for-unknown-type')
154
+
155
+
156
+ class PydanticInvalidForJsonSchema(PydanticUserError):
157
+ """An error raised during failures to generate a JSON schema for some `CoreSchema`.
158
+
159
+ Attributes:
160
+ message: Description of the error.
161
+ """
162
+
163
+ def __init__(self, message: str) -> None:
164
+ super().__init__(message, code='invalid-for-json-schema')
165
+
166
+
167
+ class PydanticForbiddenQualifier(PydanticUserError):
168
+ """An error raised if a forbidden type qualifier is found in a type annotation."""
169
+
170
+ _qualifier_repr_map: ClassVar[dict[Qualifier, str]] = {
171
+ 'required': 'typing.Required',
172
+ 'not_required': 'typing.NotRequired',
173
+ 'read_only': 'typing.ReadOnly',
174
+ 'class_var': 'typing.ClassVar',
175
+ 'init_var': 'dataclasses.InitVar',
176
+ 'final': 'typing.Final',
177
+ }
178
+
179
+ def __init__(self, qualifier: Qualifier, annotation: Any) -> None:
180
+ super().__init__(
181
+ message=(
182
+ f'The annotation {_repr.display_as_type(annotation)!r} contains the {self._qualifier_repr_map[qualifier]!r} '
183
+ f'type qualifier, which is invalid in the context it is defined.'
184
+ ),
185
+ code=None,
186
+ )
187
+
188
+
189
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/experimental/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """The "experimental" module of pydantic contains potential new features that are subject to change."""
.mcp-venv/lib/python3.13/site-packages/pydantic/experimental/arguments_schema.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Experimental module exposing a function to generate a core schema that validates callable arguments."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from typing import Any, Literal
7
+
8
+ from pydantic_core import CoreSchema
9
+
10
+ from pydantic import ConfigDict
11
+ from pydantic._internal import _config, _generate_schema, _namespace_utils
12
+
13
+
14
+ def generate_arguments_schema(
15
+ func: Callable[..., Any],
16
+ schema_type: Literal['arguments', 'arguments-v3'] = 'arguments-v3',
17
+ parameters_callback: Callable[[int, str, Any], Literal['skip'] | None] | None = None,
18
+ config: ConfigDict | None = None,
19
+ ) -> CoreSchema:
20
+ """Generate the schema for the arguments of a function.
21
+
22
+ Args:
23
+ func: The function to generate the schema for.
24
+ schema_type: The type of schema to generate.
25
+ parameters_callback: A callable that will be invoked for each parameter. The callback
26
+ should take three required arguments: the index, the name and the type annotation
27
+ (or [`Parameter.empty`][inspect.Parameter.empty] if not annotated) of the parameter.
28
+ The callback can optionally return `'skip'`, so that the parameter gets excluded
29
+ from the resulting schema.
30
+ config: The configuration to use.
31
+
32
+ Returns:
33
+ The generated schema.
34
+ """
35
+ generate_schema = _generate_schema.GenerateSchema(
36
+ _config.ConfigWrapper(config),
37
+ ns_resolver=_namespace_utils.NsResolver(namespaces_tuple=_namespace_utils.ns_for_function(func)),
38
+ )
39
+
40
+ if schema_type == 'arguments':
41
+ schema = generate_schema._arguments_schema(func, parameters_callback) # pyright: ignore[reportArgumentType]
42
+ else:
43
+ schema = generate_schema._arguments_v3_schema(func, parameters_callback) # pyright: ignore[reportArgumentType]
44
+ return generate_schema.clean_schema(schema)
.mcp-venv/lib/python3.13/site-packages/pydantic/experimental/missing_sentinel.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """Experimental module exposing a function a `MISSING` sentinel."""
2
+
3
+ from pydantic_core import MISSING
4
+
5
+ __all__ = ('MISSING',)
.mcp-venv/lib/python3.13/site-packages/pydantic/experimental/pipeline.py ADDED
@@ -0,0 +1,663 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Experimental pipeline API functionality. Be careful with this API, it's subject to change."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import datetime
6
+ import operator
7
+ import re
8
+ import sys
9
+ from collections import deque
10
+ from collections.abc import Container
11
+ from dataclasses import dataclass
12
+ from decimal import Decimal
13
+ from functools import cached_property, partial
14
+ from re import Pattern
15
+ from typing import TYPE_CHECKING, Annotated, Any, Callable, Generic, Protocol, TypeVar, Union, overload
16
+
17
+ import annotated_types
18
+
19
+ if TYPE_CHECKING:
20
+ from pydantic import GetCoreSchemaHandler
21
+
22
+ from pydantic_core import PydanticCustomError
23
+ from pydantic_core import core_schema as cs
24
+
25
+ from pydantic import Strict
26
+ from pydantic._internal._internal_dataclass import slots_true as _slots_true
27
+
28
+ if sys.version_info < (3, 10):
29
+ EllipsisType = type(Ellipsis)
30
+ else:
31
+ from types import EllipsisType
32
+
33
+ __all__ = ['validate_as', 'validate_as_deferred', 'transform']
34
+
35
+ _slots_frozen = {**_slots_true, 'frozen': True}
36
+
37
+
38
+ @dataclass(**_slots_frozen)
39
+ class _ValidateAs:
40
+ tp: type[Any]
41
+ strict: bool = False
42
+
43
+
44
+ @dataclass
45
+ class _ValidateAsDefer:
46
+ func: Callable[[], type[Any]]
47
+
48
+ @cached_property
49
+ def tp(self) -> type[Any]:
50
+ return self.func()
51
+
52
+
53
+ @dataclass(**_slots_frozen)
54
+ class _Transform:
55
+ func: Callable[[Any], Any]
56
+
57
+
58
+ @dataclass(**_slots_frozen)
59
+ class _PipelineOr:
60
+ left: _Pipeline[Any, Any]
61
+ right: _Pipeline[Any, Any]
62
+
63
+
64
+ @dataclass(**_slots_frozen)
65
+ class _PipelineAnd:
66
+ left: _Pipeline[Any, Any]
67
+ right: _Pipeline[Any, Any]
68
+
69
+
70
+ @dataclass(**_slots_frozen)
71
+ class _Eq:
72
+ value: Any
73
+
74
+
75
+ @dataclass(**_slots_frozen)
76
+ class _NotEq:
77
+ value: Any
78
+
79
+
80
+ @dataclass(**_slots_frozen)
81
+ class _In:
82
+ values: Container[Any]
83
+
84
+
85
+ @dataclass(**_slots_frozen)
86
+ class _NotIn:
87
+ values: Container[Any]
88
+
89
+
90
+ _ConstraintAnnotation = Union[
91
+ annotated_types.Le,
92
+ annotated_types.Ge,
93
+ annotated_types.Lt,
94
+ annotated_types.Gt,
95
+ annotated_types.Len,
96
+ annotated_types.MultipleOf,
97
+ annotated_types.Timezone,
98
+ annotated_types.Interval,
99
+ annotated_types.Predicate,
100
+ # common predicates not included in annotated_types
101
+ _Eq,
102
+ _NotEq,
103
+ _In,
104
+ _NotIn,
105
+ # regular expressions
106
+ Pattern[str],
107
+ ]
108
+
109
+
110
+ @dataclass(**_slots_frozen)
111
+ class _Constraint:
112
+ constraint: _ConstraintAnnotation
113
+
114
+
115
+ _Step = Union[_ValidateAs, _ValidateAsDefer, _Transform, _PipelineOr, _PipelineAnd, _Constraint]
116
+
117
+ _InT = TypeVar('_InT')
118
+ _OutT = TypeVar('_OutT')
119
+ _NewOutT = TypeVar('_NewOutT')
120
+
121
+
122
+ class _FieldTypeMarker:
123
+ pass
124
+
125
+
126
+ # TODO: ultimately, make this public, see https://github.com/pydantic/pydantic/pull/9459#discussion_r1628197626
127
+ # Also, make this frozen eventually, but that doesn't work right now because of the generic base
128
+ # Which attempts to modify __orig_base__ and such.
129
+ # We could go with a manual freeze, but that seems overkill for now.
130
+ @dataclass(**_slots_true)
131
+ class _Pipeline(Generic[_InT, _OutT]):
132
+ """Abstract representation of a chain of validation, transformation, and parsing steps."""
133
+
134
+ _steps: tuple[_Step, ...]
135
+
136
+ def transform(
137
+ self,
138
+ func: Callable[[_OutT], _NewOutT],
139
+ ) -> _Pipeline[_InT, _NewOutT]:
140
+ """Transform the output of the previous step.
141
+
142
+ If used as the first step in a pipeline, the type of the field is used.
143
+ That is, the transformation is applied to after the value is parsed to the field's type.
144
+ """
145
+ return _Pipeline[_InT, _NewOutT](self._steps + (_Transform(func),))
146
+
147
+ @overload
148
+ def validate_as(self, tp: type[_NewOutT], *, strict: bool = False) -> _Pipeline[_InT, _NewOutT]: ...
149
+
150
+ @overload
151
+ def validate_as(
152
+ self,
153
+ tp: ellipsis, # noqa: F821 # TODO: use `_typing_extra.EllipsisType` when we drop Py3.9
154
+ *,
155
+ strict: bool = False,
156
+ ) -> _Pipeline[_InT, Any]: ...
157
+
158
+ # TODO PEP 747: use TypeForm to properly type Annotated aliases (e.g. NewPath, FilePath).
159
+ # This fallback accepts any type expression but loses generic type inference.
160
+ @overload
161
+ def validate_as(self, tp: Any, *, strict: bool = ...) -> _Pipeline[_InT, Any]: ...
162
+
163
+ def validate_as(self, tp: type[_NewOutT] | EllipsisType | Any, *, strict: bool = False) -> _Pipeline[_InT, Any]: # type: ignore
164
+ """Validate / parse the input into a new type.
165
+
166
+ If no type is provided, the type of the field is used.
167
+
168
+ Types are parsed in Pydantic's `lax` mode by default,
169
+ but you can enable `strict` mode by passing `strict=True`.
170
+ """
171
+ if isinstance(tp, EllipsisType):
172
+ return _Pipeline[_InT, Any](self._steps + (_ValidateAs(_FieldTypeMarker, strict=strict),))
173
+ return _Pipeline[_InT, _NewOutT](self._steps + (_ValidateAs(tp, strict=strict),))
174
+
175
+ def validate_as_deferred(self, func: Callable[[], type[_NewOutT]]) -> _Pipeline[_InT, _NewOutT]:
176
+ """Parse the input into a new type, deferring resolution of the type until the current class
177
+ is fully defined.
178
+
179
+ This is useful when you need to reference the class in it's own type annotations.
180
+ """
181
+ return _Pipeline[_InT, _NewOutT](self._steps + (_ValidateAsDefer(func),))
182
+
183
+ # constraints
184
+ @overload
185
+ def constrain(self: _Pipeline[_InT, _NewOutGe], constraint: annotated_types.Ge) -> _Pipeline[_InT, _NewOutGe]: ...
186
+
187
+ @overload
188
+ def constrain(self: _Pipeline[_InT, _NewOutGt], constraint: annotated_types.Gt) -> _Pipeline[_InT, _NewOutGt]: ...
189
+
190
+ @overload
191
+ def constrain(self: _Pipeline[_InT, _NewOutLe], constraint: annotated_types.Le) -> _Pipeline[_InT, _NewOutLe]: ...
192
+
193
+ @overload
194
+ def constrain(self: _Pipeline[_InT, _NewOutLt], constraint: annotated_types.Lt) -> _Pipeline[_InT, _NewOutLt]: ...
195
+
196
+ @overload
197
+ def constrain(
198
+ self: _Pipeline[_InT, _NewOutLen], constraint: annotated_types.Len
199
+ ) -> _Pipeline[_InT, _NewOutLen]: ...
200
+
201
+ @overload
202
+ def constrain(
203
+ self: _Pipeline[_InT, _NewOutT], constraint: annotated_types.MultipleOf
204
+ ) -> _Pipeline[_InT, _NewOutT]: ...
205
+
206
+ @overload
207
+ def constrain(
208
+ self: _Pipeline[_InT, _NewOutDatetime], constraint: annotated_types.Timezone
209
+ ) -> _Pipeline[_InT, _NewOutDatetime]: ...
210
+
211
+ @overload
212
+ def constrain(self: _Pipeline[_InT, _OutT], constraint: annotated_types.Predicate) -> _Pipeline[_InT, _OutT]: ...
213
+
214
+ @overload
215
+ def constrain(
216
+ self: _Pipeline[_InT, _NewOutInterval], constraint: annotated_types.Interval
217
+ ) -> _Pipeline[_InT, _NewOutInterval]: ...
218
+
219
+ @overload
220
+ def constrain(self: _Pipeline[_InT, _OutT], constraint: _Eq) -> _Pipeline[_InT, _OutT]: ...
221
+
222
+ @overload
223
+ def constrain(self: _Pipeline[_InT, _OutT], constraint: _NotEq) -> _Pipeline[_InT, _OutT]: ...
224
+
225
+ @overload
226
+ def constrain(self: _Pipeline[_InT, _OutT], constraint: _In) -> _Pipeline[_InT, _OutT]: ...
227
+
228
+ @overload
229
+ def constrain(self: _Pipeline[_InT, _OutT], constraint: _NotIn) -> _Pipeline[_InT, _OutT]: ...
230
+
231
+ @overload
232
+ def constrain(self: _Pipeline[_InT, _NewOutT], constraint: Pattern[str]) -> _Pipeline[_InT, _NewOutT]: ...
233
+
234
+ def constrain(self, constraint: _ConstraintAnnotation) -> Any:
235
+ """Constrain a value to meet a certain condition.
236
+
237
+ We support most conditions from `annotated_types`, as well as regular expressions.
238
+
239
+ Most of the time you'll be calling a shortcut method like `gt`, `lt`, `len`, etc
240
+ so you don't need to call this directly.
241
+ """
242
+ return _Pipeline[_InT, _OutT](self._steps + (_Constraint(constraint),))
243
+
244
+ def predicate(self: _Pipeline[_InT, _NewOutT], func: Callable[[_NewOutT], bool]) -> _Pipeline[_InT, _NewOutT]:
245
+ """Constrain a value to meet a certain predicate."""
246
+ return self.constrain(annotated_types.Predicate(func))
247
+
248
+ def gt(self: _Pipeline[_InT, _NewOutGt], gt: _NewOutGt) -> _Pipeline[_InT, _NewOutGt]:
249
+ """Constrain a value to be greater than a certain value."""
250
+ return self.constrain(annotated_types.Gt(gt))
251
+
252
+ def lt(self: _Pipeline[_InT, _NewOutLt], lt: _NewOutLt) -> _Pipeline[_InT, _NewOutLt]:
253
+ """Constrain a value to be less than a certain value."""
254
+ return self.constrain(annotated_types.Lt(lt))
255
+
256
+ def ge(self: _Pipeline[_InT, _NewOutGe], ge: _NewOutGe) -> _Pipeline[_InT, _NewOutGe]:
257
+ """Constrain a value to be greater than or equal to a certain value."""
258
+ return self.constrain(annotated_types.Ge(ge))
259
+
260
+ def le(self: _Pipeline[_InT, _NewOutLe], le: _NewOutLe) -> _Pipeline[_InT, _NewOutLe]:
261
+ """Constrain a value to be less than or equal to a certain value."""
262
+ return self.constrain(annotated_types.Le(le))
263
+
264
+ def len(self: _Pipeline[_InT, _NewOutLen], min_len: int, max_len: int | None = None) -> _Pipeline[_InT, _NewOutLen]:
265
+ """Constrain a value to have a certain length."""
266
+ return self.constrain(annotated_types.Len(min_len, max_len))
267
+
268
+ @overload
269
+ def multiple_of(self: _Pipeline[_InT, _NewOutDiv], multiple_of: _NewOutDiv) -> _Pipeline[_InT, _NewOutDiv]: ...
270
+
271
+ @overload
272
+ def multiple_of(self: _Pipeline[_InT, _NewOutMod], multiple_of: _NewOutMod) -> _Pipeline[_InT, _NewOutMod]: ...
273
+
274
+ def multiple_of(self: _Pipeline[_InT, Any], multiple_of: Any) -> _Pipeline[_InT, Any]:
275
+ """Constrain a value to be a multiple of a certain number."""
276
+ return self.constrain(annotated_types.MultipleOf(multiple_of))
277
+
278
+ def eq(self: _Pipeline[_InT, _OutT], value: _OutT) -> _Pipeline[_InT, _OutT]:
279
+ """Constrain a value to be equal to a certain value."""
280
+ return self.constrain(_Eq(value))
281
+
282
+ def not_eq(self: _Pipeline[_InT, _OutT], value: _OutT) -> _Pipeline[_InT, _OutT]:
283
+ """Constrain a value to not be equal to a certain value."""
284
+ return self.constrain(_NotEq(value))
285
+
286
+ def in_(self: _Pipeline[_InT, _OutT], values: Container[_OutT]) -> _Pipeline[_InT, _OutT]:
287
+ """Constrain a value to be in a certain set."""
288
+ return self.constrain(_In(values))
289
+
290
+ def not_in(self: _Pipeline[_InT, _OutT], values: Container[_OutT]) -> _Pipeline[_InT, _OutT]:
291
+ """Constrain a value to not be in a certain set."""
292
+ return self.constrain(_NotIn(values))
293
+
294
+ # timezone methods
295
+ def datetime_tz_naive(self: _Pipeline[_InT, datetime.datetime]) -> _Pipeline[_InT, datetime.datetime]:
296
+ return self.constrain(annotated_types.Timezone(None))
297
+
298
+ def datetime_tz_aware(self: _Pipeline[_InT, datetime.datetime]) -> _Pipeline[_InT, datetime.datetime]:
299
+ return self.constrain(annotated_types.Timezone(...))
300
+
301
+ def datetime_tz(
302
+ self: _Pipeline[_InT, datetime.datetime], tz: datetime.tzinfo
303
+ ) -> _Pipeline[_InT, datetime.datetime]:
304
+ return self.constrain(annotated_types.Timezone(tz)) # type: ignore
305
+
306
+ def datetime_with_tz(
307
+ self: _Pipeline[_InT, datetime.datetime], tz: datetime.tzinfo | None
308
+ ) -> _Pipeline[_InT, datetime.datetime]:
309
+ return self.transform(partial(datetime.datetime.replace, tzinfo=tz))
310
+
311
+ # string methods
312
+ def str_lower(self: _Pipeline[_InT, str]) -> _Pipeline[_InT, str]:
313
+ return self.transform(str.lower)
314
+
315
+ def str_upper(self: _Pipeline[_InT, str]) -> _Pipeline[_InT, str]:
316
+ return self.transform(str.upper)
317
+
318
+ def str_title(self: _Pipeline[_InT, str]) -> _Pipeline[_InT, str]:
319
+ return self.transform(str.title)
320
+
321
+ def str_strip(self: _Pipeline[_InT, str]) -> _Pipeline[_InT, str]:
322
+ return self.transform(str.strip)
323
+
324
+ def str_pattern(self: _Pipeline[_InT, str], pattern: str) -> _Pipeline[_InT, str]:
325
+ return self.constrain(re.compile(pattern))
326
+
327
+ def str_contains(self: _Pipeline[_InT, str], substring: str) -> _Pipeline[_InT, str]:
328
+ return self.predicate(lambda v: substring in v)
329
+
330
+ def str_starts_with(self: _Pipeline[_InT, str], prefix: str) -> _Pipeline[_InT, str]:
331
+ return self.predicate(lambda v: v.startswith(prefix))
332
+
333
+ def str_ends_with(self: _Pipeline[_InT, str], suffix: str) -> _Pipeline[_InT, str]:
334
+ return self.predicate(lambda v: v.endswith(suffix))
335
+
336
+ # operators
337
+ def otherwise(self, other: _Pipeline[_OtherIn, _OtherOut]) -> _Pipeline[_InT | _OtherIn, _OutT | _OtherOut]:
338
+ """Combine two validation chains, returning the result of the first chain if it succeeds, and the second chain if it fails."""
339
+ return _Pipeline((_PipelineOr(self, other),))
340
+
341
+ __or__ = otherwise
342
+
343
+ def then(self, other: _Pipeline[_OutT, _OtherOut]) -> _Pipeline[_InT, _OtherOut]:
344
+ """Pipe the result of one validation chain into another."""
345
+ return _Pipeline((_PipelineAnd(self, other),))
346
+
347
+ __and__ = then
348
+
349
+ def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> cs.CoreSchema:
350
+ queue = deque(self._steps)
351
+
352
+ s = None
353
+
354
+ while queue:
355
+ step = queue.popleft()
356
+ s = _apply_step(step, s, handler, source_type)
357
+
358
+ s = s or cs.any_schema()
359
+ return s
360
+
361
+ def __supports_type__(self, _: _OutT) -> bool:
362
+ raise NotImplementedError
363
+
364
+
365
+ validate_as = _Pipeline[Any, Any](()).validate_as
366
+ validate_as_deferred = _Pipeline[Any, Any](()).validate_as_deferred
367
+ transform = _Pipeline[Any, Any]((_ValidateAs(_FieldTypeMarker),)).transform
368
+
369
+
370
+ def _check_func(
371
+ func: Callable[[Any], bool], predicate_err: str | Callable[[], str], s: cs.CoreSchema | None
372
+ ) -> cs.CoreSchema:
373
+ def handler(v: Any) -> Any:
374
+ if func(v):
375
+ return v
376
+ raise ValueError(f'Expected {predicate_err if isinstance(predicate_err, str) else predicate_err()}')
377
+
378
+ if s is None:
379
+ return cs.no_info_plain_validator_function(handler)
380
+ else:
381
+ return cs.no_info_after_validator_function(handler, s)
382
+
383
+
384
+ def _apply_step(step: _Step, s: cs.CoreSchema | None, handler: GetCoreSchemaHandler, source_type: Any) -> cs.CoreSchema:
385
+ if isinstance(step, _ValidateAs):
386
+ s = _apply_parse(s, step.tp, step.strict, handler, source_type)
387
+ elif isinstance(step, _ValidateAsDefer):
388
+ s = _apply_parse(s, step.tp, False, handler, source_type)
389
+ elif isinstance(step, _Transform):
390
+ s = _apply_transform(s, step.func, handler)
391
+ elif isinstance(step, _Constraint):
392
+ s = _apply_constraint(s, step.constraint)
393
+ elif isinstance(step, _PipelineOr):
394
+ s = cs.union_schema([handler(step.left), handler(step.right)])
395
+ else:
396
+ assert isinstance(step, _PipelineAnd)
397
+ s = cs.chain_schema([handler(step.left), handler(step.right)])
398
+ return s
399
+
400
+
401
+ def _apply_parse(
402
+ s: cs.CoreSchema | None,
403
+ tp: type[Any],
404
+ strict: bool,
405
+ handler: GetCoreSchemaHandler,
406
+ source_type: Any,
407
+ ) -> cs.CoreSchema:
408
+ if tp is _FieldTypeMarker:
409
+ return cs.chain_schema([s, handler(source_type)]) if s else handler(source_type)
410
+
411
+ if strict:
412
+ tp = Annotated[tp, Strict()] # type: ignore
413
+
414
+ if s and s['type'] == 'any':
415
+ return handler(tp)
416
+ else:
417
+ return cs.chain_schema([s, handler(tp)]) if s else handler(tp)
418
+
419
+
420
+ def _apply_transform(
421
+ s: cs.CoreSchema | None, func: Callable[[Any], Any], handler: GetCoreSchemaHandler
422
+ ) -> cs.CoreSchema:
423
+ if s is None:
424
+ return cs.no_info_plain_validator_function(func)
425
+
426
+ if s['type'] == 'str':
427
+ if func is str.strip:
428
+ s = s.copy()
429
+ s['strip_whitespace'] = True
430
+ return s
431
+ elif func is str.lower:
432
+ s = s.copy()
433
+ s['to_lower'] = True
434
+ return s
435
+ elif func is str.upper:
436
+ s = s.copy()
437
+ s['to_upper'] = True
438
+ return s
439
+
440
+ return cs.no_info_after_validator_function(func, s)
441
+
442
+
443
+ def _apply_constraint( # noqa: C901
444
+ s: cs.CoreSchema | None, constraint: _ConstraintAnnotation
445
+ ) -> cs.CoreSchema:
446
+ """Apply a single constraint to a schema."""
447
+ if isinstance(constraint, annotated_types.Gt):
448
+ gt = constraint.gt
449
+ if s and s['type'] in {'int', 'float', 'decimal'}:
450
+ s = s.copy()
451
+ if s['type'] == 'int' and isinstance(gt, int):
452
+ s['gt'] = gt
453
+ elif s['type'] == 'float' and isinstance(gt, float):
454
+ s['gt'] = gt
455
+ elif s['type'] == 'decimal' and isinstance(gt, Decimal):
456
+ s['gt'] = gt
457
+ else:
458
+
459
+ def check_gt(v: Any) -> bool:
460
+ return v > gt
461
+
462
+ s = _check_func(check_gt, f'> {gt}', s)
463
+ elif isinstance(constraint, annotated_types.Ge):
464
+ ge = constraint.ge
465
+ if s and s['type'] in {'int', 'float', 'decimal'}:
466
+ s = s.copy()
467
+ if s['type'] == 'int' and isinstance(ge, int):
468
+ s['ge'] = ge
469
+ elif s['type'] == 'float' and isinstance(ge, float):
470
+ s['ge'] = ge
471
+ elif s['type'] == 'decimal' and isinstance(ge, Decimal):
472
+ s['ge'] = ge
473
+
474
+ def check_ge(v: Any) -> bool:
475
+ return v >= ge
476
+
477
+ s = _check_func(check_ge, f'>= {ge}', s)
478
+ elif isinstance(constraint, annotated_types.Lt):
479
+ lt = constraint.lt
480
+ if s and s['type'] in {'int', 'float', 'decimal'}:
481
+ s = s.copy()
482
+ if s['type'] == 'int' and isinstance(lt, int):
483
+ s['lt'] = lt
484
+ elif s['type'] == 'float' and isinstance(lt, float):
485
+ s['lt'] = lt
486
+ elif s['type'] == 'decimal' and isinstance(lt, Decimal):
487
+ s['lt'] = lt
488
+
489
+ def check_lt(v: Any) -> bool:
490
+ return v < lt
491
+
492
+ s = _check_func(check_lt, f'< {lt}', s)
493
+ elif isinstance(constraint, annotated_types.Le):
494
+ le = constraint.le
495
+ if s and s['type'] in {'int', 'float', 'decimal'}:
496
+ s = s.copy()
497
+ if s['type'] == 'int' and isinstance(le, int):
498
+ s['le'] = le
499
+ elif s['type'] == 'float' and isinstance(le, float):
500
+ s['le'] = le
501
+ elif s['type'] == 'decimal' and isinstance(le, Decimal):
502
+ s['le'] = le
503
+
504
+ def check_le(v: Any) -> bool:
505
+ return v <= le
506
+
507
+ s = _check_func(check_le, f'<= {le}', s)
508
+ elif isinstance(constraint, annotated_types.Len):
509
+ min_len = constraint.min_length
510
+ max_len = constraint.max_length
511
+
512
+ if s and s['type'] in {'str', 'list', 'tuple', 'set', 'frozenset', 'dict'}:
513
+ assert (
514
+ s['type'] == 'str'
515
+ or s['type'] == 'list'
516
+ or s['type'] == 'tuple'
517
+ or s['type'] == 'set'
518
+ or s['type'] == 'dict'
519
+ or s['type'] == 'frozenset'
520
+ )
521
+ s = s.copy()
522
+ if min_len != 0:
523
+ s['min_length'] = min_len
524
+ if max_len is not None:
525
+ s['max_length'] = max_len
526
+
527
+ def check_len(v: Any) -> bool:
528
+ if max_len is not None:
529
+ return (min_len <= len(v)) and (len(v) <= max_len)
530
+ return min_len <= len(v)
531
+
532
+ s = _check_func(check_len, f'length >= {min_len} and length <= {max_len}', s)
533
+ elif isinstance(constraint, annotated_types.MultipleOf):
534
+ multiple_of = constraint.multiple_of
535
+ if s and s['type'] in {'int', 'float', 'decimal'}:
536
+ s = s.copy()
537
+ if s['type'] == 'int' and isinstance(multiple_of, int):
538
+ s['multiple_of'] = multiple_of
539
+ elif s['type'] == 'float' and isinstance(multiple_of, float):
540
+ s['multiple_of'] = multiple_of
541
+ elif s['type'] == 'decimal' and isinstance(multiple_of, Decimal):
542
+ s['multiple_of'] = multiple_of
543
+
544
+ def check_multiple_of(v: Any) -> bool:
545
+ return v % multiple_of == 0
546
+
547
+ s = _check_func(check_multiple_of, f'% {multiple_of} == 0', s)
548
+ elif isinstance(constraint, annotated_types.Timezone):
549
+ tz = constraint.tz
550
+
551
+ if tz is ...:
552
+ if s and s['type'] == 'datetime':
553
+ s = s.copy()
554
+ s['tz_constraint'] = 'aware'
555
+ else:
556
+
557
+ def check_tz_aware(v: object) -> bool:
558
+ assert isinstance(v, datetime.datetime)
559
+ return v.tzinfo is not None
560
+
561
+ s = _check_func(check_tz_aware, 'timezone aware', s)
562
+ elif tz is None:
563
+ if s and s['type'] == 'datetime':
564
+ s = s.copy()
565
+ s['tz_constraint'] = 'naive'
566
+ else:
567
+
568
+ def check_tz_naive(v: object) -> bool:
569
+ assert isinstance(v, datetime.datetime)
570
+ return v.tzinfo is None
571
+
572
+ s = _check_func(check_tz_naive, 'timezone naive', s)
573
+ else:
574
+ raise NotImplementedError('Constraining to a specific timezone is not yet supported')
575
+ elif isinstance(constraint, annotated_types.Interval):
576
+ if constraint.ge:
577
+ s = _apply_constraint(s, annotated_types.Ge(constraint.ge))
578
+ if constraint.gt:
579
+ s = _apply_constraint(s, annotated_types.Gt(constraint.gt))
580
+ if constraint.le:
581
+ s = _apply_constraint(s, annotated_types.Le(constraint.le))
582
+ if constraint.lt:
583
+ s = _apply_constraint(s, annotated_types.Lt(constraint.lt))
584
+ assert s is not None
585
+ elif isinstance(constraint, annotated_types.Predicate):
586
+ func = constraint.func
587
+ # Same logic as in `_known_annotated_metadata.apply_known_metadata()`:
588
+ predicate_name = f'{func.__qualname__!r} ' if hasattr(func, '__qualname__') else ''
589
+
590
+ def predicate_func(v: Any) -> Any:
591
+ if not func(v):
592
+ raise PydanticCustomError(
593
+ 'predicate_failed',
594
+ f'Predicate {predicate_name}failed', # pyright: ignore[reportArgumentType]
595
+ )
596
+ return v
597
+
598
+ if s is None:
599
+ s = cs.no_info_plain_validator_function(predicate_func)
600
+ else:
601
+ s = cs.no_info_after_validator_function(predicate_func, s)
602
+ elif isinstance(constraint, _NotEq):
603
+ value = constraint.value
604
+
605
+ def check_not_eq(v: Any) -> bool:
606
+ return operator.__ne__(v, value)
607
+
608
+ s = _check_func(check_not_eq, f'!= {value}', s)
609
+ elif isinstance(constraint, _Eq):
610
+ value = constraint.value
611
+
612
+ def check_eq(v: Any) -> bool:
613
+ return operator.__eq__(v, value)
614
+
615
+ s = _check_func(check_eq, f'== {value}', s)
616
+ elif isinstance(constraint, _In):
617
+ values = constraint.values
618
+
619
+ def check_in(v: Any) -> bool:
620
+ return operator.__contains__(values, v)
621
+
622
+ s = _check_func(check_in, f'in {values}', s)
623
+ elif isinstance(constraint, _NotIn):
624
+ values = constraint.values
625
+
626
+ def check_not_in(v: Any) -> bool:
627
+ return operator.__not__(operator.__contains__(values, v))
628
+
629
+ s = _check_func(check_not_in, f'not in {values}', s)
630
+ else:
631
+ assert isinstance(constraint, Pattern)
632
+ if s and s['type'] == 'str':
633
+ s = s.copy()
634
+ s['pattern'] = constraint.pattern
635
+ else:
636
+
637
+ def check_pattern(v: object) -> bool:
638
+ assert isinstance(v, str)
639
+ return constraint.match(v) is not None
640
+
641
+ s = _check_func(check_pattern, f'~ {constraint.pattern}', s)
642
+ return s
643
+
644
+
645
+ class _SupportsRange(annotated_types.SupportsLe, annotated_types.SupportsGe, Protocol):
646
+ pass
647
+
648
+
649
+ class _SupportsLen(Protocol):
650
+ def __len__(self) -> int: ...
651
+
652
+
653
+ _NewOutGt = TypeVar('_NewOutGt', bound=annotated_types.SupportsGt)
654
+ _NewOutGe = TypeVar('_NewOutGe', bound=annotated_types.SupportsGe)
655
+ _NewOutLt = TypeVar('_NewOutLt', bound=annotated_types.SupportsLt)
656
+ _NewOutLe = TypeVar('_NewOutLe', bound=annotated_types.SupportsLe)
657
+ _NewOutLen = TypeVar('_NewOutLen', bound=_SupportsLen)
658
+ _NewOutDiv = TypeVar('_NewOutDiv', bound=annotated_types.SupportsDiv)
659
+ _NewOutMod = TypeVar('_NewOutMod', bound=annotated_types.SupportsMod)
660
+ _NewOutDatetime = TypeVar('_NewOutDatetime', bound=datetime.datetime)
661
+ _NewOutInterval = TypeVar('_NewOutInterval', bound=_SupportsRange)
662
+ _OtherIn = TypeVar('_OtherIn')
663
+ _OtherOut = TypeVar('_OtherOut')
.mcp-venv/lib/python3.13/site-packages/pydantic/fields.py ADDED
@@ -0,0 +1,1892 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Defining fields on models."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ import dataclasses
6
+ import inspect
7
+ import re
8
+ import sys
9
+ from collections.abc import Callable, Mapping
10
+ from copy import copy
11
+ from dataclasses import Field as DataclassField
12
+ from functools import cached_property
13
+ from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Literal, TypeVar, final, overload
14
+ from warnings import warn
15
+
16
+ import annotated_types
17
+ import typing_extensions
18
+ from pydantic_core import MISSING, PydanticUndefined
19
+ from typing_extensions import Self, TypeAlias, TypedDict, Unpack, deprecated
20
+ from typing_inspection import typing_objects
21
+ from typing_inspection.introspection import UNKNOWN, AnnotationSource, ForbiddenQualifier, Qualifier, inspect_annotation
22
+
23
+ from . import types
24
+ from ._internal import _decorators, _fields, _generics, _internal_dataclass, _repr, _typing_extra, _utils
25
+ from ._internal._namespace_utils import GlobalsNamespace, MappingNamespace
26
+ from .aliases import AliasChoices, AliasGenerator, AliasPath
27
+ from .config import JsonDict
28
+ from .errors import PydanticForbiddenQualifier, PydanticUserError
29
+ from .json_schema import PydanticJsonSchemaWarning
30
+ from .warnings import PydanticDeprecatedSince20
31
+
32
+ if TYPE_CHECKING:
33
+ from ._internal._config import ConfigWrapper
34
+ from ._internal._repr import ReprArgs
35
+
36
+
37
+ __all__ = 'Field', 'FieldInfo', 'PrivateAttr', 'computed_field'
38
+
39
+
40
+ _Unset: Any = PydanticUndefined
41
+
42
+ if sys.version_info >= (3, 13):
43
+ import warnings
44
+
45
+ Deprecated: TypeAlias = warnings.deprecated | deprecated
46
+ else:
47
+ Deprecated: TypeAlias = deprecated
48
+
49
+
50
+ class _FromFieldInfoInputs(TypedDict, total=False):
51
+ """This class exists solely to add type checking for the `**kwargs` in `FieldInfo.from_field`."""
52
+
53
+ # TODO PEP 747: use TypeForm:
54
+ annotation: type[Any] | None
55
+ default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None
56
+ alias: str | None
57
+ alias_priority: int | None
58
+ validation_alias: str | AliasPath | AliasChoices | None
59
+ serialization_alias: str | None
60
+ title: str | None
61
+ field_title_generator: Callable[[str, FieldInfo], str] | None
62
+ description: str | None
63
+ examples: list[Any] | None
64
+ exclude: bool | None
65
+ exclude_if: Callable[[Any], bool] | None
66
+ gt: annotated_types.SupportsGt | None
67
+ ge: annotated_types.SupportsGe | None
68
+ lt: annotated_types.SupportsLt | None
69
+ le: annotated_types.SupportsLe | None
70
+ multiple_of: float | None
71
+ strict: bool | None
72
+ min_length: int | None
73
+ max_length: int | None
74
+ pattern: str | re.Pattern[str] | None
75
+ allow_inf_nan: bool | None
76
+ max_digits: int | None
77
+ decimal_places: int | None
78
+ union_mode: Literal['smart', 'left_to_right'] | None
79
+ discriminator: str | types.Discriminator | None
80
+ deprecated: Deprecated | str | bool | None
81
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None
82
+ frozen: bool | None
83
+ validate_default: bool | None
84
+ repr: bool
85
+ init: bool | None
86
+ init_var: bool | None
87
+ kw_only: bool | None
88
+ coerce_numbers_to_str: bool | None
89
+ fail_fast: bool | None
90
+
91
+
92
+ class _FieldInfoInputs(_FromFieldInfoInputs, total=False):
93
+ """This class exists solely to add type checking for the `**kwargs` in `FieldInfo.__init__`."""
94
+
95
+ default: Any
96
+
97
+
98
+ class _FieldInfoAsDict(TypedDict, closed=True):
99
+ # TODO PEP 747: use TypeForm:
100
+ annotation: Any
101
+ metadata: list[Any]
102
+ attributes: dict[str, Any]
103
+
104
+
105
+ @final
106
+ class FieldInfo(_repr.Representation):
107
+ """This class holds information about a field.
108
+
109
+ `FieldInfo` is used for any field definition regardless of whether the [`Field()`][pydantic.fields.Field]
110
+ function is explicitly used.
111
+
112
+ !!! warning
113
+ The `FieldInfo` class is meant to expose information about a field in a Pydantic model or dataclass.
114
+ `FieldInfo` instances shouldn't be instantiated directly, nor mutated.
115
+
116
+ If you need to derive a new model from another one and are willing to alter `FieldInfo` instances,
117
+ refer to this [dynamic model example](../examples/dynamic_models.md).
118
+
119
+ Attributes:
120
+ annotation: The type annotation of the field.
121
+ default: The default value of the field.
122
+ default_factory: A callable to generate the default value. The callable can either take 0 arguments
123
+ (in which case it is called as is) or a single argument containing the already validated data.
124
+ alias: The alias name of the field.
125
+ alias_priority: The priority of the field's alias.
126
+ validation_alias: The validation alias of the field.
127
+ serialization_alias: The serialization alias of the field.
128
+ title: The title of the field.
129
+ field_title_generator: A callable that takes a field name and returns title for it.
130
+ description: The description of the field.
131
+ examples: List of examples of the field.
132
+ exclude: Whether to exclude the field from the model serialization.
133
+ exclude_if: A callable that determines whether to exclude a field during serialization based on its value.
134
+ discriminator: Field name or Discriminator for discriminating the type in a tagged union.
135
+ deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport,
136
+ or a boolean. If `True`, a default deprecation message will be emitted when accessing the field.
137
+ json_schema_extra: A dict or callable to provide extra JSON schema properties.
138
+ frozen: Whether the field is frozen.
139
+ validate_default: Whether to validate the default value of the field.
140
+ repr: Whether to include the field in representation of the model.
141
+ init: Whether the field should be included in the constructor of the dataclass.
142
+ init_var: Whether the field should _only_ be included in the constructor of the dataclass, and not stored.
143
+ kw_only: Whether the field should be a keyword-only argument in the constructor of the dataclass.
144
+ metadata: The metadata list. Contains all the data that isn't expressed as direct `FieldInfo` attributes, including:
145
+
146
+ * Type-specific constraints, such as `gt` or `min_length` (these are converted to metadata classes such as `annotated_types.Gt`).
147
+ * Any other arbitrary object used within [`Annotated`][typing.Annotated] metadata
148
+ (e.g. [custom types handlers](../concepts/types.md#as-an-annotation) or any object not recognized by Pydantic).
149
+ """
150
+
151
+ # TODO PEP 747: use TypeForm:
152
+ annotation: type[Any] | None
153
+ default: Any
154
+ default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None
155
+ alias: str | None
156
+ alias_priority: int | None
157
+ validation_alias: str | AliasPath | AliasChoices | None
158
+ serialization_alias: str | None
159
+ title: str | None
160
+ field_title_generator: Callable[[str, FieldInfo], str] | None
161
+ description: str | None
162
+ examples: list[Any] | None
163
+ exclude: bool | None
164
+ exclude_if: Callable[[Any], bool] | None
165
+ discriminator: str | types.Discriminator | None
166
+ deprecated: Deprecated | str | bool | None
167
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None
168
+ frozen: bool | None
169
+ validate_default: bool | None
170
+ repr: bool
171
+ init: bool | None
172
+ init_var: bool | None
173
+ kw_only: bool | None
174
+ metadata: list[Any]
175
+
176
+ __slots__ = (
177
+ 'annotation',
178
+ 'default',
179
+ 'default_factory',
180
+ 'alias',
181
+ 'alias_priority',
182
+ 'validation_alias',
183
+ 'serialization_alias',
184
+ 'title',
185
+ 'field_title_generator',
186
+ 'description',
187
+ 'examples',
188
+ 'exclude',
189
+ 'exclude_if',
190
+ 'discriminator',
191
+ 'deprecated',
192
+ 'json_schema_extra',
193
+ 'frozen',
194
+ 'validate_default',
195
+ 'repr',
196
+ 'init',
197
+ 'init_var',
198
+ 'kw_only',
199
+ 'metadata',
200
+ '_attributes_set',
201
+ '_qualifiers',
202
+ '_complete',
203
+ '_original_assignment',
204
+ '_original_annotation',
205
+ '_final',
206
+ )
207
+
208
+ # used to convert kwargs to metadata/constraints,
209
+ # None has a special meaning - these items are collected into a `PydanticGeneralMetadata`
210
+ metadata_lookup: ClassVar[dict[str, Callable[[Any], Any] | None]] = {
211
+ 'strict': types.Strict,
212
+ 'gt': annotated_types.Gt,
213
+ 'ge': annotated_types.Ge,
214
+ 'lt': annotated_types.Lt,
215
+ 'le': annotated_types.Le,
216
+ 'multiple_of': annotated_types.MultipleOf,
217
+ 'min_length': annotated_types.MinLen,
218
+ 'max_length': annotated_types.MaxLen,
219
+ 'pattern': None,
220
+ 'allow_inf_nan': None,
221
+ 'max_digits': None,
222
+ 'decimal_places': None,
223
+ 'union_mode': None,
224
+ 'coerce_numbers_to_str': None,
225
+ 'fail_fast': types.FailFast,
226
+ }
227
+
228
+ def __init__(self, **kwargs: Unpack[_FieldInfoInputs]) -> None:
229
+ """This class should generally not be initialized directly; instead, use the `pydantic.fields.Field` function
230
+ or one of the constructor classmethods.
231
+
232
+ See the signature of `pydantic.fields.Field` for more details about the expected arguments.
233
+ """
234
+ # Tracking the explicitly set attributes is necessary to correctly merge `Field()` functions
235
+ # (e.g. with `Annotated[int, Field(alias='a'), Field(alias=None)]`, even though `None` is the default value,
236
+ # we need to track that `alias=None` was explicitly set):
237
+ self._attributes_set = {k: v for k, v in kwargs.items() if v is not _Unset and k not in self.metadata_lookup}
238
+ kwargs = {k: _DefaultValues.get(k) if v is _Unset else v for k, v in kwargs.items()} # type: ignore
239
+ self.annotation = kwargs.get('annotation')
240
+
241
+ # Note: in theory, the second `pop()` arguments are not required below, as defaults are already set from `_DefaultsValues`.
242
+ default = kwargs.pop('default', PydanticUndefined)
243
+ if default is Ellipsis:
244
+ self.default = PydanticUndefined
245
+ self._attributes_set.pop('default', None)
246
+ else:
247
+ self.default = default
248
+
249
+ self.default_factory = kwargs.pop('default_factory', None)
250
+
251
+ if self.default is not PydanticUndefined and self.default_factory is not None:
252
+ raise TypeError('cannot specify both default and default_factory')
253
+
254
+ self.alias = kwargs.pop('alias', None)
255
+ self.validation_alias = kwargs.pop('validation_alias', None)
256
+ self.serialization_alias = kwargs.pop('serialization_alias', None)
257
+ alias_is_set = any(alias is not None for alias in (self.alias, self.validation_alias, self.serialization_alias))
258
+ self.alias_priority = kwargs.pop('alias_priority', None) or 2 if alias_is_set else None
259
+ self.title = kwargs.pop('title', None)
260
+ self.field_title_generator = kwargs.pop('field_title_generator', None)
261
+ self.description = kwargs.pop('description', None)
262
+ self.examples = kwargs.pop('examples', None)
263
+ self.exclude = kwargs.pop('exclude', None)
264
+ self.exclude_if = kwargs.pop('exclude_if', None)
265
+ self.discriminator = kwargs.pop('discriminator', None)
266
+ # For compatibility with FastAPI<=0.110.0, we preserve the existing value if it is not overridden
267
+ self.deprecated = kwargs.pop('deprecated', getattr(self, 'deprecated', None))
268
+ self.repr = kwargs.pop('repr', True)
269
+ self.json_schema_extra = kwargs.pop('json_schema_extra', None)
270
+ self.validate_default = kwargs.pop('validate_default', None)
271
+ self.frozen = kwargs.pop('frozen', None)
272
+ # currently only used on dataclasses
273
+ self.init = kwargs.pop('init', None)
274
+ self.init_var = kwargs.pop('init_var', None)
275
+ self.kw_only = kwargs.pop('kw_only', None)
276
+
277
+ self.metadata = self._collect_metadata(kwargs) # type: ignore
278
+
279
+ # Private attributes:
280
+ self._qualifiers: set[Qualifier] = set()
281
+ # Used to rebuild FieldInfo instances:
282
+ self._complete = True
283
+ self._original_annotation: Any = PydanticUndefined
284
+ self._original_assignment: Any = PydanticUndefined
285
+ # Used to track whether the `FieldInfo` instance represents the data about a field (and is exposed in `model_fields`/`__pydantic_fields__`),
286
+ # or if it is the result of the `Field()` function being used as metadata in an `Annotated` type/as an assignment
287
+ # (not an ideal pattern, see https://github.com/pydantic/pydantic/issues/11122):
288
+ self._final = False
289
+
290
+ @staticmethod
291
+ def from_field(default: Any = PydanticUndefined, **kwargs: Unpack[_FromFieldInfoInputs]) -> FieldInfo:
292
+ """Create a new `FieldInfo` object with the `Field` function.
293
+
294
+ Args:
295
+ default: The default value for the field. Defaults to Undefined.
296
+ **kwargs: Additional arguments dictionary.
297
+
298
+ Raises:
299
+ TypeError: If 'annotation' is passed as a keyword argument.
300
+
301
+ Returns:
302
+ A new FieldInfo object with the given parameters.
303
+
304
+ Example:
305
+ This is how you can create a field with default value like this:
306
+
307
+ ```python
308
+ import pydantic
309
+
310
+ class MyModel(pydantic.BaseModel):
311
+ foo: int = pydantic.Field(4)
312
+ ```
313
+ """
314
+ if 'annotation' in kwargs:
315
+ raise TypeError('"annotation" is not permitted as a Field keyword argument')
316
+ return FieldInfo(default=default, **kwargs)
317
+
318
+ @staticmethod
319
+ def from_annotation(annotation: type[Any], *, _source: AnnotationSource = AnnotationSource.ANY) -> FieldInfo:
320
+ """Creates a `FieldInfo` instance from a bare annotation.
321
+
322
+ This function is used internally to create a `FieldInfo` from a bare annotation like this:
323
+
324
+ ```python
325
+ import pydantic
326
+
327
+ class MyModel(pydantic.BaseModel):
328
+ foo: int # <-- like this
329
+ ```
330
+
331
+ We also account for the case where the annotation can be an instance of `Annotated` and where
332
+ one of the (not first) arguments in `Annotated` is an instance of `FieldInfo`, e.g.:
333
+
334
+ ```python
335
+ from typing import Annotated
336
+
337
+ import annotated_types
338
+
339
+ import pydantic
340
+
341
+ class MyModel(pydantic.BaseModel):
342
+ foo: Annotated[int, annotated_types.Gt(42)]
343
+ bar: Annotated[int, pydantic.Field(gt=42)]
344
+ ```
345
+
346
+ Args:
347
+ annotation: An annotation object.
348
+
349
+ Returns:
350
+ An instance of the field metadata.
351
+ """
352
+ try:
353
+ inspected_ann = inspect_annotation(
354
+ annotation,
355
+ annotation_source=_source,
356
+ unpack_type_aliases='skip',
357
+ )
358
+ except ForbiddenQualifier as e:
359
+ raise PydanticForbiddenQualifier(e.qualifier, annotation)
360
+
361
+ # TODO check for classvar and error?
362
+
363
+ # No assigned value, this happens when using a bare `Final` qualifier (also for other
364
+ # qualifiers, but they shouldn't appear here). In this case we infer the type as `Any`
365
+ # because we don't have any assigned value.
366
+ type_expr: Any = Any if inspected_ann.type is UNKNOWN else inspected_ann.type
367
+ final = 'final' in inspected_ann.qualifiers
368
+ metadata = inspected_ann.metadata
369
+
370
+ attr_overrides = {'annotation': type_expr}
371
+ if final:
372
+ attr_overrides['frozen'] = True
373
+ field_info = FieldInfo._construct(metadata, **attr_overrides)
374
+ field_info._qualifiers = inspected_ann.qualifiers
375
+ field_info._final = True
376
+ return field_info
377
+
378
+ @staticmethod
379
+ def from_annotated_attribute(
380
+ annotation: type[Any], default: Any, *, _source: AnnotationSource = AnnotationSource.ANY
381
+ ) -> FieldInfo:
382
+ """Create `FieldInfo` from an annotation with a default value.
383
+
384
+ This is used in cases like the following:
385
+
386
+ ```python
387
+ from typing import Annotated
388
+
389
+ import annotated_types
390
+
391
+ import pydantic
392
+
393
+ class MyModel(pydantic.BaseModel):
394
+ foo: int = 4 # <-- like this
395
+ bar: Annotated[int, annotated_types.Gt(4)] = 4 # <-- or this
396
+ spam: Annotated[int, pydantic.Field(gt=4)] = 4 # <-- or this
397
+ ```
398
+
399
+ Args:
400
+ annotation: The type annotation of the field.
401
+ default: The default value of the field.
402
+
403
+ Returns:
404
+ A field object with the passed values.
405
+ """
406
+ if annotation is not MISSING and annotation is default:
407
+ raise PydanticUserError(
408
+ 'Error when building FieldInfo from annotated attribute. '
409
+ "Make sure you don't have any field name clashing with a type annotation.",
410
+ code='unevaluable-type-annotation',
411
+ )
412
+
413
+ try:
414
+ inspected_ann = inspect_annotation(
415
+ annotation,
416
+ annotation_source=_source,
417
+ unpack_type_aliases='skip',
418
+ )
419
+ except ForbiddenQualifier as e:
420
+ raise PydanticForbiddenQualifier(e.qualifier, annotation)
421
+
422
+ # TODO check for classvar and error?
423
+
424
+ # TODO infer from the default, this can be done in v3 once we treat final fields with
425
+ # a default as proper fields and not class variables:
426
+ type_expr: Any = Any if inspected_ann.type is UNKNOWN else inspected_ann.type
427
+ final = 'final' in inspected_ann.qualifiers
428
+ metadata = inspected_ann.metadata
429
+
430
+ # HACK 1: the order in which the metadata is merged is inconsistent; we need to prepend
431
+ # metadata from the assignment at the beginning of the metadata. Changing this is only
432
+ # possible in v3 (at least). See https://github.com/pydantic/pydantic/issues/10507
433
+ prepend_metadata: list[Any] | None = None
434
+ attr_overrides = {'annotation': type_expr}
435
+ if final:
436
+ attr_overrides['frozen'] = True
437
+
438
+ # HACK 2: FastAPI is subclassing `FieldInfo` and historically expected the actual
439
+ # instance's type to be preserved when constructing new models with its subclasses as assignments.
440
+ # This code is never reached by Pydantic itself, and in an ideal world this shouldn't be necessary.
441
+ if not metadata and isinstance(default, FieldInfo) and type(default) is not FieldInfo:
442
+ field_info = default._copy()
443
+ field_info._attributes_set.update(attr_overrides)
444
+ for k, v in attr_overrides.items():
445
+ setattr(field_info, k, v)
446
+ return field_info
447
+
448
+ if isinstance(default, FieldInfo):
449
+ default_copy = default._copy() # Copy unnecessary when we remove HACK 1.
450
+ prepend_metadata = default_copy.metadata
451
+ default_copy.metadata = []
452
+ metadata = metadata + [default_copy]
453
+ if 'init_var' in inspected_ann.qualifiers:
454
+ # Only relevant for dataclasses, when `f: InitVar[<type>] = Field(...)`
455
+ # is used:
456
+ attr_overrides['init_var'] = True
457
+ elif isinstance(default, dataclasses.Field):
458
+ from_field = FieldInfo._from_dataclass_field(default)
459
+ prepend_metadata = from_field.metadata # Unnecessary when we remove HACK 1.
460
+ from_field.metadata = []
461
+ metadata = metadata + [from_field]
462
+ if 'init_var' in inspected_ann.qualifiers:
463
+ attr_overrides['init_var'] = True
464
+ if (init := getattr(default, 'init', None)) is not None:
465
+ attr_overrides['init'] = init
466
+ if (kw_only := getattr(default, 'kw_only', None)) is not None:
467
+ attr_overrides['kw_only'] = kw_only
468
+ else:
469
+ # `default` is the actual default value
470
+ attr_overrides['default'] = default
471
+
472
+ field_info = FieldInfo._construct(
473
+ prepend_metadata + metadata if prepend_metadata is not None else metadata, **attr_overrides
474
+ )
475
+ field_info._qualifiers = inspected_ann.qualifiers
476
+ field_info._final = True
477
+ return field_info
478
+
479
+ @classmethod
480
+ def _construct(cls, metadata: list[Any], **attr_overrides: Any) -> Self:
481
+ """Construct the final `FieldInfo` instance, by merging the possibly existing `FieldInfo` instances from the metadata.
482
+
483
+ With the following example:
484
+
485
+ ```python {test="skip" lint="skip"}
486
+ class Model(BaseModel):
487
+ f: Annotated[int, Gt(1), Field(description='desc', lt=2)]
488
+ ```
489
+
490
+ `metadata` refers to the metadata elements of the `Annotated` form. This metadata is iterated over from left to right:
491
+
492
+ - If the element is a `Field()` function (which is itself a `FieldInfo` instance), the field attributes (such as
493
+ `description`) are saved to be set on the final `FieldInfo` instance.
494
+ On the other hand, some kwargs (such as `lt`) are stored as `metadata` (see `FieldInfo.__init__()`, calling
495
+ `FieldInfo._collect_metadata()`). In this case, the final metadata list is extended with the one from this instance.
496
+ - Else, the element is considered as a single metadata object, and is appended to the final metadata list.
497
+
498
+ Args:
499
+ metadata: The list of metadata elements to merge together. If the `FieldInfo` instance to be constructed is for
500
+ a field with an assigned `Field()`, this `Field()` assignment should be added as the last element of the
501
+ provided metadata.
502
+ **attr_overrides: Extra attributes that should be set on the final merged `FieldInfo` instance.
503
+
504
+ Returns:
505
+ The final merged `FieldInfo` instance.
506
+ """
507
+ merged_metadata: list[Any] = []
508
+ merged_kwargs: dict[str, Any] = {}
509
+
510
+ for meta in metadata:
511
+ if isinstance(meta, FieldInfo):
512
+ merged_metadata.extend(meta.metadata)
513
+
514
+ new_js_extra: JsonDict | None = None
515
+ current_js_extra = meta.json_schema_extra
516
+ if current_js_extra is not None and 'json_schema_extra' in merged_kwargs:
517
+ # We need to merge `json_schema_extra`'s:
518
+ existing_js_extra = merged_kwargs['json_schema_extra']
519
+ if isinstance(existing_js_extra, dict):
520
+ if isinstance(current_js_extra, dict):
521
+ new_js_extra = {
522
+ **existing_js_extra,
523
+ **current_js_extra,
524
+ }
525
+ elif callable(current_js_extra):
526
+ warn(
527
+ 'Composing `dict` and `callable` type `json_schema_extra` is not supported. '
528
+ 'The `callable` type is being ignored. '
529
+ "If you'd like support for this behavior, please open an issue on pydantic.",
530
+ UserWarning,
531
+ )
532
+ elif callable(existing_js_extra) and isinstance(current_js_extra, dict):
533
+ warn(
534
+ 'Composing `dict` and `callable` type `json_schema_extra` is not supported. '
535
+ 'The `callable` type is being ignored. '
536
+ "If you'd like support for this behavior, please open an issue on pydantic.",
537
+ UserWarning,
538
+ )
539
+
540
+ # HACK: It is common for users to define "make model partial" (or similar) utilities, that
541
+ # convert all model fields to be optional (i.e. have a default value). To do so, they mutate
542
+ # each `FieldInfo` instance from `model_fields` to set a `default`, and use `create_model()`
543
+ # with `Annotated[<orig_type> | None, mutated_field_info]`` as an annotation. However, such
544
+ # mutations (by doing simple assignments) are only accidentally working, because we also
545
+ # need to track attributes explicitly set in `_attributes_set` (relying on default values for
546
+ # each attribute is *not* enough, for instance with `Annotated[int, Field(alias='a'), Field(alias=None)]`
547
+ # the resulting `FieldInfo` should have `alias=None`).
548
+ # To mitigate this, we add a special case when a "final" `FieldInfo` instance (that is an instance coming
549
+ # from `model_fields`) is used in annotated metadata (or assignment). In this case, we assume *all* attributes
550
+ # were explicitly set, and as such we use all of them (and this will correctly pick up the mutations).
551
+ # In theory, this shouldn't really be supported, you are only supposed to use the `Field()` function, not
552
+ # a `FieldInfo` instance directly (granted, `Field()` returns a `FieldInfo`, see
553
+ # https://github.com/pydantic/pydantic/issues/11122):
554
+ if meta._final:
555
+ merged_kwargs.update({attr: getattr(meta, attr) for attr in _Attrs})
556
+ else:
557
+ merged_kwargs.update(meta._attributes_set)
558
+
559
+ if new_js_extra is not None:
560
+ merged_kwargs['json_schema_extra'] = new_js_extra
561
+ elif typing_objects.is_deprecated(meta):
562
+ merged_kwargs['deprecated'] = meta
563
+ else:
564
+ merged_metadata.append(meta)
565
+
566
+ merged_kwargs.update(attr_overrides)
567
+ merged_field_info = cls(**merged_kwargs)
568
+ merged_field_info.metadata = merged_metadata
569
+ return merged_field_info
570
+
571
+ @staticmethod
572
+ @typing_extensions.deprecated(
573
+ "The 'merge_field_infos()' method is deprecated and will be removed in a future version. "
574
+ 'If you relied on this method, please open an issue in the Pydantic issue tracker.',
575
+ category=None,
576
+ )
577
+ def merge_field_infos(*field_infos: FieldInfo, **overrides: Any) -> FieldInfo:
578
+ """Merge `FieldInfo` instances keeping only explicitly set attributes.
579
+
580
+ Later `FieldInfo` instances override earlier ones.
581
+
582
+ Returns:
583
+ FieldInfo: A merged FieldInfo instance.
584
+ """
585
+ if len(field_infos) == 1:
586
+ # No merging necessary, but we still need to make a copy and apply the overrides
587
+ field_info = field_infos[0]._copy()
588
+ field_info._attributes_set.update(overrides)
589
+
590
+ default_override = overrides.pop('default', PydanticUndefined)
591
+ if default_override is Ellipsis:
592
+ default_override = PydanticUndefined
593
+ if default_override is not PydanticUndefined:
594
+ field_info.default = default_override
595
+
596
+ for k, v in overrides.items():
597
+ setattr(field_info, k, v)
598
+ return field_info # type: ignore
599
+
600
+ merged_field_info_kwargs: dict[str, Any] = {}
601
+ metadata = {}
602
+ for field_info in field_infos:
603
+ attributes_set = field_info._attributes_set.copy()
604
+
605
+ try:
606
+ json_schema_extra = attributes_set.pop('json_schema_extra')
607
+ existing_json_schema_extra = merged_field_info_kwargs.get('json_schema_extra')
608
+
609
+ if existing_json_schema_extra is None:
610
+ merged_field_info_kwargs['json_schema_extra'] = json_schema_extra
611
+ if isinstance(existing_json_schema_extra, dict):
612
+ if isinstance(json_schema_extra, dict):
613
+ merged_field_info_kwargs['json_schema_extra'] = {
614
+ **existing_json_schema_extra,
615
+ **json_schema_extra,
616
+ }
617
+ if callable(json_schema_extra):
618
+ warn(
619
+ 'Composing `dict` and `callable` type `json_schema_extra` is not supported.'
620
+ 'The `callable` type is being ignored.'
621
+ "If you'd like support for this behavior, please open an issue on pydantic.",
622
+ PydanticJsonSchemaWarning,
623
+ )
624
+ elif callable(json_schema_extra):
625
+ # if ever there's a case of a callable, we'll just keep the last json schema extra spec
626
+ merged_field_info_kwargs['json_schema_extra'] = json_schema_extra
627
+ except KeyError:
628
+ pass
629
+
630
+ # later FieldInfo instances override everything except json_schema_extra from earlier FieldInfo instances
631
+ merged_field_info_kwargs.update(attributes_set)
632
+
633
+ for x in field_info.metadata:
634
+ if not isinstance(x, FieldInfo):
635
+ metadata[type(x)] = x
636
+
637
+ merged_field_info_kwargs.update(overrides)
638
+ field_info = FieldInfo(**merged_field_info_kwargs)
639
+ field_info.metadata = list(metadata.values())
640
+ return field_info
641
+
642
+ @staticmethod
643
+ def _from_dataclass_field(dc_field: DataclassField[Any]) -> FieldInfo:
644
+ """Return a new `FieldInfo` instance from a `dataclasses.Field` instance.
645
+
646
+ Args:
647
+ dc_field: The `dataclasses.Field` instance to convert.
648
+
649
+ Returns:
650
+ The corresponding `FieldInfo` instance.
651
+
652
+ Raises:
653
+ TypeError: If any of the `FieldInfo` kwargs does not match the `dataclass.Field` kwargs.
654
+ """
655
+ default = dc_field.default
656
+ if default is dataclasses.MISSING:
657
+ default = _Unset
658
+
659
+ if dc_field.default_factory is dataclasses.MISSING:
660
+ default_factory = _Unset
661
+ else:
662
+ default_factory = dc_field.default_factory
663
+
664
+ # use the `Field` function so in correct kwargs raise the correct `TypeError`
665
+ dc_field_metadata = {k: v for k, v in dc_field.metadata.items() if k in _FIELD_ARG_NAMES}
666
+ if sys.version_info >= (3, 14) and dc_field.doc is not None:
667
+ dc_field_metadata['description'] = dc_field.doc
668
+ return Field(default=default, default_factory=default_factory, repr=dc_field.repr, **dc_field_metadata) # pyright: ignore[reportCallIssue]
669
+
670
+ @staticmethod
671
+ def _collect_metadata(kwargs: dict[str, Any]) -> list[Any]:
672
+ """Collect annotations from kwargs.
673
+
674
+ Args:
675
+ kwargs: Keyword arguments passed to the function.
676
+
677
+ Returns:
678
+ A list of metadata objects - a combination of `annotated_types.BaseMetadata` and
679
+ `PydanticMetadata`.
680
+ """
681
+ metadata: list[Any] = []
682
+ general_metadata = {}
683
+ for key, value in list(kwargs.items()):
684
+ try:
685
+ marker = FieldInfo.metadata_lookup[key]
686
+ except KeyError:
687
+ continue
688
+
689
+ del kwargs[key]
690
+ if value is not None:
691
+ if marker is None:
692
+ general_metadata[key] = value
693
+ else:
694
+ metadata.append(marker(value))
695
+ if general_metadata:
696
+ metadata.append(_fields.pydantic_general_metadata(**general_metadata))
697
+ return metadata
698
+
699
+ @property
700
+ def deprecation_message(self) -> str | None:
701
+ """The deprecation message to be emitted, or `None` if not set."""
702
+ if self.deprecated is None:
703
+ return None
704
+ if isinstance(self.deprecated, bool):
705
+ return 'deprecated' if self.deprecated else None
706
+ return self.deprecated if isinstance(self.deprecated, str) else self.deprecated.message
707
+
708
+ @property
709
+ def default_factory_takes_validated_data(self) -> bool | None:
710
+ """Whether the provided default factory callable has a validated data parameter.
711
+
712
+ Returns `None` if no default factory is set.
713
+ """
714
+ if self.default_factory is not None:
715
+ return _fields.takes_validated_data_argument(self.default_factory)
716
+
717
+ @overload
718
+ def get_default(
719
+ self, *, call_default_factory: Literal[True], validated_data: dict[str, Any] | None = None
720
+ ) -> Any: ...
721
+
722
+ @overload
723
+ def get_default(self, *, call_default_factory: Literal[False] = ...) -> Any: ...
724
+
725
+ def get_default(self, *, call_default_factory: bool = False, validated_data: dict[str, Any] | None = None) -> Any:
726
+ """Get the default value.
727
+
728
+ We expose an option for whether to call the default_factory (if present), as calling it may
729
+ result in side effects that we want to avoid. However, there are times when it really should
730
+ be called (namely, when instantiating a model via `model_construct`).
731
+
732
+ Args:
733
+ call_default_factory: Whether to call the default factory or not.
734
+ validated_data: The already validated data to be passed to the default factory.
735
+
736
+ Returns:
737
+ The default value, calling the default factory if requested or `PydanticUndefined` if not set.
738
+ """
739
+ return _fields.resolve_default_value(
740
+ default=self.default,
741
+ default_factory=self.default_factory,
742
+ validated_data=validated_data,
743
+ call_default_factory=call_default_factory,
744
+ )
745
+
746
+ def is_required(self) -> bool:
747
+ """Check if the field is required (i.e., does not have a default value or factory).
748
+
749
+ Returns:
750
+ `True` if the field is required, `False` otherwise.
751
+ """
752
+ return self.default is PydanticUndefined and self.default_factory is None
753
+
754
+ def rebuild_annotation(self) -> Any:
755
+ """Attempts to rebuild the original annotation for use in function signatures.
756
+
757
+ If metadata is present, it adds it to the original annotation using
758
+ `Annotated`. Otherwise, it returns the original annotation as-is.
759
+
760
+ Note that because the metadata has been flattened, the original annotation
761
+ may not be reconstructed exactly as originally provided, e.g. if the original
762
+ type had unrecognized annotations, or was annotated with a call to `pydantic.Field`.
763
+
764
+ Returns:
765
+ The rebuilt annotation.
766
+ """
767
+ if not self.metadata:
768
+ return self.annotation
769
+ else:
770
+ # Annotated arguments must be a tuple
771
+ return Annotated[(self.annotation, *self.metadata)] # type: ignore
772
+
773
+ def apply_typevars_map(
774
+ self,
775
+ typevars_map: Mapping[TypeVar, Any] | None,
776
+ globalns: GlobalsNamespace | None = None,
777
+ localns: MappingNamespace | None = None,
778
+ ) -> None:
779
+ """Apply a `typevars_map` to the annotation.
780
+
781
+ This method is used when analyzing parametrized generic types to replace typevars with their concrete types.
782
+
783
+ This method applies the `typevars_map` to the annotation in place.
784
+
785
+ Args:
786
+ typevars_map: A dictionary mapping type variables to their concrete types.
787
+ globalns: The globals namespace to use during type annotation evaluation.
788
+ localns: The locals namespace to use during type annotation evaluation.
789
+
790
+ See Also:
791
+ pydantic._internal._generics.replace_types is used for replacing the typevars with
792
+ their concrete types.
793
+ """
794
+ annotation = _generics.replace_types(self.annotation, typevars_map)
795
+ annotation, evaluated = _typing_extra.try_eval_type(annotation, globalns, localns)
796
+ self.annotation = annotation
797
+ if not evaluated:
798
+ self._complete = False
799
+ self._original_annotation = self.annotation
800
+
801
+ def asdict(self) -> _FieldInfoAsDict:
802
+ """Return a dictionary representation of the `FieldInfo` instance.
803
+
804
+ The returned value is a dictionary with three items:
805
+
806
+ * `annotation`: The type annotation of the field.
807
+ * `metadata`: The metadata list.
808
+ * `attributes`: A mapping of the remaining `FieldInfo` attributes to their values (e.g. `alias`, `title`).
809
+ """
810
+ return {
811
+ 'annotation': self.annotation,
812
+ 'metadata': self.metadata,
813
+ 'attributes': {attr: getattr(self, attr) for attr in _Attrs},
814
+ }
815
+
816
+ def _copy(self) -> Self:
817
+ """Return a copy of the `FieldInfo` instance."""
818
+ # Note: we can't define a custom `__copy__()`, as `FieldInfo` is being subclassed
819
+ # by some third-party libraries with extra attributes defined (and as `FieldInfo`
820
+ # is slotted, we can't make a copy of the `__dict__`).
821
+ if type(self) is FieldInfo:
822
+ # Fast-path if the instance isn't a subclass (`copy.copy()` relies on pickling which is slower):
823
+ copied = FieldInfo.__new__(FieldInfo)
824
+ for attr_name in FieldInfo.__slots__:
825
+ setattr(copied, attr_name, getattr(self, attr_name))
826
+ else:
827
+ copied = copy(self)
828
+
829
+ for attr_name in ('metadata', '_attributes_set', '_qualifiers'):
830
+ # Apply "deep-copy" behavior on collections attributes:
831
+ setattr(copied, attr_name, getattr(copied, attr_name).copy())
832
+
833
+ return copied # pyright: ignore[reportReturnType]
834
+
835
+ def __repr_args__(self) -> ReprArgs:
836
+ yield 'annotation', _repr.PlainRepr(_repr.display_as_type(self.annotation))
837
+ yield 'required', self.is_required()
838
+
839
+ for s in self.__slots__:
840
+ # TODO: properly make use of the protocol (https://rich.readthedocs.io/en/stable/pretty.html#rich-repr-protocol)
841
+ # By yielding a three-tuple:
842
+ if s in (
843
+ 'annotation',
844
+ '_attributes_set',
845
+ '_qualifiers',
846
+ '_complete',
847
+ '_original_assignment',
848
+ '_original_annotation',
849
+ '_final',
850
+ ):
851
+ continue
852
+ elif s == 'metadata' and not self.metadata:
853
+ continue
854
+ elif s == 'repr' and self.repr is True:
855
+ continue
856
+ if s == 'frozen' and self.frozen is False:
857
+ continue
858
+ if s == 'validation_alias' and self.validation_alias == self.alias:
859
+ continue
860
+ if s == 'serialization_alias' and self.serialization_alias == self.alias:
861
+ continue
862
+ if s == 'default' and self.default is not PydanticUndefined:
863
+ yield 'default', self.default
864
+ elif s == 'default_factory' and self.default_factory is not None:
865
+ yield 'default_factory', _repr.PlainRepr(_repr.display_as_type(self.default_factory))
866
+ else:
867
+ value = getattr(self, s)
868
+ if value is not None and value is not PydanticUndefined:
869
+ yield s, value
870
+
871
+
872
+ class _EmptyKwargs(TypedDict):
873
+ """This class exists solely to ensure that type checking warns about passing `**extra` in `Field`."""
874
+
875
+
876
+ _Attrs = {
877
+ 'default': ...,
878
+ 'default_factory': None,
879
+ 'alias': None,
880
+ 'alias_priority': None,
881
+ 'validation_alias': None,
882
+ 'serialization_alias': None,
883
+ 'title': None,
884
+ 'field_title_generator': None,
885
+ 'description': None,
886
+ 'examples': None,
887
+ 'exclude': None,
888
+ 'exclude_if': None,
889
+ 'discriminator': None,
890
+ 'deprecated': None,
891
+ 'json_schema_extra': None,
892
+ 'frozen': None,
893
+ 'validate_default': None,
894
+ 'repr': True,
895
+ 'init': None,
896
+ 'init_var': None,
897
+ 'kw_only': None,
898
+ }
899
+
900
+ _DefaultValues = {
901
+ **_Attrs,
902
+ 'kw_only': None,
903
+ 'pattern': None,
904
+ 'strict': None,
905
+ 'gt': None,
906
+ 'ge': None,
907
+ 'lt': None,
908
+ 'le': None,
909
+ 'multiple_of': None,
910
+ 'allow_inf_nan': None,
911
+ 'max_digits': None,
912
+ 'decimal_places': None,
913
+ 'min_length': None,
914
+ 'max_length': None,
915
+ 'coerce_numbers_to_str': None,
916
+ }
917
+
918
+
919
+ _T = TypeVar('_T')
920
+
921
+
922
+ # NOTE: Actual return type is 'FieldInfo', but we want to help type checkers
923
+ # to understand the magic that happens at runtime with the following overloads:
924
+ @overload # type hint the return value as `Any` to avoid type checking regressions when using `...`.
925
+ def Field(
926
+ default: ellipsis, # noqa: F821 # TODO: use `_typing_extra.EllipsisType` when we drop Py3.9
927
+ *,
928
+ alias: str | None = _Unset,
929
+ alias_priority: int | None = _Unset,
930
+ validation_alias: str | AliasPath | AliasChoices | None = _Unset,
931
+ serialization_alias: str | None = _Unset,
932
+ title: str | None = _Unset,
933
+ field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
934
+ description: str | None = _Unset,
935
+ examples: list[Any] | None = _Unset,
936
+ exclude: bool | None = _Unset,
937
+ exclude_if: Callable[[Any], bool] | None = _Unset,
938
+ discriminator: str | types.Discriminator | None = _Unset,
939
+ deprecated: Deprecated | str | bool | None = _Unset,
940
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
941
+ frozen: bool | None = _Unset,
942
+ validate_default: bool | None = _Unset,
943
+ repr: bool = _Unset,
944
+ init: bool | None = _Unset,
945
+ init_var: bool | None = _Unset,
946
+ kw_only: bool | None = _Unset,
947
+ pattern: str | re.Pattern[str] | None = _Unset,
948
+ strict: bool | None = _Unset,
949
+ coerce_numbers_to_str: bool | None = _Unset,
950
+ gt: annotated_types.SupportsGt | None = _Unset,
951
+ ge: annotated_types.SupportsGe | None = _Unset,
952
+ lt: annotated_types.SupportsLt | None = _Unset,
953
+ le: annotated_types.SupportsLe | None = _Unset,
954
+ multiple_of: float | None = _Unset,
955
+ allow_inf_nan: bool | None = _Unset,
956
+ max_digits: int | None = _Unset,
957
+ decimal_places: int | None = _Unset,
958
+ min_length: int | None = _Unset,
959
+ max_length: int | None = _Unset,
960
+ union_mode: Literal['smart', 'left_to_right'] = _Unset,
961
+ fail_fast: bool | None = _Unset,
962
+ **extra: Unpack[_EmptyKwargs],
963
+ ) -> Any: ...
964
+ @overload # `default` argument set, validate_default=True (no type checking on the default value)
965
+ def Field(
966
+ default: Any,
967
+ *,
968
+ alias: str | None = _Unset,
969
+ alias_priority: int | None = _Unset,
970
+ validation_alias: str | AliasPath | AliasChoices | None = _Unset,
971
+ serialization_alias: str | None = _Unset,
972
+ title: str | None = _Unset,
973
+ field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
974
+ description: str | None = _Unset,
975
+ examples: list[Any] | None = _Unset,
976
+ exclude: bool | None = _Unset,
977
+ exclude_if: Callable[[Any], bool] | None = _Unset,
978
+ discriminator: str | types.Discriminator | None = _Unset,
979
+ deprecated: Deprecated | str | bool | None = _Unset,
980
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
981
+ frozen: bool | None = _Unset,
982
+ validate_default: Literal[True],
983
+ repr: bool = _Unset,
984
+ init: bool | None = _Unset,
985
+ init_var: bool | None = _Unset,
986
+ kw_only: bool | None = _Unset,
987
+ pattern: str | re.Pattern[str] | None = _Unset,
988
+ strict: bool | None = _Unset,
989
+ coerce_numbers_to_str: bool | None = _Unset,
990
+ gt: annotated_types.SupportsGt | None = _Unset,
991
+ ge: annotated_types.SupportsGe | None = _Unset,
992
+ lt: annotated_types.SupportsLt | None = _Unset,
993
+ le: annotated_types.SupportsLe | None = _Unset,
994
+ multiple_of: float | None = _Unset,
995
+ allow_inf_nan: bool | None = _Unset,
996
+ max_digits: int | None = _Unset,
997
+ decimal_places: int | None = _Unset,
998
+ min_length: int | None = _Unset,
999
+ max_length: int | None = _Unset,
1000
+ union_mode: Literal['smart', 'left_to_right'] = _Unset,
1001
+ fail_fast: bool | None = _Unset,
1002
+ **extra: Unpack[_EmptyKwargs],
1003
+ ) -> Any: ...
1004
+ @overload # `default` argument set, validate_default=False or unset
1005
+ def Field(
1006
+ default: _T,
1007
+ *,
1008
+ alias: str | None = _Unset,
1009
+ alias_priority: int | None = _Unset,
1010
+ validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1011
+ serialization_alias: str | None = _Unset,
1012
+ title: str | None = _Unset,
1013
+ field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1014
+ description: str | None = _Unset,
1015
+ examples: list[Any] | None = _Unset,
1016
+ exclude: bool | None = _Unset,
1017
+ # NOTE: to get proper type checking on `exclude_if`'s argument, we could use `_T` instead of `Any`. However,
1018
+ # this requires (at least for pyright) adding an additional overload where `exclude_if` is required (otherwise
1019
+ # `a: int = Field(default_factory=str)` results in a false negative).
1020
+ exclude_if: Callable[[Any], bool] | None = _Unset,
1021
+ discriminator: str | types.Discriminator | None = _Unset,
1022
+ deprecated: Deprecated | str | bool | None = _Unset,
1023
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1024
+ frozen: bool | None = _Unset,
1025
+ validate_default: Literal[False] = ...,
1026
+ repr: bool = _Unset,
1027
+ init: bool | None = _Unset,
1028
+ init_var: bool | None = _Unset,
1029
+ kw_only: bool | None = _Unset,
1030
+ pattern: str | re.Pattern[str] | None = _Unset,
1031
+ strict: bool | None = _Unset,
1032
+ coerce_numbers_to_str: bool | None = _Unset,
1033
+ gt: annotated_types.SupportsGt | None = _Unset,
1034
+ ge: annotated_types.SupportsGe | None = _Unset,
1035
+ lt: annotated_types.SupportsLt | None = _Unset,
1036
+ le: annotated_types.SupportsLe | None = _Unset,
1037
+ multiple_of: float | None = _Unset,
1038
+ allow_inf_nan: bool | None = _Unset,
1039
+ max_digits: int | None = _Unset,
1040
+ decimal_places: int | None = _Unset,
1041
+ min_length: int | None = _Unset,
1042
+ max_length: int | None = _Unset,
1043
+ union_mode: Literal['smart', 'left_to_right'] = _Unset,
1044
+ fail_fast: bool | None = _Unset,
1045
+ **extra: Unpack[_EmptyKwargs],
1046
+ ) -> _T: ...
1047
+ @overload # `default_factory` argument set, validate_default=True (no type checking on the default value)
1048
+ def Field( # pyright: ignore[reportOverlappingOverload]
1049
+ *,
1050
+ default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any],
1051
+ alias: str | None = _Unset,
1052
+ alias_priority: int | None = _Unset,
1053
+ validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1054
+ serialization_alias: str | None = _Unset,
1055
+ title: str | None = _Unset,
1056
+ field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1057
+ description: str | None = _Unset,
1058
+ examples: list[Any] | None = _Unset,
1059
+ exclude: bool | None = _Unset,
1060
+ exclude_if: Callable[[Any], bool] | None = _Unset,
1061
+ discriminator: str | types.Discriminator | None = _Unset,
1062
+ deprecated: Deprecated | str | bool | None = _Unset,
1063
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1064
+ frozen: bool | None = _Unset,
1065
+ validate_default: Literal[True],
1066
+ repr: bool = _Unset,
1067
+ init: bool | None = _Unset,
1068
+ init_var: bool | None = _Unset,
1069
+ kw_only: bool | None = _Unset,
1070
+ pattern: str | re.Pattern[str] | None = _Unset,
1071
+ strict: bool | None = _Unset,
1072
+ coerce_numbers_to_str: bool | None = _Unset,
1073
+ gt: annotated_types.SupportsGt | None = _Unset,
1074
+ ge: annotated_types.SupportsGe | None = _Unset,
1075
+ lt: annotated_types.SupportsLt | None = _Unset,
1076
+ le: annotated_types.SupportsLe | None = _Unset,
1077
+ multiple_of: float | None = _Unset,
1078
+ allow_inf_nan: bool | None = _Unset,
1079
+ max_digits: int | None = _Unset,
1080
+ decimal_places: int | None = _Unset,
1081
+ min_length: int | None = _Unset,
1082
+ max_length: int | None = _Unset,
1083
+ union_mode: Literal['smart', 'left_to_right'] = _Unset,
1084
+ fail_fast: bool | None = _Unset,
1085
+ **extra: Unpack[_EmptyKwargs],
1086
+ ) -> Any: ...
1087
+ @overload # `default_factory` argument set, validate_default=False or unset
1088
+ def Field(
1089
+ *,
1090
+ default_factory: Callable[[], _T] | Callable[[dict[str, Any]], _T],
1091
+ alias: str | None = _Unset,
1092
+ alias_priority: int | None = _Unset,
1093
+ validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1094
+ serialization_alias: str | None = _Unset,
1095
+ title: str | None = _Unset,
1096
+ field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1097
+ description: str | None = _Unset,
1098
+ examples: list[Any] | None = _Unset,
1099
+ exclude: bool | None = _Unset,
1100
+ # NOTE: to get proper type checking on `exclude_if`'s argument, we could use `_T` instead of `Any`. However,
1101
+ # this requires (at least for pyright) adding an additional overload where `exclude_if` is required (otherwise
1102
+ # `a: int = Field(default_factory=str)` results in a false negative).
1103
+ exclude_if: Callable[[Any], bool] | None = _Unset,
1104
+ discriminator: str | types.Discriminator | None = _Unset,
1105
+ deprecated: Deprecated | str | bool | None = _Unset,
1106
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1107
+ frozen: bool | None = _Unset,
1108
+ validate_default: Literal[False] | None = _Unset,
1109
+ repr: bool = _Unset,
1110
+ init: bool | None = _Unset,
1111
+ init_var: bool | None = _Unset,
1112
+ kw_only: bool | None = _Unset,
1113
+ pattern: str | re.Pattern[str] | None = _Unset,
1114
+ strict: bool | None = _Unset,
1115
+ coerce_numbers_to_str: bool | None = _Unset,
1116
+ gt: annotated_types.SupportsGt | None = _Unset,
1117
+ ge: annotated_types.SupportsGe | None = _Unset,
1118
+ lt: annotated_types.SupportsLt | None = _Unset,
1119
+ le: annotated_types.SupportsLe | None = _Unset,
1120
+ multiple_of: float | None = _Unset,
1121
+ allow_inf_nan: bool | None = _Unset,
1122
+ max_digits: int | None = _Unset,
1123
+ decimal_places: int | None = _Unset,
1124
+ min_length: int | None = _Unset,
1125
+ max_length: int | None = _Unset,
1126
+ union_mode: Literal['smart', 'left_to_right'] = _Unset,
1127
+ fail_fast: bool | None = _Unset,
1128
+ **extra: Unpack[_EmptyKwargs],
1129
+ ) -> _T: ...
1130
+ @overload
1131
+ def Field( # No default set
1132
+ *,
1133
+ alias: str | None = _Unset,
1134
+ alias_priority: int | None = _Unset,
1135
+ validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1136
+ serialization_alias: str | None = _Unset,
1137
+ title: str | None = _Unset,
1138
+ field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1139
+ description: str | None = _Unset,
1140
+ examples: list[Any] | None = _Unset,
1141
+ exclude: bool | None = _Unset,
1142
+ exclude_if: Callable[[Any], bool] | None = _Unset,
1143
+ discriminator: str | types.Discriminator | None = _Unset,
1144
+ deprecated: Deprecated | str | bool | None = _Unset,
1145
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1146
+ frozen: bool | None = _Unset,
1147
+ validate_default: bool | None = _Unset,
1148
+ repr: bool = _Unset,
1149
+ init: bool | None = _Unset,
1150
+ init_var: bool | None = _Unset,
1151
+ kw_only: bool | None = _Unset,
1152
+ pattern: str | re.Pattern[str] | None = _Unset,
1153
+ strict: bool | None = _Unset,
1154
+ coerce_numbers_to_str: bool | None = _Unset,
1155
+ gt: annotated_types.SupportsGt | None = _Unset,
1156
+ ge: annotated_types.SupportsGe | None = _Unset,
1157
+ lt: annotated_types.SupportsLt | None = _Unset,
1158
+ le: annotated_types.SupportsLe | None = _Unset,
1159
+ multiple_of: float | None = _Unset,
1160
+ allow_inf_nan: bool | None = _Unset,
1161
+ max_digits: int | None = _Unset,
1162
+ decimal_places: int | None = _Unset,
1163
+ min_length: int | None = _Unset,
1164
+ max_length: int | None = _Unset,
1165
+ union_mode: Literal['smart', 'left_to_right'] = _Unset,
1166
+ fail_fast: bool | None = _Unset,
1167
+ **extra: Unpack[_EmptyKwargs],
1168
+ ) -> Any: ...
1169
+ def Field( # noqa: C901
1170
+ default: Any = PydanticUndefined,
1171
+ *,
1172
+ default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None = _Unset,
1173
+ alias: str | None = _Unset,
1174
+ alias_priority: int | None = _Unset,
1175
+ validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1176
+ serialization_alias: str | None = _Unset,
1177
+ title: str | None = _Unset,
1178
+ field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1179
+ description: str | None = _Unset,
1180
+ examples: list[Any] | None = _Unset,
1181
+ exclude: bool | None = _Unset,
1182
+ exclude_if: Callable[[Any], bool] | None = _Unset,
1183
+ discriminator: str | types.Discriminator | None = _Unset,
1184
+ deprecated: Deprecated | str | bool | None = _Unset,
1185
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1186
+ frozen: bool | None = _Unset,
1187
+ validate_default: bool | None = _Unset,
1188
+ repr: bool = _Unset,
1189
+ init: bool | None = _Unset,
1190
+ init_var: bool | None = _Unset,
1191
+ kw_only: bool | None = _Unset,
1192
+ pattern: str | re.Pattern[str] | None = _Unset,
1193
+ strict: bool | None = _Unset,
1194
+ coerce_numbers_to_str: bool | None = _Unset,
1195
+ gt: annotated_types.SupportsGt | None = _Unset,
1196
+ ge: annotated_types.SupportsGe | None = _Unset,
1197
+ lt: annotated_types.SupportsLt | None = _Unset,
1198
+ le: annotated_types.SupportsLe | None = _Unset,
1199
+ multiple_of: float | None = _Unset,
1200
+ allow_inf_nan: bool | None = _Unset,
1201
+ max_digits: int | None = _Unset,
1202
+ decimal_places: int | None = _Unset,
1203
+ min_length: int | None = _Unset,
1204
+ max_length: int | None = _Unset,
1205
+ union_mode: Literal['smart', 'left_to_right'] = _Unset,
1206
+ fail_fast: bool | None = _Unset,
1207
+ **extra: Unpack[_EmptyKwargs],
1208
+ ) -> Any:
1209
+ """!!! abstract "Usage Documentation"
1210
+ [Fields](../concepts/fields.md)
1211
+
1212
+ Create a field for objects that can be configured.
1213
+
1214
+ Used to provide extra information about a field, either for the model schema or complex validation. Some arguments
1215
+ apply only to number fields (`int`, `float`, `Decimal`) and some apply only to `str`.
1216
+
1217
+ Note:
1218
+ - Any `_Unset` objects will be replaced by the corresponding value defined in the `_DefaultValues` dictionary. If a key for the `_Unset` object is not found in the `_DefaultValues` dictionary, it will default to `None`
1219
+
1220
+ Args:
1221
+ default: Default value if the field is not set.
1222
+ default_factory: A callable to generate the default value. The callable can either take 0 arguments
1223
+ (in which case it is called as is) or a single argument containing the already validated data.
1224
+ alias: The name to use for the attribute when validating or serializing by alias.
1225
+ This is often used for things like converting between snake and camel case.
1226
+ alias_priority: Priority of the alias. This affects whether an alias generator is used.
1227
+ validation_alias: Like `alias`, but only affects validation, not serialization.
1228
+ serialization_alias: Like `alias`, but only affects serialization, not validation.
1229
+ title: Human-readable title.
1230
+ field_title_generator: A callable that takes a field name and returns title for it.
1231
+ description: Human-readable description.
1232
+ examples: Example values for this field.
1233
+ exclude: Whether to exclude the field from the model serialization.
1234
+ exclude_if: A callable that determines whether to exclude a field during serialization based on its value.
1235
+ discriminator: Field name or Discriminator for discriminating the type in a tagged union.
1236
+ deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport,
1237
+ or a boolean. If `True`, a default deprecation message will be emitted when accessing the field.
1238
+ json_schema_extra: A dict or callable to provide extra JSON schema properties.
1239
+ frozen: Whether the field is frozen. If true, attempts to change the value on an instance will raise an error.
1240
+ validate_default: If `True`, apply validation to the default value every time you create an instance.
1241
+ Otherwise, for performance reasons, the default value of the field is trusted and not validated.
1242
+ repr: A boolean indicating whether to include the field in the `__repr__` output.
1243
+ init: Whether the field should be included in the constructor of the dataclass.
1244
+ (Only applies to dataclasses.)
1245
+ init_var: Whether the field should _only_ be included in the constructor of the dataclass.
1246
+ (Only applies to dataclasses.)
1247
+ kw_only: Whether the field should be a keyword-only argument in the constructor of the dataclass.
1248
+ (Only applies to dataclasses.)
1249
+ coerce_numbers_to_str: Whether to enable coercion of any `Number` type to `str` (not applicable in `strict` mode).
1250
+ strict: If `True`, strict validation is applied to the field.
1251
+ See [Strict Mode](../concepts/strict_mode.md) for details.
1252
+ gt: Greater than. If set, value must be greater than this. Only applicable to numbers.
1253
+ ge: Greater than or equal. If set, value must be greater than or equal to this. Only applicable to numbers.
1254
+ lt: Less than. If set, value must be less than this. Only applicable to numbers.
1255
+ le: Less than or equal. If set, value must be less than or equal to this. Only applicable to numbers.
1256
+ multiple_of: Value must be a multiple of this. Only applicable to numbers.
1257
+ min_length: Minimum length for iterables.
1258
+ max_length: Maximum length for iterables.
1259
+ pattern: Pattern for strings (a regular expression).
1260
+ allow_inf_nan: Allow `inf`, `-inf`, `nan`. Only applicable to float and [`Decimal`][decimal.Decimal] numbers.
1261
+ max_digits: Maximum number of allow digits for strings.
1262
+ decimal_places: Maximum number of decimal places allowed for numbers.
1263
+ union_mode: The strategy to apply when validating a union. Can be `smart` (the default), or `left_to_right`.
1264
+ See [Union Mode](../concepts/unions.md#union-modes) for details.
1265
+ fail_fast: If `True`, validation will stop on the first error. If `False`, all validation errors will be collected.
1266
+ This option can be applied only to iterable types (list, tuple, set, and frozenset).
1267
+ extra: (Deprecated) Extra fields that will be included in the JSON schema.
1268
+
1269
+ !!! warning Deprecated
1270
+ The `extra` kwargs is deprecated. Use `json_schema_extra` instead.
1271
+
1272
+ Returns:
1273
+ A new [`FieldInfo`][pydantic.fields.FieldInfo]. The return annotation is `Any` so `Field` can be used on
1274
+ type-annotated fields without causing a type error.
1275
+ """
1276
+ # Check deprecated and removed params from V1. This logic should eventually be removed.
1277
+ const = extra.pop('const', None) # type: ignore
1278
+ if const is not None:
1279
+ raise PydanticUserError('`const` is removed, use `Literal` instead', code='removed-kwargs')
1280
+
1281
+ min_items = extra.pop('min_items', None) # type: ignore
1282
+ if min_items is not None:
1283
+ warn(
1284
+ '`min_items` is deprecated and will be removed, use `min_length` instead',
1285
+ PydanticDeprecatedSince20,
1286
+ stacklevel=2,
1287
+ )
1288
+ if min_length in (None, _Unset):
1289
+ min_length = min_items # type: ignore
1290
+
1291
+ max_items = extra.pop('max_items', None) # type: ignore
1292
+ if max_items is not None:
1293
+ warn(
1294
+ '`max_items` is deprecated and will be removed, use `max_length` instead',
1295
+ PydanticDeprecatedSince20,
1296
+ stacklevel=2,
1297
+ )
1298
+ if max_length in (None, _Unset):
1299
+ max_length = max_items # type: ignore
1300
+
1301
+ unique_items = extra.pop('unique_items', None) # type: ignore
1302
+ if unique_items is not None:
1303
+ raise PydanticUserError(
1304
+ (
1305
+ '`unique_items` is removed, use `Set` instead'
1306
+ '(this feature is discussed in https://github.com/pydantic/pydantic-core/issues/296)'
1307
+ ),
1308
+ code='removed-kwargs',
1309
+ )
1310
+
1311
+ allow_mutation = extra.pop('allow_mutation', None) # type: ignore
1312
+ if allow_mutation is not None:
1313
+ warn(
1314
+ '`allow_mutation` is deprecated and will be removed. use `frozen` instead',
1315
+ PydanticDeprecatedSince20,
1316
+ stacklevel=2,
1317
+ )
1318
+ if allow_mutation is False:
1319
+ frozen = True
1320
+
1321
+ regex = extra.pop('regex', None) # type: ignore
1322
+ if regex is not None:
1323
+ raise PydanticUserError('`regex` is removed. use `pattern` instead', code='removed-kwargs')
1324
+
1325
+ if extra:
1326
+ warn(
1327
+ 'Using extra keyword arguments on `Field` is deprecated and will be removed.'
1328
+ ' Use `json_schema_extra` instead.'
1329
+ f' (Extra keys: {", ".join(k.__repr__() for k in extra.keys())})',
1330
+ PydanticDeprecatedSince20,
1331
+ stacklevel=2,
1332
+ )
1333
+ if not json_schema_extra or json_schema_extra is _Unset:
1334
+ json_schema_extra = extra # type: ignore
1335
+
1336
+ if (
1337
+ validation_alias
1338
+ and validation_alias is not _Unset
1339
+ and not isinstance(validation_alias, (str, AliasChoices, AliasPath))
1340
+ ):
1341
+ raise TypeError('Invalid `validation_alias` type. it should be `str`, `AliasChoices`, or `AliasPath`')
1342
+
1343
+ if serialization_alias in (_Unset, None) and isinstance(alias, str):
1344
+ serialization_alias = alias
1345
+
1346
+ if validation_alias in (_Unset, None):
1347
+ validation_alias = alias
1348
+
1349
+ include = extra.pop('include', None) # type: ignore
1350
+ if include is not None:
1351
+ warn(
1352
+ '`include` is deprecated and does nothing. It will be removed, use `exclude` instead',
1353
+ PydanticDeprecatedSince20,
1354
+ stacklevel=2,
1355
+ )
1356
+
1357
+ return FieldInfo.from_field(
1358
+ default,
1359
+ default_factory=default_factory,
1360
+ alias=alias,
1361
+ alias_priority=alias_priority,
1362
+ validation_alias=validation_alias,
1363
+ serialization_alias=serialization_alias,
1364
+ title=title,
1365
+ field_title_generator=field_title_generator,
1366
+ description=description,
1367
+ examples=examples,
1368
+ exclude=exclude,
1369
+ exclude_if=exclude_if,
1370
+ discriminator=discriminator,
1371
+ deprecated=deprecated,
1372
+ json_schema_extra=json_schema_extra,
1373
+ frozen=frozen,
1374
+ pattern=pattern,
1375
+ validate_default=validate_default,
1376
+ repr=repr,
1377
+ init=init,
1378
+ init_var=init_var,
1379
+ kw_only=kw_only,
1380
+ coerce_numbers_to_str=coerce_numbers_to_str,
1381
+ strict=strict,
1382
+ gt=gt,
1383
+ ge=ge,
1384
+ lt=lt,
1385
+ le=le,
1386
+ multiple_of=multiple_of,
1387
+ min_length=min_length,
1388
+ max_length=max_length,
1389
+ allow_inf_nan=allow_inf_nan,
1390
+ max_digits=max_digits,
1391
+ decimal_places=decimal_places,
1392
+ union_mode=union_mode,
1393
+ fail_fast=fail_fast,
1394
+ )
1395
+
1396
+
1397
+ _FIELD_ARG_NAMES = set(inspect.signature(Field).parameters)
1398
+ _FIELD_ARG_NAMES.remove('extra') # do not include the varkwargs parameter
1399
+
1400
+
1401
+ class ModelPrivateAttr(_repr.Representation):
1402
+ """A descriptor for private attributes in class models.
1403
+
1404
+ !!! warning
1405
+ You generally shouldn't be creating `ModelPrivateAttr` instances directly, instead use
1406
+ `pydantic.fields.PrivateAttr`. (This is similar to `FieldInfo` vs. `Field`.)
1407
+
1408
+ Attributes:
1409
+ default: The default value of the attribute if not provided.
1410
+ default_factory: A callable to generate the default value. The callable can either take 0 arguments
1411
+ (in which case it is called as is) or a single argument containing the validated data (the model's
1412
+ [`__dict__`][object.__dict__]) and the already initialized private attributes.
1413
+ """
1414
+
1415
+ __slots__ = ('default', 'default_factory')
1416
+
1417
+ def __init__(
1418
+ self,
1419
+ default: Any = PydanticUndefined,
1420
+ *,
1421
+ default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None = None,
1422
+ ) -> None:
1423
+ if default is Ellipsis:
1424
+ self.default = PydanticUndefined
1425
+ else:
1426
+ self.default = default
1427
+ self.default_factory = default_factory
1428
+
1429
+ if not TYPE_CHECKING:
1430
+ # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access
1431
+
1432
+ def __getattr__(self, item: str) -> Any:
1433
+ """This function improves compatibility with custom descriptors by ensuring delegation happens
1434
+ as expected when the default value of a private attribute is a descriptor.
1435
+ """
1436
+ if item in {'__get__', '__set__', '__delete__'}:
1437
+ if hasattr(self.default, item):
1438
+ return getattr(self.default, item)
1439
+ raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')
1440
+
1441
+ def __set_name__(self, cls: type[Any], name: str) -> None:
1442
+ """Preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487."""
1443
+ default = self.default
1444
+ if default is PydanticUndefined:
1445
+ return
1446
+ set_name = getattr(default, '__set_name__', None)
1447
+ if callable(set_name):
1448
+ set_name(cls, name)
1449
+
1450
+ @property
1451
+ def default_factory_takes_validated_data(self) -> bool | None:
1452
+ """Whether the provided default factory callable has a validated data parameter.
1453
+
1454
+ Returns `None` if no default factory is set.
1455
+ """
1456
+ if self.default_factory is not None:
1457
+ return _fields.takes_validated_data_argument(self.default_factory)
1458
+
1459
+ @overload
1460
+ def get_default(
1461
+ self, *, call_default_factory: Literal[True], validated_data: dict[str, Any] | None = None
1462
+ ) -> Any: ...
1463
+
1464
+ @overload
1465
+ def get_default(self, *, call_default_factory: Literal[False] = ...) -> Any: ...
1466
+
1467
+ def get_default(self, *, call_default_factory: bool = False, validated_data: dict[str, Any] | None = None) -> Any:
1468
+ """Get the default value.
1469
+
1470
+ We expose an option for whether to call the default_factory (if present), as calling it may
1471
+ result in side effects that we want to avoid. However, there are times when it really should
1472
+ be called (namely, when instantiating a model via `model_construct`).
1473
+
1474
+ Args:
1475
+ call_default_factory: Whether to call the default factory or not.
1476
+ validated_data: The already validated data to be passed to the default factory.
1477
+
1478
+ Returns:
1479
+ The default value, calling the default factory if requested or `None` if not set.
1480
+ """
1481
+ return _fields.resolve_default_value(
1482
+ default=self.default,
1483
+ default_factory=self.default_factory,
1484
+ validated_data=validated_data,
1485
+ call_default_factory=call_default_factory,
1486
+ )
1487
+
1488
+ def __eq__(self, other: Any) -> bool:
1489
+ return isinstance(other, self.__class__) and (self.default, self.default_factory) == (
1490
+ other.default,
1491
+ other.default_factory,
1492
+ )
1493
+
1494
+
1495
+ # NOTE: Actual return type is 'ModelPrivateAttr', but we want to help type checkers
1496
+ # to understand the magic that happens at runtime.
1497
+ @overload # `default` argument set
1498
+ def PrivateAttr(
1499
+ default: _T,
1500
+ *,
1501
+ init: Literal[False] = False,
1502
+ ) -> _T: ...
1503
+ @overload # `default_factory` argument set
1504
+ def PrivateAttr(
1505
+ *,
1506
+ default_factory: Callable[[], _T] | Callable[[dict[str, Any]], _T],
1507
+ init: Literal[False] = False,
1508
+ ) -> _T: ...
1509
+ @overload # No default set
1510
+ def PrivateAttr(
1511
+ *,
1512
+ init: Literal[False] = False,
1513
+ ) -> Any: ...
1514
+ def PrivateAttr(
1515
+ default: Any = PydanticUndefined,
1516
+ *,
1517
+ default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None = None,
1518
+ init: Literal[False] = False,
1519
+ ) -> Any:
1520
+ """!!! abstract "Usage Documentation"
1521
+ [Private Model Attributes](../concepts/models.md#private-model-attributes)
1522
+
1523
+ Indicates that an attribute is intended for private use and not handled during normal validation/serialization.
1524
+
1525
+ Private attributes are not validated by Pydantic, so it's up to you to ensure they are used in a type-safe manner.
1526
+
1527
+ Private attributes are stored in `__private_attributes__` on the model.
1528
+
1529
+ Args:
1530
+ default: The attribute's default value. Defaults to Undefined.
1531
+ default_factory: A callable to generate the default value. The callable can either take 0 arguments
1532
+ (in which case it is called as is) or a single argument containing the validated data (the model's
1533
+ [`__dict__`][object.__dict__]) and the already initialized private attributes.
1534
+ If both `default` and `default_factory` are set, an error will be raised.
1535
+ init: Whether the attribute should be included in the constructor of the dataclass. Always `False`.
1536
+
1537
+ Returns:
1538
+ An instance of [`ModelPrivateAttr`][pydantic.fields.ModelPrivateAttr] class.
1539
+
1540
+ Raises:
1541
+ ValueError: If both `default` and `default_factory` are set.
1542
+ """
1543
+ if default is not PydanticUndefined and default_factory is not None:
1544
+ raise TypeError('cannot specify both default and default_factory')
1545
+
1546
+ return ModelPrivateAttr(
1547
+ default,
1548
+ default_factory=default_factory,
1549
+ )
1550
+
1551
+
1552
+ @dataclasses.dataclass(**_internal_dataclass.slots_true)
1553
+ class ComputedFieldInfo:
1554
+ """A container for data from `@computed_field` so that we can access it while building the pydantic-core schema.
1555
+
1556
+ Attributes:
1557
+ decorator_repr: A class variable representing the decorator string, '@computed_field'.
1558
+ wrapped_property: The wrapped computed field property.
1559
+ return_type: The type of the computed field property's return value.
1560
+ alias: The alias of the property to be used during serialization.
1561
+ alias_priority: The priority of the alias. This affects whether an alias generator is used.
1562
+ title: Title of the computed field to include in the serialization JSON schema.
1563
+ field_title_generator: A callable that takes a field name and returns title for it.
1564
+ description: Description of the computed field to include in the serialization JSON schema.
1565
+ deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport,
1566
+ or a boolean. If `True`, a default deprecation message will be emitted when accessing the field.
1567
+ examples: Example values of the computed field to include in the serialization JSON schema.
1568
+ json_schema_extra: A dict or callable to provide extra JSON schema properties.
1569
+ repr: A boolean indicating whether to include the field in the __repr__ output.
1570
+ """
1571
+
1572
+ decorator_repr: ClassVar[str] = '@computed_field'
1573
+ wrapped_property: property
1574
+ return_type: Any
1575
+ alias: str | None
1576
+ alias_priority: int | None
1577
+ exclude_if: Callable[[Any], bool] | None
1578
+ title: str | None
1579
+ field_title_generator: Callable[[str, ComputedFieldInfo], str] | None
1580
+ description: str | None
1581
+ deprecated: Deprecated | str | bool | None
1582
+ examples: list[Any] | None
1583
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None
1584
+ repr: bool
1585
+ # NOTE: if you add a new field, add it to the `__copy__()` implementation.
1586
+
1587
+ def __copy__(self) -> Self:
1588
+ return type(self)(
1589
+ wrapped_property=self.wrapped_property,
1590
+ return_type=self.return_type,
1591
+ alias=self.alias,
1592
+ alias_priority=self.alias_priority,
1593
+ exclude_if=self.exclude_if,
1594
+ title=self.title,
1595
+ field_title_generator=self.field_title_generator,
1596
+ description=self.description,
1597
+ deprecated=self.deprecated,
1598
+ examples=self.examples.copy() if isinstance(self.examples, list) else self.examples,
1599
+ json_schema_extra=self.json_schema_extra.copy()
1600
+ if isinstance(self.json_schema_extra, dict)
1601
+ else self.json_schema_extra,
1602
+ repr=self.repr,
1603
+ )
1604
+
1605
+ @property
1606
+ def deprecation_message(self) -> str | None:
1607
+ """The deprecation message to be emitted, or `None` if not set."""
1608
+ if self.deprecated is None:
1609
+ return None
1610
+ if isinstance(self.deprecated, bool):
1611
+ return 'deprecated' if self.deprecated else None
1612
+ return self.deprecated if isinstance(self.deprecated, str) else self.deprecated.message
1613
+
1614
+ def _update_from_config(self, config_wrapper: ConfigWrapper, name: str) -> None:
1615
+ """Update the instance from the configuration set on the class this computed field belongs to."""
1616
+ title_generator = self.field_title_generator or config_wrapper.field_title_generator
1617
+ if title_generator is not None and self.title is None:
1618
+ self.title = title_generator(name, self)
1619
+ if config_wrapper.alias_generator is not None:
1620
+ self._apply_alias_generator(config_wrapper.alias_generator, name)
1621
+
1622
+ def _apply_alias_generator(self, alias_generator: Callable[[str], str] | AliasGenerator, name: str) -> None:
1623
+ """Apply an alias generator to aliases if appropriate.
1624
+
1625
+ Args:
1626
+ alias_generator: A callable that takes a string and returns a string, or an `AliasGenerator` instance.
1627
+ name: The name of the computed field from which to generate the alias.
1628
+ """
1629
+ # Apply an alias_generator if
1630
+ # 1. An alias is not specified
1631
+ # 2. An alias is specified, but the priority is <= 1
1632
+
1633
+ if self.alias_priority is None or self.alias_priority <= 1 or self.alias is None:
1634
+ alias, _, serialization_alias = None, None, None
1635
+
1636
+ if isinstance(alias_generator, AliasGenerator):
1637
+ alias, _, serialization_alias = alias_generator.generate_aliases(name)
1638
+ elif callable(alias_generator):
1639
+ alias = alias_generator(name)
1640
+
1641
+ # if priority is not set, we set to 1
1642
+ # which supports the case where the alias_generator from a child class is used
1643
+ # to generate an alias for a field in a parent class
1644
+ if self.alias_priority is None or self.alias_priority <= 1:
1645
+ self.alias_priority = 1
1646
+
1647
+ # if the priority is 1, then we set the aliases to the generated alias
1648
+ # note that we use the serialization_alias with priority over alias, as computed_field
1649
+ # aliases are used for serialization only (not validation)
1650
+ if self.alias_priority == 1:
1651
+ self.alias = _utils.get_first_not_none(serialization_alias, alias)
1652
+
1653
+
1654
+ def _wrapped_property_is_private(property_: cached_property | property) -> bool: # type: ignore
1655
+ """Returns true if provided property is private, False otherwise."""
1656
+ wrapped_name: str = ''
1657
+
1658
+ if isinstance(property_, property):
1659
+ wrapped_name = getattr(property_.fget, '__name__', '')
1660
+ elif isinstance(property_, cached_property): # type: ignore
1661
+ wrapped_name = getattr(property_.func, '__name__', '') # type: ignore
1662
+
1663
+ return wrapped_name.startswith('_') and not wrapped_name.startswith('__')
1664
+
1665
+
1666
+ # this should really be `property[T], cached_property[T]` but property is not generic unlike cached_property
1667
+ # See https://github.com/python/typing/issues/985 and linked issues
1668
+ PropertyT = TypeVar('PropertyT')
1669
+
1670
+
1671
+ @overload
1672
+ def computed_field(func: PropertyT, /) -> PropertyT: ...
1673
+
1674
+
1675
+ @overload
1676
+ def computed_field(
1677
+ *,
1678
+ alias: str | None = None,
1679
+ alias_priority: int | None = None,
1680
+ exclude_if: Callable[[Any], bool] | None = None,
1681
+ title: str | None = None,
1682
+ field_title_generator: Callable[[str, ComputedFieldInfo], str] | None = None,
1683
+ description: str | None = None,
1684
+ deprecated: Deprecated | str | bool | None = None,
1685
+ examples: list[Any] | None = None,
1686
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = None,
1687
+ repr: bool = True,
1688
+ return_type: Any = PydanticUndefined,
1689
+ ) -> Callable[[PropertyT], PropertyT]: ...
1690
+
1691
+
1692
+ def computed_field(
1693
+ func: PropertyT | None = None,
1694
+ /,
1695
+ *,
1696
+ alias: str | None = None,
1697
+ alias_priority: int | None = None,
1698
+ exclude_if: Callable[[Any], bool] | None = None,
1699
+ title: str | None = None,
1700
+ field_title_generator: Callable[[str, ComputedFieldInfo], str] | None = None,
1701
+ description: str | None = None,
1702
+ deprecated: Deprecated | str | bool | None = None,
1703
+ examples: list[Any] | None = None,
1704
+ json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = None,
1705
+ repr: bool | None = None,
1706
+ return_type: Any = PydanticUndefined,
1707
+ ) -> PropertyT | Callable[[PropertyT], PropertyT]:
1708
+ """!!! abstract "Usage Documentation"
1709
+ [The `computed_field` decorator](../concepts/fields.md#the-computed_field-decorator)
1710
+
1711
+ Decorator to include `property` and `cached_property` when serializing models or dataclasses.
1712
+
1713
+ This is useful for fields that are computed from other fields, or for fields that are expensive to compute and should be cached.
1714
+
1715
+ ```python
1716
+ from pydantic import BaseModel, computed_field
1717
+
1718
+ class Rectangle(BaseModel):
1719
+ width: int
1720
+ length: int
1721
+
1722
+ @computed_field
1723
+ @property
1724
+ def area(self) -> int:
1725
+ return self.width * self.length
1726
+
1727
+ print(Rectangle(width=3, length=2).model_dump())
1728
+ #> {'width': 3, 'length': 2, 'area': 6}
1729
+ ```
1730
+
1731
+ If applied to functions not yet decorated with `@property` or `@cached_property`, the function is
1732
+ automatically wrapped with `property`. Although this is more concise, you will lose IntelliSense in your IDE,
1733
+ and confuse static type checkers, thus explicit use of `@property` is recommended.
1734
+
1735
+ !!! warning "Mypy Warning"
1736
+ Even with the `@property` or `@cached_property` applied to your function before `@computed_field`,
1737
+ mypy may throw a `Decorated property not supported` error.
1738
+ See [mypy issue #1362](https://github.com/python/mypy/issues/1362), for more information.
1739
+ To avoid this error message, add `# type: ignore[prop-decorator]` to the `@computed_field` line.
1740
+
1741
+ [pyright](https://github.com/microsoft/pyright) supports `@computed_field` without error.
1742
+
1743
+ ```python
1744
+ import random
1745
+
1746
+ from pydantic import BaseModel, computed_field
1747
+
1748
+ class Square(BaseModel):
1749
+ width: float
1750
+
1751
+ @computed_field
1752
+ def area(self) -> float: # converted to a `property` by `computed_field`
1753
+ return round(self.width**2, 2)
1754
+
1755
+ @area.setter
1756
+ def area(self, new_area: float) -> None:
1757
+ self.width = new_area**0.5
1758
+
1759
+ @computed_field(alias='the magic number', repr=False)
1760
+ def random_number(self) -> int:
1761
+ return random.randint(0, 1_000)
1762
+
1763
+ square = Square(width=1.3)
1764
+
1765
+ # `random_number` does not appear in representation
1766
+ print(repr(square))
1767
+ #> Square(width=1.3, area=1.69)
1768
+
1769
+ print(square.random_number)
1770
+ #> 3
1771
+
1772
+ square.area = 4
1773
+
1774
+ print(square.model_dump_json(by_alias=True))
1775
+ #> {"width":2.0,"area":4.0,"the magic number":3}
1776
+ ```
1777
+
1778
+ !!! warning "Overriding with `computed_field`"
1779
+ You can't override a field from a parent class with a `computed_field` in the child class.
1780
+ `mypy` complains about this behavior if allowed, and `dataclasses` doesn't allow this pattern either.
1781
+ See the example below:
1782
+
1783
+ ```python
1784
+ from pydantic import BaseModel, computed_field
1785
+
1786
+ class Parent(BaseModel):
1787
+ a: str
1788
+
1789
+ try:
1790
+
1791
+ class Child(Parent):
1792
+ @computed_field
1793
+ @property
1794
+ def a(self) -> str:
1795
+ return 'new a'
1796
+
1797
+ except TypeError as e:
1798
+ print(e)
1799
+ '''
1800
+ Field 'a' of class 'Child' overrides symbol of same name in a parent class. This override with a computed_field is incompatible.
1801
+ '''
1802
+ ```
1803
+
1804
+ Private properties decorated with `@computed_field` have `repr=False` by default.
1805
+
1806
+ ```python
1807
+ from functools import cached_property
1808
+
1809
+ from pydantic import BaseModel, computed_field
1810
+
1811
+ class Model(BaseModel):
1812
+ foo: int
1813
+
1814
+ @computed_field
1815
+ @cached_property
1816
+ def _private_cached_property(self) -> int:
1817
+ return -self.foo
1818
+
1819
+ @computed_field
1820
+ @property
1821
+ def _private_property(self) -> int:
1822
+ return -self.foo
1823
+
1824
+ m = Model(foo=1)
1825
+ print(repr(m))
1826
+ #> Model(foo=1)
1827
+ ```
1828
+
1829
+ Args:
1830
+ func: the function to wrap.
1831
+ alias: alias to use when serializing this computed field, only used when `by_alias=True`
1832
+ alias_priority: priority of the alias. This affects whether an alias generator is used
1833
+ exclude_if: A callable that determines whether to exclude this computed field during serialization based on its value.
1834
+ title: Title to use when including this computed field in JSON Schema
1835
+ field_title_generator: A callable that takes a field name and returns title for it.
1836
+ description: Description to use when including this computed field in JSON Schema, defaults to the function's
1837
+ docstring
1838
+ deprecated: A deprecation message (or an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport).
1839
+ to be emitted when accessing the field. Or a boolean. This will automatically be set if the property is decorated with the
1840
+ `deprecated` decorator.
1841
+ examples: Example values to use when including this computed field in JSON Schema
1842
+ json_schema_extra: A dict or callable to provide extra JSON schema properties.
1843
+ repr: whether to include this computed field in model repr.
1844
+ Default is `False` for private properties and `True` for public properties.
1845
+ return_type: optional return for serialization logic to expect when serializing to JSON, if included
1846
+ this must be correct, otherwise a `TypeError` is raised.
1847
+ If you don't include a return type Any is used, which does runtime introspection to handle arbitrary
1848
+ objects.
1849
+
1850
+ Returns:
1851
+ A proxy wrapper for the property.
1852
+ """
1853
+
1854
+ def dec(f: Any) -> Any:
1855
+ nonlocal description, deprecated, return_type, alias_priority
1856
+ unwrapped = _decorators.unwrap_wrapped_function(f)
1857
+
1858
+ if description is None and unwrapped.__doc__:
1859
+ description = inspect.cleandoc(unwrapped.__doc__)
1860
+
1861
+ if deprecated is None and hasattr(unwrapped, '__deprecated__'):
1862
+ deprecated = unwrapped.__deprecated__
1863
+
1864
+ # if the function isn't already decorated with `@property` (or another descriptor), then we wrap it now
1865
+ f = _decorators.ensure_property(f)
1866
+ alias_priority = (alias_priority or 2) if alias is not None else None
1867
+
1868
+ if repr is None:
1869
+ repr_: bool = not _wrapped_property_is_private(property_=f)
1870
+ else:
1871
+ repr_ = repr
1872
+
1873
+ dec_info = ComputedFieldInfo(
1874
+ f,
1875
+ return_type,
1876
+ alias,
1877
+ alias_priority,
1878
+ exclude_if,
1879
+ title,
1880
+ field_title_generator,
1881
+ description,
1882
+ deprecated,
1883
+ examples,
1884
+ json_schema_extra,
1885
+ repr_,
1886
+ )
1887
+ return _decorators.PydanticDescriptorProxy(f, dec_info)
1888
+
1889
+ if func is None:
1890
+ return dec
1891
+ else:
1892
+ return dec(func)
.mcp-venv/lib/python3.13/site-packages/pydantic/functional_serializers.py ADDED
@@ -0,0 +1,470 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """This module contains related classes and functions for serialization."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ from functools import partial, partialmethod
7
+ from typing import TYPE_CHECKING, Annotated, Any, Callable, Literal, TypeVar, overload
8
+
9
+ from pydantic_core import PydanticUndefined, core_schema
10
+ from pydantic_core.core_schema import SerializationInfo, SerializerFunctionWrapHandler, WhenUsed
11
+ from typing_extensions import TypeAlias
12
+
13
+ from . import PydanticUndefinedAnnotation
14
+ from ._internal import _decorators, _internal_dataclass
15
+ from .annotated_handlers import GetCoreSchemaHandler
16
+ from .errors import PydanticUserError
17
+
18
+
19
+ @dataclasses.dataclass(**_internal_dataclass.slots_true, frozen=True)
20
+ class PlainSerializer:
21
+ """Plain serializers use a function to modify the output of serialization.
22
+
23
+ This is particularly helpful when you want to customize the serialization for annotated types.
24
+ Consider an input of `list`, which will be serialized into a space-delimited string.
25
+
26
+ ```python
27
+ from typing import Annotated
28
+
29
+ from pydantic import BaseModel, PlainSerializer
30
+
31
+ CustomStr = Annotated[
32
+ list, PlainSerializer(lambda x: ' '.join(x), return_type=str)
33
+ ]
34
+
35
+ class StudentModel(BaseModel):
36
+ courses: CustomStr
37
+
38
+ student = StudentModel(courses=['Math', 'Chemistry', 'English'])
39
+ print(student.model_dump())
40
+ #> {'courses': 'Math Chemistry English'}
41
+ ```
42
+
43
+ Attributes:
44
+ func: The serializer function.
45
+ return_type: The return type for the function. If omitted it will be inferred from the type annotation.
46
+ when_used: Determines when this serializer should be used. Accepts a string with values `'always'`,
47
+ `'unless-none'`, `'json'`, and `'json-unless-none'`. Defaults to 'always'.
48
+ """
49
+
50
+ func: core_schema.SerializerFunction
51
+ return_type: Any = PydanticUndefined
52
+ when_used: WhenUsed = 'always'
53
+
54
+ def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
55
+ """Gets the Pydantic core schema.
56
+
57
+ Args:
58
+ source_type: The source type.
59
+ handler: The `GetCoreSchemaHandler` instance.
60
+
61
+ Returns:
62
+ The Pydantic core schema.
63
+ """
64
+ schema = handler(source_type)
65
+ if self.return_type is not PydanticUndefined:
66
+ return_type = self.return_type
67
+ else:
68
+ try:
69
+ # Do not pass in globals as the function could be defined in a different module.
70
+ # Instead, let `get_callable_return_type` infer the globals to use, but still pass
71
+ # in locals that may contain a parent/rebuild namespace:
72
+ return_type = _decorators.get_callable_return_type(
73
+ self.func,
74
+ localns=handler._get_types_namespace().locals,
75
+ )
76
+ except NameError as e:
77
+ raise PydanticUndefinedAnnotation.from_name_error(e) from e
78
+
79
+ return_schema = None if return_type is PydanticUndefined else handler.generate_schema(return_type)
80
+ schema['serialization'] = core_schema.plain_serializer_function_ser_schema(
81
+ function=self.func,
82
+ info_arg=_decorators.inspect_annotated_serializer(self.func, 'plain'),
83
+ return_schema=return_schema,
84
+ when_used=self.when_used,
85
+ )
86
+ return schema
87
+
88
+
89
+ @dataclasses.dataclass(**_internal_dataclass.slots_true, frozen=True)
90
+ class WrapSerializer:
91
+ """Wrap serializers receive the raw inputs along with a handler function that applies the standard serialization
92
+ logic, and can modify the resulting value before returning it as the final output of serialization.
93
+
94
+ For example, here's a scenario in which a wrap serializer transforms timezones to UTC **and** utilizes the existing `datetime` serialization logic.
95
+
96
+ ```python
97
+ from datetime import datetime, timezone
98
+ from typing import Annotated, Any
99
+
100
+ from pydantic import BaseModel, WrapSerializer
101
+
102
+ class EventDatetime(BaseModel):
103
+ start: datetime
104
+ end: datetime
105
+
106
+ def convert_to_utc(value: Any, handler, info) -> dict[str, datetime]:
107
+ # Note that `handler` can actually help serialize the `value` for
108
+ # further custom serialization in case it's a subclass.
109
+ partial_result = handler(value, info)
110
+ if info.mode == 'json':
111
+ return {
112
+ k: datetime.fromisoformat(v).astimezone(timezone.utc)
113
+ for k, v in partial_result.items()
114
+ }
115
+ return {k: v.astimezone(timezone.utc) for k, v in partial_result.items()}
116
+
117
+ UTCEventDatetime = Annotated[EventDatetime, WrapSerializer(convert_to_utc)]
118
+
119
+ class EventModel(BaseModel):
120
+ event_datetime: UTCEventDatetime
121
+
122
+ dt = EventDatetime(
123
+ start='2024-01-01T07:00:00-08:00', end='2024-01-03T20:00:00+06:00'
124
+ )
125
+ event = EventModel(event_datetime=dt)
126
+ print(event.model_dump())
127
+ '''
128
+ {
129
+ 'event_datetime': {
130
+ 'start': datetime.datetime(
131
+ 2024, 1, 1, 15, 0, tzinfo=datetime.timezone.utc
132
+ ),
133
+ 'end': datetime.datetime(
134
+ 2024, 1, 3, 14, 0, tzinfo=datetime.timezone.utc
135
+ ),
136
+ }
137
+ }
138
+ '''
139
+
140
+ print(event.model_dump_json())
141
+ '''
142
+ {"event_datetime":{"start":"2024-01-01T15:00:00Z","end":"2024-01-03T14:00:00Z"}}
143
+ '''
144
+ ```
145
+
146
+ Attributes:
147
+ func: The serializer function to be wrapped.
148
+ return_type: The return type for the function. If omitted it will be inferred from the type annotation.
149
+ when_used: Determines when this serializer should be used. Accepts a string with values `'always'`,
150
+ `'unless-none'`, `'json'`, and `'json-unless-none'`. Defaults to 'always'.
151
+ """
152
+
153
+ func: core_schema.WrapSerializerFunction
154
+ return_type: Any = PydanticUndefined
155
+ when_used: WhenUsed = 'always'
156
+
157
+ def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
158
+ """This method is used to get the Pydantic core schema of the class.
159
+
160
+ Args:
161
+ source_type: Source type.
162
+ handler: Core schema handler.
163
+
164
+ Returns:
165
+ The generated core schema of the class.
166
+ """
167
+ schema = handler(source_type)
168
+ if self.return_type is not PydanticUndefined:
169
+ return_type = self.return_type
170
+ else:
171
+ try:
172
+ # Do not pass in globals as the function could be defined in a different module.
173
+ # Instead, let `get_callable_return_type` infer the globals to use, but still pass
174
+ # in locals that may contain a parent/rebuild namespace:
175
+ return_type = _decorators.get_callable_return_type(
176
+ self.func,
177
+ localns=handler._get_types_namespace().locals,
178
+ )
179
+ except NameError as e:
180
+ raise PydanticUndefinedAnnotation.from_name_error(e) from e
181
+
182
+ return_schema = None if return_type is PydanticUndefined else handler.generate_schema(return_type)
183
+ schema['serialization'] = core_schema.wrap_serializer_function_ser_schema(
184
+ function=self.func,
185
+ info_arg=_decorators.inspect_annotated_serializer(self.func, 'wrap'),
186
+ return_schema=return_schema,
187
+ when_used=self.when_used,
188
+ )
189
+ return schema
190
+
191
+
192
+ if TYPE_CHECKING:
193
+ _Partial: TypeAlias = 'partial[Any] | partialmethod[Any]'
194
+
195
+ FieldPlainSerializer: TypeAlias = 'core_schema.SerializerFunction | _Partial'
196
+ """A field serializer method or function in `plain` mode."""
197
+
198
+ FieldWrapSerializer: TypeAlias = 'core_schema.WrapSerializerFunction | _Partial'
199
+ """A field serializer method or function in `wrap` mode."""
200
+
201
+ FieldSerializer: TypeAlias = 'FieldPlainSerializer | FieldWrapSerializer'
202
+ """A field serializer method or function."""
203
+
204
+ _FieldPlainSerializerT = TypeVar('_FieldPlainSerializerT', bound=FieldPlainSerializer)
205
+ _FieldWrapSerializerT = TypeVar('_FieldWrapSerializerT', bound=FieldWrapSerializer)
206
+
207
+
208
+ @overload
209
+ def field_serializer(
210
+ field: str,
211
+ /,
212
+ *fields: str,
213
+ mode: Literal['wrap'],
214
+ return_type: Any = ...,
215
+ when_used: WhenUsed = ...,
216
+ check_fields: bool | None = ...,
217
+ ) -> Callable[[_FieldWrapSerializerT], _FieldWrapSerializerT]: ...
218
+
219
+
220
+ @overload
221
+ def field_serializer(
222
+ field: str,
223
+ /,
224
+ *fields: str,
225
+ mode: Literal['plain'] = ...,
226
+ return_type: Any = ...,
227
+ when_used: WhenUsed = ...,
228
+ check_fields: bool | None = ...,
229
+ ) -> Callable[[_FieldPlainSerializerT], _FieldPlainSerializerT]: ...
230
+
231
+
232
+ def field_serializer( # noqa: D417
233
+ field: str,
234
+ /,
235
+ *fields: str,
236
+ mode: Literal['plain', 'wrap'] = 'plain',
237
+ # TODO PEP 747 (grep for 'return_type' on the whole code base):
238
+ return_type: Any = PydanticUndefined,
239
+ when_used: WhenUsed = 'always',
240
+ check_fields: bool | None = None,
241
+ ) -> (
242
+ Callable[[_FieldWrapSerializerT], _FieldWrapSerializerT]
243
+ | Callable[[_FieldPlainSerializerT], _FieldPlainSerializerT]
244
+ ):
245
+ """Decorator that enables custom field serialization.
246
+
247
+ In the below example, a field of type `set` is used to mitigate duplication. A `field_serializer` is used to serialize the data as a sorted list.
248
+
249
+ ```python
250
+ from pydantic import BaseModel, field_serializer
251
+
252
+ class StudentModel(BaseModel):
253
+ name: str = 'Jane'
254
+ courses: set[str]
255
+
256
+ @field_serializer('courses', when_used='json')
257
+ def serialize_courses_in_order(self, courses: set[str]):
258
+ return sorted(courses)
259
+
260
+ student = StudentModel(courses={'Math', 'Chemistry', 'English'})
261
+ print(student.model_dump_json())
262
+ #> {"name":"Jane","courses":["Chemistry","English","Math"]}
263
+ ```
264
+
265
+ See [the usage documentation](../concepts/serialization.md#serializers) for more information.
266
+
267
+ Four signatures are supported for the decorated serializer:
268
+
269
+ - `(self, value: Any, info: FieldSerializationInfo)`
270
+ - `(self, value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo)`
271
+ - `(value: Any, info: SerializationInfo)`
272
+ - `(value: Any, nxt: SerializerFunctionWrapHandler, info: SerializationInfo)`
273
+
274
+ Args:
275
+ *fields: The field names the serializer should apply to.
276
+ mode: The serialization mode.
277
+
278
+ - `plain` means the function will be called instead of the default serialization logic,
279
+ - `wrap` means the function will be called with an argument to optionally call the
280
+ default serialization logic.
281
+ return_type: Optional return type for the function, if omitted it will be inferred from the type annotation.
282
+ when_used: Determines the serializer will be used for serialization.
283
+ check_fields: Whether to check that the fields actually exist on the model.
284
+
285
+ Raises:
286
+ PydanticUserError:
287
+ - If the decorator is used without any arguments (at least one field name must be provided).
288
+ - If the provided field names are not strings.
289
+ """
290
+ if callable(field) or isinstance(field, classmethod):
291
+ raise PydanticUserError(
292
+ 'The `@field_serializer` decorator cannot be used without arguments, at least one field must be provided. '
293
+ "For example: `@field_serializer('<field_name>', ...)`.",
294
+ code='decorator-missing-arguments',
295
+ )
296
+
297
+ fields = field, *fields
298
+ if not all(isinstance(field, str) for field in fields):
299
+ raise PydanticUserError(
300
+ 'The provided field names to the `@field_serializer` decorator should be strings. '
301
+ "For example: `@field_serializer('<field_name_1>', '<field_name_2>', ...).`",
302
+ code='decorator-invalid-fields',
303
+ )
304
+
305
+ def dec(f: FieldSerializer) -> _decorators.PydanticDescriptorProxy[Any]:
306
+ dec_info = _decorators.FieldSerializerDecoratorInfo(
307
+ fields=fields,
308
+ mode=mode,
309
+ return_type=return_type,
310
+ when_used=when_used,
311
+ check_fields=check_fields,
312
+ )
313
+ return _decorators.PydanticDescriptorProxy(f, dec_info) # pyright: ignore[reportArgumentType]
314
+
315
+ return dec # pyright: ignore[reportReturnType]
316
+
317
+
318
+ if TYPE_CHECKING:
319
+ # The first argument in the following callables represent the `self` type:
320
+
321
+ ModelPlainSerializerWithInfo: TypeAlias = Callable[[Any, SerializationInfo[Any]], Any]
322
+ """A model serializer method with the `info` argument, in `plain` mode."""
323
+
324
+ ModelPlainSerializerWithoutInfo: TypeAlias = Callable[[Any], Any]
325
+ """A model serializer method without the `info` argument, in `plain` mode."""
326
+
327
+ ModelPlainSerializer: TypeAlias = 'ModelPlainSerializerWithInfo | ModelPlainSerializerWithoutInfo'
328
+ """A model serializer method in `plain` mode."""
329
+
330
+ ModelWrapSerializerWithInfo: TypeAlias = Callable[[Any, SerializerFunctionWrapHandler, SerializationInfo[Any]], Any]
331
+ """A model serializer method with the `info` argument, in `wrap` mode."""
332
+
333
+ ModelWrapSerializerWithoutInfo: TypeAlias = Callable[[Any, SerializerFunctionWrapHandler], Any]
334
+ """A model serializer method without the `info` argument, in `wrap` mode."""
335
+
336
+ ModelWrapSerializer: TypeAlias = 'ModelWrapSerializerWithInfo | ModelWrapSerializerWithoutInfo'
337
+ """A model serializer method in `wrap` mode."""
338
+
339
+ ModelSerializer: TypeAlias = 'ModelPlainSerializer | ModelWrapSerializer'
340
+
341
+ _ModelPlainSerializerT = TypeVar('_ModelPlainSerializerT', bound=ModelPlainSerializer)
342
+ _ModelWrapSerializerT = TypeVar('_ModelWrapSerializerT', bound=ModelWrapSerializer)
343
+
344
+
345
+ @overload
346
+ def model_serializer(f: _ModelPlainSerializerT, /) -> _ModelPlainSerializerT: ...
347
+
348
+
349
+ @overload
350
+ def model_serializer(
351
+ *, mode: Literal['wrap'], when_used: WhenUsed = 'always', return_type: Any = ...
352
+ ) -> Callable[[_ModelWrapSerializerT], _ModelWrapSerializerT]: ...
353
+
354
+
355
+ @overload
356
+ def model_serializer(
357
+ *,
358
+ mode: Literal['plain'] = ...,
359
+ when_used: WhenUsed = 'always',
360
+ return_type: Any = ...,
361
+ ) -> Callable[[_ModelPlainSerializerT], _ModelPlainSerializerT]: ...
362
+
363
+
364
+ def model_serializer(
365
+ f: _ModelPlainSerializerT | _ModelWrapSerializerT | None = None,
366
+ /,
367
+ *,
368
+ mode: Literal['plain', 'wrap'] = 'plain',
369
+ when_used: WhenUsed = 'always',
370
+ return_type: Any = PydanticUndefined,
371
+ ) -> (
372
+ _ModelPlainSerializerT
373
+ | Callable[[_ModelWrapSerializerT], _ModelWrapSerializerT]
374
+ | Callable[[_ModelPlainSerializerT], _ModelPlainSerializerT]
375
+ ):
376
+ """Decorator that enables custom model serialization.
377
+
378
+ This is useful when a model need to be serialized in a customized manner, allowing for flexibility beyond just specific fields.
379
+
380
+ An example would be to serialize temperature to the same temperature scale, such as degrees Celsius.
381
+
382
+ ```python
383
+ from typing import Literal
384
+
385
+ from pydantic import BaseModel, model_serializer
386
+
387
+ class TemperatureModel(BaseModel):
388
+ unit: Literal['C', 'F']
389
+ value: int
390
+
391
+ @model_serializer()
392
+ def serialize_model(self):
393
+ if self.unit == 'F':
394
+ return {'unit': 'C', 'value': int((self.value - 32) / 1.8)}
395
+ return {'unit': self.unit, 'value': self.value}
396
+
397
+ temperature = TemperatureModel(unit='F', value=212)
398
+ print(temperature.model_dump())
399
+ #> {'unit': 'C', 'value': 100}
400
+ ```
401
+
402
+ Two signatures are supported for `mode='plain'`, which is the default:
403
+
404
+ - `(self)`
405
+ - `(self, info: SerializationInfo)`
406
+
407
+ And two other signatures for `mode='wrap'`:
408
+
409
+ - `(self, nxt: SerializerFunctionWrapHandler)`
410
+ - `(self, nxt: SerializerFunctionWrapHandler, info: SerializationInfo)`
411
+
412
+ See [the usage documentation](../concepts/serialization.md#serializers) for more information.
413
+
414
+ Args:
415
+ f: The function to be decorated.
416
+ mode: The serialization mode.
417
+
418
+ - `'plain'` means the function will be called instead of the default serialization logic
419
+ - `'wrap'` means the function will be called with an argument to optionally call the default
420
+ serialization logic.
421
+ when_used: Determines when this serializer should be used.
422
+ return_type: The return type for the function. If omitted it will be inferred from the type annotation.
423
+
424
+ Returns:
425
+ The decorator function.
426
+ """
427
+
428
+ def dec(f: ModelSerializer) -> _decorators.PydanticDescriptorProxy[Any]:
429
+ dec_info = _decorators.ModelSerializerDecoratorInfo(mode=mode, return_type=return_type, when_used=when_used)
430
+ return _decorators.PydanticDescriptorProxy(f, dec_info)
431
+
432
+ if f is None:
433
+ return dec # pyright: ignore[reportReturnType]
434
+ else:
435
+ return dec(f) # pyright: ignore[reportReturnType]
436
+
437
+
438
+ AnyType = TypeVar('AnyType')
439
+
440
+
441
+ if TYPE_CHECKING:
442
+ SerializeAsAny = Annotated[AnyType, ...] # SerializeAsAny[list[str]] will be treated by type checkers as list[str]
443
+ """Annotation used to mark a type as having duck-typing serialization behavior.
444
+
445
+ See [usage documentation](../concepts/serialization.md#serializing-with-duck-typing) for more details.
446
+ """
447
+ else:
448
+
449
+ @dataclasses.dataclass(**_internal_dataclass.slots_true)
450
+ class SerializeAsAny:
451
+ """Annotation used to mark a type as having duck-typing serialization behavior.
452
+
453
+ See [usage documentation](../concepts/serialization.md#serializing-with-duck-typing) for more details.
454
+ """
455
+
456
+ def __class_getitem__(cls, item: Any) -> Any:
457
+ return Annotated[item, SerializeAsAny()]
458
+
459
+ def __get_pydantic_core_schema__(
460
+ self, source_type: Any, handler: GetCoreSchemaHandler
461
+ ) -> core_schema.CoreSchema:
462
+ schema = handler(source_type)
463
+ schema_to_update = schema
464
+ while schema_to_update['type'] == 'definitions':
465
+ schema_to_update = schema_to_update.copy()
466
+ schema_to_update = schema_to_update['schema']
467
+ schema_to_update['serialization'] = core_schema.simple_ser_schema('any')
468
+ return schema
469
+
470
+ __hash__ = object.__hash__
.mcp-venv/lib/python3.13/site-packages/pydantic/functional_validators.py ADDED
@@ -0,0 +1,889 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """This module contains related classes and functions for validation."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ import dataclasses
6
+ import sys
7
+ import warnings
8
+ from functools import partialmethod
9
+ from typing import TYPE_CHECKING, Annotated, Any, Callable, Literal, TypeVar, Union, cast, overload
10
+
11
+ from pydantic_core import PydanticUndefined, core_schema
12
+ from typing_extensions import Self, TypeAlias
13
+
14
+ from ._internal import _decorators, _generics, _internal_dataclass
15
+ from .annotated_handlers import GetCoreSchemaHandler
16
+ from .errors import PydanticUserError
17
+ from .version import version_short
18
+ from .warnings import ArbitraryTypeWarning, PydanticDeprecatedSince212
19
+
20
+ if sys.version_info < (3, 11):
21
+ from typing_extensions import Protocol
22
+ else:
23
+ from typing import Protocol
24
+
25
+ _inspect_validator = _decorators.inspect_validator
26
+
27
+
28
+ @dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true)
29
+ class AfterValidator:
30
+ """!!! abstract "Usage Documentation"
31
+ [field *after* validators](../concepts/validators.md#field-after-validator)
32
+
33
+ A metadata class that indicates that a validation should be applied **after** the inner validation logic.
34
+
35
+ Attributes:
36
+ func: The validator function.
37
+
38
+ Example:
39
+ ```python
40
+ from typing import Annotated
41
+
42
+ from pydantic import AfterValidator, BaseModel, ValidationError
43
+
44
+ MyInt = Annotated[int, AfterValidator(lambda v: v + 1)]
45
+
46
+ class Model(BaseModel):
47
+ a: MyInt
48
+
49
+ print(Model(a=1).a)
50
+ #> 2
51
+
52
+ try:
53
+ Model(a='a')
54
+ except ValidationError as e:
55
+ print(e.json(indent=2))
56
+ '''
57
+ [
58
+ {
59
+ "type": "int_parsing",
60
+ "loc": [
61
+ "a"
62
+ ],
63
+ "msg": "Input should be a valid integer, unable to parse string as an integer",
64
+ "input": "a",
65
+ "url": "https://errors.pydantic.dev/2/v/int_parsing"
66
+ }
67
+ ]
68
+ '''
69
+ ```
70
+ """
71
+
72
+ func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction
73
+
74
+ def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
75
+ schema = handler(source_type)
76
+ info_arg = _inspect_validator(self.func, mode='after', type='field')
77
+ if info_arg:
78
+ func = cast(core_schema.WithInfoValidatorFunction, self.func)
79
+ return core_schema.with_info_after_validator_function(func, schema=schema)
80
+ else:
81
+ func = cast(core_schema.NoInfoValidatorFunction, self.func)
82
+ return core_schema.no_info_after_validator_function(func, schema=schema)
83
+
84
+ @classmethod
85
+ def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self:
86
+ return cls(func=decorator.func)
87
+
88
+
89
+ @dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true)
90
+ class BeforeValidator:
91
+ """!!! abstract "Usage Documentation"
92
+ [field *before* validators](../concepts/validators.md#field-before-validator)
93
+
94
+ A metadata class that indicates that a validation should be applied **before** the inner validation logic.
95
+
96
+ Attributes:
97
+ func: The validator function.
98
+ json_schema_input_type: The input type used to generate the appropriate
99
+ JSON Schema (in validation mode). The actual input type is `Any`.
100
+
101
+ Example:
102
+ ```python
103
+ from typing import Annotated
104
+
105
+ from pydantic import BaseModel, BeforeValidator
106
+
107
+ MyInt = Annotated[int, BeforeValidator(lambda v: v + 1)]
108
+
109
+ class Model(BaseModel):
110
+ a: MyInt
111
+
112
+ print(Model(a=1).a)
113
+ #> 2
114
+
115
+ try:
116
+ Model(a='a')
117
+ except TypeError as e:
118
+ print(e)
119
+ #> can only concatenate str (not "int") to str
120
+ ```
121
+ """
122
+
123
+ func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction
124
+ json_schema_input_type: Any = PydanticUndefined
125
+
126
+ def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
127
+ schema = handler(source_type)
128
+ input_schema = (
129
+ None
130
+ if self.json_schema_input_type is PydanticUndefined
131
+ else handler.generate_schema(self.json_schema_input_type)
132
+ )
133
+
134
+ info_arg = _inspect_validator(self.func, mode='before', type='field')
135
+ if info_arg:
136
+ func = cast(core_schema.WithInfoValidatorFunction, self.func)
137
+ return core_schema.with_info_before_validator_function(
138
+ func,
139
+ schema=schema,
140
+ json_schema_input_schema=input_schema,
141
+ )
142
+ else:
143
+ func = cast(core_schema.NoInfoValidatorFunction, self.func)
144
+ return core_schema.no_info_before_validator_function(
145
+ func, schema=schema, json_schema_input_schema=input_schema
146
+ )
147
+
148
+ @classmethod
149
+ def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self:
150
+ return cls(
151
+ func=decorator.func,
152
+ json_schema_input_type=decorator.info.json_schema_input_type,
153
+ )
154
+
155
+
156
+ @dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true)
157
+ class PlainValidator:
158
+ """!!! abstract "Usage Documentation"
159
+ [field *plain* validators](../concepts/validators.md#field-plain-validator)
160
+
161
+ A metadata class that indicates that a validation should be applied **instead** of the inner validation logic.
162
+
163
+ !!! note
164
+ Before v2.9, `PlainValidator` wasn't always compatible with JSON Schema generation for `mode='validation'`.
165
+ You can now use the `json_schema_input_type` argument to specify the input type of the function
166
+ to be used in the JSON schema when `mode='validation'` (the default). See the example below for more details.
167
+
168
+ Attributes:
169
+ func: The validator function.
170
+ json_schema_input_type: The input type used to generate the appropriate
171
+ JSON Schema (in validation mode). The actual input type is `Any`.
172
+
173
+ Example:
174
+ ```python
175
+ from typing import Annotated, Union
176
+
177
+ from pydantic import BaseModel, PlainValidator
178
+
179
+ def validate(v: object) -> int:
180
+ if not isinstance(v, (int, str)):
181
+ raise ValueError(f'Expected int or str, got {type(v)}')
182
+
183
+ return int(v) + 1
184
+
185
+ MyInt = Annotated[
186
+ int,
187
+ PlainValidator(validate, json_schema_input_type=Union[str, int]), # (1)!
188
+ ]
189
+
190
+ class Model(BaseModel):
191
+ a: MyInt
192
+
193
+ print(Model(a='1').a)
194
+ #> 2
195
+
196
+ print(Model(a=1).a)
197
+ #> 2
198
+ ```
199
+
200
+ 1. In this example, we've specified the `json_schema_input_type` as `Union[str, int]` which indicates to the JSON schema
201
+ generator that in validation mode, the input type for the `a` field can be either a [`str`][] or an [`int`][].
202
+ """
203
+
204
+ func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction
205
+ json_schema_input_type: Any = Any
206
+
207
+ def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
208
+ # Note that for some valid uses of PlainValidator, it is not possible to generate a core schema for the
209
+ # source_type, so calling `handler(source_type)` will error, which prevents us from generating a proper
210
+ # serialization schema. To work around this for use cases that will not involve serialization, we simply
211
+ # catch any PydanticSchemaGenerationError that may be raised while attempting to build the serialization schema
212
+ # and abort any attempts to handle special serialization.
213
+ from pydantic import PydanticSchemaGenerationError
214
+
215
+ try:
216
+ schema = handler(source_type)
217
+ # TODO if `schema['serialization']` is one of `'include-exclude-dict/sequence',
218
+ # schema validation will fail. That's why we use 'type ignore' comments below.
219
+ serialization = schema.get(
220
+ 'serialization',
221
+ core_schema.wrap_serializer_function_ser_schema(
222
+ function=lambda v, h: h(v),
223
+ schema=schema,
224
+ return_schema=handler.generate_schema(source_type),
225
+ ),
226
+ )
227
+ except PydanticSchemaGenerationError:
228
+ serialization = None
229
+
230
+ input_schema = handler.generate_schema(self.json_schema_input_type)
231
+
232
+ info_arg = _inspect_validator(self.func, mode='plain', type='field')
233
+ if info_arg:
234
+ func = cast(core_schema.WithInfoValidatorFunction, self.func)
235
+ return core_schema.with_info_plain_validator_function(
236
+ func,
237
+ serialization=serialization, # pyright: ignore[reportArgumentType]
238
+ json_schema_input_schema=input_schema,
239
+ )
240
+ else:
241
+ func = cast(core_schema.NoInfoValidatorFunction, self.func)
242
+ return core_schema.no_info_plain_validator_function(
243
+ func,
244
+ serialization=serialization, # pyright: ignore[reportArgumentType]
245
+ json_schema_input_schema=input_schema,
246
+ )
247
+
248
+ @classmethod
249
+ def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self:
250
+ return cls(
251
+ func=decorator.func,
252
+ json_schema_input_type=decorator.info.json_schema_input_type,
253
+ )
254
+
255
+
256
+ @dataclasses.dataclass(frozen=True, **_internal_dataclass.slots_true)
257
+ class WrapValidator:
258
+ """!!! abstract "Usage Documentation"
259
+ [field *wrap* validators](../concepts/validators.md#field-wrap-validator)
260
+
261
+ A metadata class that indicates that a validation should be applied **around** the inner validation logic.
262
+
263
+ Attributes:
264
+ func: The validator function.
265
+ json_schema_input_type: The input type used to generate the appropriate
266
+ JSON Schema (in validation mode). The actual input type is `Any`.
267
+
268
+ ```python
269
+ from datetime import datetime
270
+ from typing import Annotated
271
+
272
+ from pydantic import BaseModel, ValidationError, WrapValidator
273
+
274
+ def validate_timestamp(v, handler):
275
+ if v == 'now':
276
+ # we don't want to bother with further validation, just return the new value
277
+ return datetime.now()
278
+ try:
279
+ return handler(v)
280
+ except ValidationError:
281
+ # validation failed, in this case we want to return a default value
282
+ return datetime(2000, 1, 1)
283
+
284
+ MyTimestamp = Annotated[datetime, WrapValidator(validate_timestamp)]
285
+
286
+ class Model(BaseModel):
287
+ a: MyTimestamp
288
+
289
+ print(Model(a='now').a)
290
+ #> 2032-01-02 03:04:05.000006
291
+ print(Model(a='invalid').a)
292
+ #> 2000-01-01 00:00:00
293
+ ```
294
+ """
295
+
296
+ func: core_schema.NoInfoWrapValidatorFunction | core_schema.WithInfoWrapValidatorFunction
297
+ json_schema_input_type: Any = PydanticUndefined
298
+
299
+ def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
300
+ schema = handler(source_type)
301
+ input_schema = (
302
+ None
303
+ if self.json_schema_input_type is PydanticUndefined
304
+ else handler.generate_schema(self.json_schema_input_type)
305
+ )
306
+
307
+ info_arg = _inspect_validator(self.func, mode='wrap', type='field')
308
+ if info_arg:
309
+ func = cast(core_schema.WithInfoWrapValidatorFunction, self.func)
310
+ return core_schema.with_info_wrap_validator_function(
311
+ func,
312
+ schema=schema,
313
+ json_schema_input_schema=input_schema,
314
+ )
315
+ else:
316
+ func = cast(core_schema.NoInfoWrapValidatorFunction, self.func)
317
+ return core_schema.no_info_wrap_validator_function(
318
+ func,
319
+ schema=schema,
320
+ json_schema_input_schema=input_schema,
321
+ )
322
+
323
+ @classmethod
324
+ def _from_decorator(cls, decorator: _decorators.Decorator[_decorators.FieldValidatorDecoratorInfo]) -> Self:
325
+ return cls(
326
+ func=decorator.func,
327
+ json_schema_input_type=decorator.info.json_schema_input_type,
328
+ )
329
+
330
+
331
+ if TYPE_CHECKING:
332
+
333
+ class _OnlyValueValidatorClsMethod(Protocol):
334
+ def __call__(self, cls: Any, value: Any, /) -> Any: ...
335
+
336
+ class _V2ValidatorClsMethod(Protocol):
337
+ def __call__(self, cls: Any, value: Any, info: core_schema.ValidationInfo[Any], /) -> Any: ...
338
+
339
+ class _OnlyValueWrapValidatorClsMethod(Protocol):
340
+ def __call__(self, cls: Any, value: Any, handler: core_schema.ValidatorFunctionWrapHandler, /) -> Any: ...
341
+
342
+ class _V2WrapValidatorClsMethod(Protocol):
343
+ def __call__(
344
+ self,
345
+ cls: Any,
346
+ value: Any,
347
+ handler: core_schema.ValidatorFunctionWrapHandler,
348
+ info: core_schema.ValidationInfo[Any],
349
+ /,
350
+ ) -> Any: ...
351
+
352
+ _V2Validator = Union[
353
+ _V2ValidatorClsMethod,
354
+ core_schema.WithInfoValidatorFunction,
355
+ _OnlyValueValidatorClsMethod,
356
+ core_schema.NoInfoValidatorFunction,
357
+ ]
358
+
359
+ _V2WrapValidator = Union[
360
+ _V2WrapValidatorClsMethod,
361
+ core_schema.WithInfoWrapValidatorFunction,
362
+ _OnlyValueWrapValidatorClsMethod,
363
+ core_schema.NoInfoWrapValidatorFunction,
364
+ ]
365
+
366
+ _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]]
367
+
368
+ _V2BeforeAfterOrPlainValidatorType = TypeVar(
369
+ '_V2BeforeAfterOrPlainValidatorType',
370
+ bound=Union[_V2Validator, _PartialClsOrStaticMethod],
371
+ )
372
+ _V2WrapValidatorType = TypeVar('_V2WrapValidatorType', bound=Union[_V2WrapValidator, _PartialClsOrStaticMethod])
373
+
374
+ FieldValidatorModes: TypeAlias = Literal['before', 'after', 'wrap', 'plain']
375
+
376
+
377
+ @overload
378
+ def field_validator(
379
+ field: str,
380
+ /,
381
+ *fields: str,
382
+ mode: Literal['wrap'],
383
+ check_fields: bool | None = ...,
384
+ json_schema_input_type: Any = ...,
385
+ ) -> Callable[[_V2WrapValidatorType], _V2WrapValidatorType]: ...
386
+
387
+
388
+ @overload
389
+ def field_validator(
390
+ field: str,
391
+ /,
392
+ *fields: str,
393
+ mode: Literal['before', 'plain'],
394
+ check_fields: bool | None = ...,
395
+ json_schema_input_type: Any = ...,
396
+ ) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ...
397
+
398
+
399
+ @overload
400
+ def field_validator(
401
+ field: str,
402
+ /,
403
+ *fields: str,
404
+ mode: Literal['after'] = ...,
405
+ check_fields: bool | None = ...,
406
+ ) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType]: ...
407
+
408
+
409
+ def field_validator( # noqa: D417
410
+ field: str,
411
+ /,
412
+ *fields: str,
413
+ mode: FieldValidatorModes = 'after',
414
+ check_fields: bool | None = None,
415
+ json_schema_input_type: Any = PydanticUndefined,
416
+ ) -> Callable[[Any], Any]:
417
+ """!!! abstract "Usage Documentation"
418
+ [field validators](../concepts/validators.md#field-validators)
419
+
420
+ Decorate methods on the class indicating that they should be used to validate fields.
421
+
422
+ Example usage:
423
+ ```python
424
+ from typing import Any
425
+
426
+ from pydantic import (
427
+ BaseModel,
428
+ ValidationError,
429
+ field_validator,
430
+ )
431
+
432
+ class Model(BaseModel):
433
+ a: str
434
+
435
+ @field_validator('a')
436
+ @classmethod
437
+ def ensure_foobar(cls, v: Any):
438
+ if 'foobar' not in v:
439
+ raise ValueError('"foobar" not found in a')
440
+ return v
441
+
442
+ print(repr(Model(a='this is foobar good')))
443
+ #> Model(a='this is foobar good')
444
+
445
+ try:
446
+ Model(a='snap')
447
+ except ValidationError as exc_info:
448
+ print(exc_info)
449
+ '''
450
+ 1 validation error for Model
451
+ a
452
+ Value error, "foobar" not found in a [type=value_error, input_value='snap', input_type=str]
453
+ '''
454
+ ```
455
+
456
+ For more in depth examples, see [Field Validators](../concepts/validators.md#field-validators).
457
+
458
+ Args:
459
+ *fields: The field names the validator should apply to.
460
+ mode: Specifies whether to validate the fields before or after validation.
461
+ check_fields: Whether to check that the fields actually exist on the model.
462
+ json_schema_input_type: The input type of the function. This is only used to generate
463
+ the appropriate JSON Schema (in validation mode) and can only specified
464
+ when `mode` is either `'before'`, `'plain'` or `'wrap'`.
465
+
466
+ Raises:
467
+ PydanticUserError:
468
+ - If the decorator is used without any arguments (at least one field name must be provided).
469
+ - If the provided field names are not strings.
470
+ - If `json_schema_input_type` is provided with an unsupported `mode`.
471
+ - If the decorator is applied to an instance method.
472
+ """
473
+ if callable(field) or isinstance(field, classmethod):
474
+ raise PydanticUserError(
475
+ 'The `@field_validator` decorator cannot be used without arguments, at least one field must be provided. '
476
+ "For example: `@field_validator('<field_name>', ...)`.",
477
+ code='decorator-missing-arguments',
478
+ )
479
+
480
+ if mode not in ('before', 'plain', 'wrap') and json_schema_input_type is not PydanticUndefined:
481
+ raise PydanticUserError(
482
+ f"`json_schema_input_type` can't be used when mode is set to {mode!r}",
483
+ code='validator-input-type',
484
+ )
485
+
486
+ if json_schema_input_type is PydanticUndefined and mode == 'plain':
487
+ json_schema_input_type = Any
488
+
489
+ fields = field, *fields
490
+ if not all(isinstance(field, str) for field in fields):
491
+ raise PydanticUserError(
492
+ 'The provided field names to the `@field_validator` decorator should be strings. '
493
+ "For example: `@field_validator('<field_name_1>', '<field_name_2>', ...).`",
494
+ code='decorator-invalid-fields',
495
+ )
496
+
497
+ def dec(
498
+ f: Callable[..., Any] | staticmethod[Any, Any] | classmethod[Any, Any, Any],
499
+ ) -> _decorators.PydanticDescriptorProxy[Any]:
500
+ if _decorators.is_instance_method_from_sig(f):
501
+ raise PydanticUserError(
502
+ 'The `@field_validator` decorator cannot be applied to instance methods',
503
+ code='validator-instance-method',
504
+ )
505
+
506
+ # auto apply the @classmethod decorator
507
+ f = _decorators.ensure_classmethod_based_on_signature(f)
508
+
509
+ dec_info = _decorators.FieldValidatorDecoratorInfo(
510
+ fields=fields, mode=mode, check_fields=check_fields, json_schema_input_type=json_schema_input_type
511
+ )
512
+ return _decorators.PydanticDescriptorProxy(f, dec_info)
513
+
514
+ return dec
515
+
516
+
517
+ _ModelType = TypeVar('_ModelType')
518
+ _ModelTypeCo = TypeVar('_ModelTypeCo', covariant=True)
519
+
520
+
521
+ class ModelWrapValidatorHandler(core_schema.ValidatorFunctionWrapHandler, Protocol[_ModelTypeCo]):
522
+ """`@model_validator` decorated function handler argument type. This is used when `mode='wrap'`."""
523
+
524
+ def __call__( # noqa: D102
525
+ self,
526
+ value: Any,
527
+ outer_location: str | int | None = None,
528
+ /,
529
+ ) -> _ModelTypeCo: # pragma: no cover
530
+ ...
531
+
532
+
533
+ class ModelWrapValidatorWithoutInfo(Protocol[_ModelType]):
534
+ """A `@model_validator` decorated function signature.
535
+ This is used when `mode='wrap'` and the function does not have info argument.
536
+ """
537
+
538
+ def __call__( # noqa: D102
539
+ self,
540
+ cls: type[_ModelType],
541
+ # this can be a dict, a model instance
542
+ # or anything else that gets passed to validate_python
543
+ # thus validators _must_ handle all cases
544
+ value: Any,
545
+ handler: ModelWrapValidatorHandler[_ModelType],
546
+ /,
547
+ ) -> _ModelType: ...
548
+
549
+
550
+ class ModelWrapValidator(Protocol[_ModelType]):
551
+ """A `@model_validator` decorated function signature. This is used when `mode='wrap'`."""
552
+
553
+ def __call__( # noqa: D102
554
+ self,
555
+ cls: type[_ModelType],
556
+ # this can be a dict, a model instance
557
+ # or anything else that gets passed to validate_python
558
+ # thus validators _must_ handle all cases
559
+ value: Any,
560
+ handler: ModelWrapValidatorHandler[_ModelType],
561
+ info: core_schema.ValidationInfo,
562
+ /,
563
+ ) -> _ModelType: ...
564
+
565
+
566
+ class FreeModelBeforeValidatorWithoutInfo(Protocol):
567
+ """A `@model_validator` decorated function signature.
568
+ This is used when `mode='before'` and the function does not have info argument.
569
+ """
570
+
571
+ def __call__( # noqa: D102
572
+ self,
573
+ # this can be a dict, a model instance
574
+ # or anything else that gets passed to validate_python
575
+ # thus validators _must_ handle all cases
576
+ value: Any,
577
+ /,
578
+ ) -> Any: ...
579
+
580
+
581
+ class ModelBeforeValidatorWithoutInfo(Protocol):
582
+ """A `@model_validator` decorated function signature.
583
+ This is used when `mode='before'` and the function does not have info argument.
584
+ """
585
+
586
+ def __call__( # noqa: D102
587
+ self,
588
+ cls: Any,
589
+ # this can be a dict, a model instance
590
+ # or anything else that gets passed to validate_python
591
+ # thus validators _must_ handle all cases
592
+ value: Any,
593
+ /,
594
+ ) -> Any: ...
595
+
596
+
597
+ class FreeModelBeforeValidator(Protocol):
598
+ """A `@model_validator` decorated function signature. This is used when `mode='before'`."""
599
+
600
+ def __call__( # noqa: D102
601
+ self,
602
+ # this can be a dict, a model instance
603
+ # or anything else that gets passed to validate_python
604
+ # thus validators _must_ handle all cases
605
+ value: Any,
606
+ info: core_schema.ValidationInfo[Any],
607
+ /,
608
+ ) -> Any: ...
609
+
610
+
611
+ class ModelBeforeValidator(Protocol):
612
+ """A `@model_validator` decorated function signature. This is used when `mode='before'`."""
613
+
614
+ def __call__( # noqa: D102
615
+ self,
616
+ cls: Any,
617
+ # this can be a dict, a model instance
618
+ # or anything else that gets passed to validate_python
619
+ # thus validators _must_ handle all cases
620
+ value: Any,
621
+ info: core_schema.ValidationInfo[Any],
622
+ /,
623
+ ) -> Any: ...
624
+
625
+
626
+ ModelAfterValidatorWithoutInfo = Callable[[_ModelType], _ModelType]
627
+ """A `@model_validator` decorated function signature. This is used when `mode='after'` and the function does not
628
+ have info argument.
629
+ """
630
+
631
+ ModelAfterValidator = Callable[[_ModelType, core_schema.ValidationInfo[Any]], _ModelType]
632
+ """A `@model_validator` decorated function signature. This is used when `mode='after'`."""
633
+
634
+ _AnyModelWrapValidator = Union[ModelWrapValidator[_ModelType], ModelWrapValidatorWithoutInfo[_ModelType]]
635
+ _AnyModelBeforeValidator = Union[
636
+ FreeModelBeforeValidator, ModelBeforeValidator, FreeModelBeforeValidatorWithoutInfo, ModelBeforeValidatorWithoutInfo
637
+ ]
638
+ _AnyModelAfterValidator = Union[ModelAfterValidator[_ModelType], ModelAfterValidatorWithoutInfo[_ModelType]]
639
+
640
+
641
+ @overload
642
+ def model_validator(
643
+ *,
644
+ mode: Literal['wrap'],
645
+ ) -> Callable[
646
+ [_AnyModelWrapValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]
647
+ ]: ...
648
+
649
+
650
+ @overload
651
+ def model_validator(
652
+ *,
653
+ mode: Literal['before'],
654
+ ) -> Callable[
655
+ [_AnyModelBeforeValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]
656
+ ]: ...
657
+
658
+
659
+ @overload
660
+ def model_validator(
661
+ *,
662
+ mode: Literal['after'],
663
+ ) -> Callable[
664
+ [_AnyModelAfterValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]
665
+ ]: ...
666
+
667
+
668
+ def model_validator(
669
+ *,
670
+ mode: Literal['wrap', 'before', 'after'],
671
+ ) -> Any:
672
+ """!!! abstract "Usage Documentation"
673
+ [Model Validators](../concepts/validators.md#model-validators)
674
+
675
+ Decorate model methods for validation purposes.
676
+
677
+ Example usage:
678
+ ```python
679
+ from typing_extensions import Self
680
+
681
+ from pydantic import BaseModel, ValidationError, model_validator
682
+
683
+ class Square(BaseModel):
684
+ width: float
685
+ height: float
686
+
687
+ @model_validator(mode='after')
688
+ def verify_square(self) -> Self:
689
+ if self.width != self.height:
690
+ raise ValueError('width and height do not match')
691
+ return self
692
+
693
+ s = Square(width=1, height=1)
694
+ print(repr(s))
695
+ #> Square(width=1.0, height=1.0)
696
+
697
+ try:
698
+ Square(width=1, height=2)
699
+ except ValidationError as e:
700
+ print(e)
701
+ '''
702
+ 1 validation error for Square
703
+ Value error, width and height do not match [type=value_error, input_value={'width': 1, 'height': 2}, input_type=dict]
704
+ '''
705
+ ```
706
+
707
+ For more in depth examples, see [Model Validators](../concepts/validators.md#model-validators).
708
+
709
+ Args:
710
+ mode: A required string literal that specifies the validation mode.
711
+ It can be one of the following: 'wrap', 'before', or 'after'.
712
+
713
+ Returns:
714
+ A decorator that can be used to decorate a function to be used as a model validator.
715
+ """
716
+
717
+ def dec(f: Any) -> _decorators.PydanticDescriptorProxy[Any]:
718
+ # auto apply the @classmethod decorator. NOTE: in V3, do not apply the conversion for 'after' validators:
719
+ f = _decorators.ensure_classmethod_based_on_signature(f)
720
+ if mode == 'after' and isinstance(f, classmethod):
721
+ warnings.warn(
722
+ category=PydanticDeprecatedSince212,
723
+ message=(
724
+ "Using `@model_validator` with mode='after' on a classmethod is deprecated. Instead, use an instance method. "
725
+ f'See the documentation at https://docs.pydantic.dev/{version_short()}/concepts/validators/#model-after-validator.'
726
+ ),
727
+ stacklevel=2,
728
+ )
729
+
730
+ dec_info = _decorators.ModelValidatorDecoratorInfo(mode=mode)
731
+ return _decorators.PydanticDescriptorProxy(f, dec_info)
732
+
733
+ return dec
734
+
735
+
736
+ AnyType = TypeVar('AnyType')
737
+
738
+
739
+ if TYPE_CHECKING:
740
+ # If we add configurable attributes to IsInstance, we'd probably need to stop hiding it from type checkers like this
741
+ InstanceOf = Annotated[AnyType, ...] # `IsInstance[Sequence]` will be recognized by type checkers as `Sequence`
742
+
743
+ else:
744
+
745
+ @dataclasses.dataclass(**_internal_dataclass.slots_true)
746
+ class InstanceOf:
747
+ '''Generic type for annotating a type that is an instance of a given class.
748
+
749
+ Example:
750
+ ```python
751
+ from pydantic import BaseModel, InstanceOf
752
+
753
+ class Foo:
754
+ ...
755
+
756
+ class Bar(BaseModel):
757
+ foo: InstanceOf[Foo]
758
+
759
+ Bar(foo=Foo())
760
+ try:
761
+ Bar(foo=42)
762
+ except ValidationError as e:
763
+ print(e)
764
+ """
765
+ [
766
+ β”‚ {
767
+ β”‚ β”‚ 'type': 'is_instance_of',
768
+ β”‚ β”‚ 'loc': ('foo',),
769
+ β”‚ β”‚ 'msg': 'Input should be an instance of Foo',
770
+ β”‚ β”‚ 'input': 42,
771
+ β”‚ β”‚ 'ctx': {'class': 'Foo'},
772
+ β”‚ β”‚ 'url': 'https://errors.pydantic.dev/0.38.0/v/is_instance_of'
773
+ β”‚ }
774
+ ]
775
+ """
776
+ ```
777
+ '''
778
+
779
+ @classmethod
780
+ def __class_getitem__(cls, item: AnyType) -> AnyType:
781
+ return Annotated[item, cls()]
782
+
783
+ @classmethod
784
+ def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
785
+ from pydantic._internal._generate_schema import GENERATE_SCHEMA_ERRORS
786
+
787
+ # use the generic _origin_ as the second argument to isinstance when appropriate
788
+ instance_of_schema = core_schema.is_instance_schema(_generics.get_origin(source) or source)
789
+
790
+ try:
791
+ # Try to generate the "standard" schema, which will be used when loading from JSON
792
+ original_schema = handler(source)
793
+ except GENERATE_SCHEMA_ERRORS:
794
+ # If that fails, just produce a schema that can validate from python
795
+ return instance_of_schema
796
+ else:
797
+ # Use the "original" approach to serialization
798
+ instance_of_schema['serialization'] = core_schema.wrap_serializer_function_ser_schema(
799
+ function=lambda v, h: h(v), schema=original_schema
800
+ )
801
+ return core_schema.json_or_python_schema(python_schema=instance_of_schema, json_schema=original_schema)
802
+
803
+ __hash__ = object.__hash__
804
+
805
+
806
+ if TYPE_CHECKING:
807
+ SkipValidation = Annotated[AnyType, ...] # SkipValidation[list[str]] will be treated by type checkers as list[str]
808
+ else:
809
+
810
+ @dataclasses.dataclass(**_internal_dataclass.slots_true)
811
+ class SkipValidation:
812
+ """If this is applied as an annotation (e.g., via `x: Annotated[int, SkipValidation]`), validation will be
813
+ skipped. You can also use `SkipValidation[int]` as a shorthand for `Annotated[int, SkipValidation]`.
814
+
815
+ This can be useful if you want to use a type annotation for documentation/IDE/type-checking purposes,
816
+ and know that it is safe to skip validation for one or more of the fields.
817
+
818
+ Because this converts the validation schema to `any_schema`, subsequent annotation-applied transformations
819
+ may not have the expected effects. Therefore, when used, this annotation should generally be the final
820
+ annotation applied to a type.
821
+ """
822
+
823
+ def __class_getitem__(cls, item: Any) -> Any:
824
+ return Annotated[item, SkipValidation()]
825
+
826
+ @classmethod
827
+ def __get_pydantic_core_schema__(cls, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
828
+ with warnings.catch_warnings():
829
+ warnings.simplefilter('ignore', ArbitraryTypeWarning)
830
+ original_schema = handler(source)
831
+ metadata = {'pydantic_js_annotation_functions': [lambda _c, h: h(original_schema)]}
832
+ return core_schema.any_schema(
833
+ metadata=metadata,
834
+ serialization=core_schema.wrap_serializer_function_ser_schema(
835
+ function=lambda v, h: h(v), schema=original_schema
836
+ ),
837
+ )
838
+
839
+ __hash__ = object.__hash__
840
+
841
+
842
+ _FromTypeT = TypeVar('_FromTypeT')
843
+
844
+
845
+ class ValidateAs:
846
+ """A helper class to validate a custom type from a type that is natively supported by Pydantic.
847
+
848
+ Args:
849
+ from_type: The type natively supported by Pydantic to use to perform validation.
850
+ instantiation_hook: A callable taking the validated type as an argument, and returning
851
+ the populated custom type.
852
+
853
+ Example:
854
+ ```python {lint="skip"}
855
+ from typing import Annotated
856
+
857
+ from pydantic import BaseModel, TypeAdapter, ValidateAs
858
+
859
+ class MyCls:
860
+ def __init__(self, a: int) -> None:
861
+ self.a = a
862
+
863
+ def __repr__(self) -> str:
864
+ return f"MyCls(a={self.a})"
865
+
866
+ class Model(BaseModel):
867
+ a: int
868
+
869
+
870
+ ta = TypeAdapter(
871
+ Annotated[MyCls, ValidateAs(Model, lambda v: MyCls(a=v.a))]
872
+ )
873
+
874
+ print(ta.validate_python({'a': 1}))
875
+ #> MyCls(a=1)
876
+ ```
877
+ """
878
+
879
+ # TODO: make use of PEP 747
880
+ def __init__(self, from_type: type[_FromTypeT], /, instantiation_hook: Callable[[_FromTypeT], Any]) -> None:
881
+ self.from_type = from_type
882
+ self.instantiation_hook = instantiation_hook
883
+
884
+ def __get_pydantic_core_schema__(self, source: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
885
+ schema = handler(self.from_type)
886
+ return core_schema.no_info_after_validator_function(
887
+ self.instantiation_hook,
888
+ schema=schema,
889
+ )
.mcp-venv/lib/python3.13/site-packages/pydantic/generics.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """The `generics` module is a backport module from V1."""
2
+
3
+ from ._migration import getattr_migration
4
+
5
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/json.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """The `json` module is a backport module from V1."""
2
+
3
+ from ._migration import getattr_migration
4
+
5
+ __getattr__ = getattr_migration(__name__)
.mcp-venv/lib/python3.13/site-packages/pydantic/json_schema.py ADDED
The diff for this file is too large to render. See raw diff