schemathesis 4.1.4__py3-none-any.whl → 4.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. schemathesis/cli/commands/run/executor.py +1 -1
  2. schemathesis/cli/commands/run/handlers/base.py +28 -1
  3. schemathesis/cli/commands/run/handlers/cassettes.py +109 -137
  4. schemathesis/cli/commands/run/handlers/junitxml.py +5 -6
  5. schemathesis/cli/commands/run/handlers/output.py +7 -1
  6. schemathesis/cli/ext/fs.py +1 -1
  7. schemathesis/config/_diff_base.py +3 -1
  8. schemathesis/config/_operations.py +2 -0
  9. schemathesis/config/_phases.py +21 -4
  10. schemathesis/config/_projects.py +10 -2
  11. schemathesis/core/adapter.py +34 -0
  12. schemathesis/core/errors.py +29 -5
  13. schemathesis/core/jsonschema/__init__.py +13 -0
  14. schemathesis/core/jsonschema/bundler.py +163 -0
  15. schemathesis/{specs/openapi/constants.py → core/jsonschema/keywords.py} +0 -8
  16. schemathesis/core/jsonschema/references.py +122 -0
  17. schemathesis/core/jsonschema/types.py +41 -0
  18. schemathesis/core/media_types.py +6 -4
  19. schemathesis/core/parameters.py +37 -0
  20. schemathesis/core/transforms.py +25 -2
  21. schemathesis/core/validation.py +19 -0
  22. schemathesis/engine/context.py +1 -1
  23. schemathesis/engine/errors.py +11 -18
  24. schemathesis/engine/phases/stateful/_executor.py +1 -1
  25. schemathesis/engine/phases/unit/_executor.py +30 -13
  26. schemathesis/errors.py +4 -0
  27. schemathesis/filters.py +2 -2
  28. schemathesis/generation/coverage.py +87 -11
  29. schemathesis/generation/hypothesis/__init__.py +79 -2
  30. schemathesis/generation/hypothesis/builder.py +108 -70
  31. schemathesis/generation/meta.py +5 -14
  32. schemathesis/generation/overrides.py +17 -17
  33. schemathesis/pytest/lazy.py +1 -1
  34. schemathesis/pytest/plugin.py +1 -6
  35. schemathesis/schemas.py +22 -72
  36. schemathesis/specs/graphql/schemas.py +27 -16
  37. schemathesis/specs/openapi/_hypothesis.py +83 -68
  38. schemathesis/specs/openapi/adapter/__init__.py +10 -0
  39. schemathesis/specs/openapi/adapter/parameters.py +504 -0
  40. schemathesis/specs/openapi/adapter/protocol.py +57 -0
  41. schemathesis/specs/openapi/adapter/references.py +19 -0
  42. schemathesis/specs/openapi/adapter/responses.py +329 -0
  43. schemathesis/specs/openapi/adapter/security.py +141 -0
  44. schemathesis/specs/openapi/adapter/v2.py +28 -0
  45. schemathesis/specs/openapi/adapter/v3_0.py +28 -0
  46. schemathesis/specs/openapi/adapter/v3_1.py +28 -0
  47. schemathesis/specs/openapi/checks.py +99 -90
  48. schemathesis/specs/openapi/converter.py +114 -27
  49. schemathesis/specs/openapi/examples.py +210 -168
  50. schemathesis/specs/openapi/negative/__init__.py +12 -7
  51. schemathesis/specs/openapi/negative/mutations.py +68 -40
  52. schemathesis/specs/openapi/references.py +2 -175
  53. schemathesis/specs/openapi/schemas.py +142 -490
  54. schemathesis/specs/openapi/serialization.py +15 -7
  55. schemathesis/specs/openapi/stateful/__init__.py +17 -12
  56. schemathesis/specs/openapi/stateful/inference.py +13 -11
  57. schemathesis/specs/openapi/stateful/links.py +5 -20
  58. schemathesis/specs/openapi/types/__init__.py +3 -0
  59. schemathesis/specs/openapi/types/v3.py +68 -0
  60. schemathesis/specs/openapi/utils.py +1 -13
  61. schemathesis/transport/requests.py +3 -11
  62. schemathesis/transport/serialization.py +63 -27
  63. schemathesis/transport/wsgi.py +1 -8
  64. {schemathesis-4.1.4.dist-info → schemathesis-4.2.1.dist-info}/METADATA +2 -2
  65. {schemathesis-4.1.4.dist-info → schemathesis-4.2.1.dist-info}/RECORD +68 -53
  66. schemathesis/specs/openapi/parameters.py +0 -405
  67. schemathesis/specs/openapi/security.py +0 -162
  68. {schemathesis-4.1.4.dist-info → schemathesis-4.2.1.dist-info}/WHEEL +0 -0
  69. {schemathesis-4.1.4.dist-info → schemathesis-4.2.1.dist-info}/entry_points.txt +0 -0
  70. {schemathesis-4.1.4.dist-info → schemathesis-4.2.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,11 +1,11 @@
1
1
  schemathesis/__init__.py,sha256=QqVUCBQr-RDEstgCZLsxzIa9HJslVSeijrm9gES4b_0,1423
2
2
  schemathesis/auths.py,sha256=JdEwPRS9WKmPcxzGXYYz9pjlIUMQYCfif7ZJU0Kde-I,16400
3
3
  schemathesis/checks.py,sha256=GTdejjXDooAOuq66nvCK3i-AMPBuU-_-aNeSeL9JIlc,6561
4
- schemathesis/errors.py,sha256=T8nobEi5tQX_SkwaYb8JFoIlF9F_vOQVprZ8EVPAhjA,931
5
- schemathesis/filters.py,sha256=Nk1Z6_L0fJBIzFGwjUhx9oDHJiGn-kVxbAXWeN9gRcQ,13525
4
+ schemathesis/errors.py,sha256=K3irHIZkrBH2-9LIjlgXlm8RNC41Nffd39ncfwagUvw,1053
5
+ schemathesis/filters.py,sha256=IevPA5A04GfRLLjmkFLZ0CLhjNO3RmpZq_yw6MqjLIA,13515
6
6
  schemathesis/hooks.py,sha256=q2wqYNgpMCO8ImSBkbrWDSwN0BSELelqJMgAAgGvv2M,14836
7
7
  schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- schemathesis/schemas.py,sha256=i0L6jYulGGASD1RiQsA6sOTNt1v812KHSZKIhnuX34s,28965
8
+ schemathesis/schemas.py,sha256=jq2KSphzfLn63FNROrc3GwukTDt4ih4-RmF0Z4WSpu8,27582
9
9
  schemathesis/cli/__init__.py,sha256=U9gjzWWpiFhaqevPjZbwyTNjABdpvXETI4HgwdGKnvs,877
10
10
  schemathesis/cli/__main__.py,sha256=MWaenjaUTZIfNPFzKmnkTiawUri7DVldtg3mirLwzU8,92
11
11
  schemathesis/cli/constants.py,sha256=CVcQNHEiX-joAQmyuEVKWPOSxDHsOw_EXXZsEclzLuY,341
@@ -15,84 +15,91 @@ schemathesis/cli/commands/data.py,sha256=_ALywjIeCZjuaoDQFy-Kj8RZkEGqXd-Y95O47h8
15
15
  schemathesis/cli/commands/run/__init__.py,sha256=_ApiSVh9q-TsJQ_-IiVBNnLCtTCDMTnOLwuJhOvbCp4,18925
16
16
  schemathesis/cli/commands/run/context.py,sha256=taegOHWc_B-HDwiU1R9Oi4q57mdfLXc-B954QUj8t7A,7984
17
17
  schemathesis/cli/commands/run/events.py,sha256=ew0TQOc9T2YBZynYWv95k9yfAk8-hGuZDLMxjT8EhvY,1595
18
- schemathesis/cli/commands/run/executor.py,sha256=kFbZw583SZ-jqjv8goTp2yEJOpZ_bzecyTeZvdc6qTE,5327
18
+ schemathesis/cli/commands/run/executor.py,sha256=_koznTX0DoELPN_1mxr9K_Qg7-9MPXWdld1MFn3YG_Y,5329
19
19
  schemathesis/cli/commands/run/filters.py,sha256=pzkNRcf5vLPSsMfnvt711GNzRSBK5iZIFjPA0fiH1N4,1701
20
20
  schemathesis/cli/commands/run/loaders.py,sha256=6j0ez7wduAUYbUT28ELKxMf-dYEWr_67m_KIuTSyNGk,4358
21
21
  schemathesis/cli/commands/run/validation.py,sha256=DQaMiBLN2tYT9hONvv8xnyPvNXZH768UlOdUxTd5kZs,9193
22
22
  schemathesis/cli/commands/run/handlers/__init__.py,sha256=TPZ3KdGi8m0fjlN0GjA31MAXXn1qI7uU4FtiDwroXZI,1915
23
- schemathesis/cli/commands/run/handlers/base.py,sha256=yDsTtCiztLksfk7cRzg8JlaAVOfS-zwK3tsJMOXAFyc,530
24
- schemathesis/cli/commands/run/handlers/cassettes.py,sha256=_PBynFlQ5wSg7hEG316hOX4gbVrv6CpYHdFrcG1qeiA,19477
25
- schemathesis/cli/commands/run/handlers/junitxml.py,sha256=ydk6Ofj-Uti6H8EucT4Snp85cmTA5W7uVpKkoHrIDKE,2586
26
- schemathesis/cli/commands/run/handlers/output.py,sha256=p1_vXzxrrVuC8cN3PV3e7PUjstReDInsfAdXeCUsn08,63727
23
+ schemathesis/cli/commands/run/handlers/base.py,sha256=qUtDvtr3F6were_BznfnaPpMibGJMnQ5CA9aEzcIUBc,1306
24
+ schemathesis/cli/commands/run/handlers/cassettes.py,sha256=LzvQp--Ub5MXF7etet7fQD0Ufloh1R0j2X1o9dT8Z4k,19253
25
+ schemathesis/cli/commands/run/handlers/junitxml.py,sha256=qiFvM4-SlM67sep003SkLqPslzaEb4nOm3bkzw-DO-Q,2602
26
+ schemathesis/cli/commands/run/handlers/output.py,sha256=TwK82zNpIZ7Q76ggTp8gcW2clzrw0WBmHFJMcvYL1nE,63927
27
27
  schemathesis/cli/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- schemathesis/cli/ext/fs.py,sha256=3lvoAsEDDdih75ITJJNxemd3nwxX55gGWrI7uDxm0cM,447
28
+ schemathesis/cli/ext/fs.py,sha256=dHQYBjQozQmuSSfXVp-2KWFK0ESOb_w-lV2SptfMfco,461
29
29
  schemathesis/cli/ext/groups.py,sha256=kQ37t6qeArcKaY2y5VxyK3_KwAkBKCVm58IYV8gewds,2720
30
30
  schemathesis/cli/ext/options.py,sha256=6yYwZNJL__FCEEL7kI3r5MbVmbp3ZeQjm7DrZ6J_h7s,3347
31
31
  schemathesis/config/__init__.py,sha256=Ff-mcdwCatFIS_WpJNpSe-gl7ez0-m_s4F2_4Teg2eM,6240
32
32
  schemathesis/config/_auth.py,sha256=83RLVPm97W2thbn-yi01Rt94YwOxLG_a5VoxhEfjUjs,1528
33
33
  schemathesis/config/_checks.py,sha256=F0r16eSSiICvoiTUkNNOE2PH73EGd8bikoeZdME_3Yw,10763
34
- schemathesis/config/_diff_base.py,sha256=-XqS6cTzZC5fplz8_2RSZHDMSAPJhBBIEP6H8wcgHmo,4221
34
+ schemathesis/config/_diff_base.py,sha256=U7wuE4480EjP3K16mfC528TP5q7Q5IwAZwZLqRIrS1E,4300
35
35
  schemathesis/config/_env.py,sha256=8XfIyrnGNQuCDnfG0lwmKRFbasRUjgeQGBAMupsmtOU,613
36
36
  schemathesis/config/_error.py,sha256=jfv9chQ4NGoDYypszNGymr0zxXVo65yP0AWK1WVEPIM,5781
37
37
  schemathesis/config/_generation.py,sha256=giWs4z17z9nRe_9Z3mAZ3LEoyh4hkcJnlAA6LSy6iEo,5210
38
38
  schemathesis/config/_health_check.py,sha256=zC9inla5ibMBlEy5WyM4_TME7ju_KH3Bwfo21RI3Gks,561
39
- schemathesis/config/_operations.py,sha256=RhTr0EtJZV3z28-dh9-JUpLePQpj-eG6B952ykWoHaQ,12322
39
+ schemathesis/config/_operations.py,sha256=JvfMkieYBkbEmZRb4cTvQLfvHQLhmsxa3GXzgjOtmFc,12383
40
40
  schemathesis/config/_output.py,sha256=3G9SOi-4oNcQPHeNRG3HggFCwvcKOW1kF28a9m0H-pU,4434
41
41
  schemathesis/config/_parameters.py,sha256=i76Hwaf834fBAMmtKfKTl1SFCicJ-Y-5tZt5QNGW2fA,618
42
- schemathesis/config/_phases.py,sha256=AR5AYBF12xr4iUTCJIwaFcHqnlo7o7QhHI1l1gof4uw,7755
43
- schemathesis/config/_projects.py,sha256=NAUTp48OLr4wxWaLpgDoPT5NAPG40LvmKug7BNt4quk,20201
42
+ schemathesis/config/_phases.py,sha256=JgDyh579iR301OpD93L3WBeEpYUrNxD7R59WZE1X2MA,8390
43
+ schemathesis/config/_projects.py,sha256=MpXFBIkNAWAzE_NWQISI9R8dlbCVId2eXGdIqZBgK98,20468
44
44
  schemathesis/config/_rate_limit.py,sha256=ekEW-jP_Ichk_O6hYpj-h2TTTKfp7Fm0nyFUbvlWcbA,456
45
45
  schemathesis/config/_report.py,sha256=ZECDpaCY4WWHD5UbjvgZoSjLz-rlTvfd5Ivzdgzqf2I,3891
46
46
  schemathesis/config/_validator.py,sha256=IcE8geFZ0ZwR18rkIRs25i7pTl7Z84XbjYGUB-mqReU,258
47
47
  schemathesis/config/_warnings.py,sha256=sI0VZcTj3dOnphhBwYwU_KTagxr89HGWTtQ99HcY84k,772
48
48
  schemathesis/config/schema.json,sha256=3CRSBfUK2vLVl1h5PfeK_YDdEoBZSojYl8Q1kT-ITLE,19846
49
49
  schemathesis/core/__init__.py,sha256=h4gmDePIPvPiVuYxnjrpPKytSZPi6fZeVdTG6c822E4,1973
50
+ schemathesis/core/adapter.py,sha256=zwJ0vNhalrF9sYXN8_0pMSkJ71GPDnUBKqBCVsnuVIY,951
50
51
  schemathesis/core/compat.py,sha256=9BWCrFoqN2sJIaiht_anxe8kLjYMR7t0iiOkXqLRUZ8,1058
51
52
  schemathesis/core/control.py,sha256=IzwIc8HIAEMtZWW0Q0iXI7T1niBpjvcLlbuwOSmy5O8,130
52
53
  schemathesis/core/curl.py,sha256=jrPL9KpNHteyJ6A1oxJRSkL5bfuBeuPs3xh9Z_ml2cE,1892
53
54
  schemathesis/core/deserialization.py,sha256=qjXUPaz_mc1OSgXzTUSkC8tuVR8wgVQtb9g3CcAF6D0,2951
54
- schemathesis/core/errors.py,sha256=pwiyGhX7tId88Toe2H4ZYsCDc_OvUJtW8Wv-xDv2UD4,16361
55
+ schemathesis/core/errors.py,sha256=CeZtzZOwBELzf-T_lLkwLU9Wtla50HuF_17CNJzgNPU,17087
55
56
  schemathesis/core/failures.py,sha256=yFpAxWdEnm0Ri8z8RqRI9H7vcLH5ztOeSIi4m4SGx5g,8996
56
57
  schemathesis/core/fs.py,sha256=ItQT0_cVwjDdJX9IiI7EnU75NI2H3_DCEyyUjzg_BgI,472
57
58
  schemathesis/core/hooks.py,sha256=qhbkkRSf8URJ4LKv2wmKRINKpquUOgxQzWBHKWRWo3Q,475
58
59
  schemathesis/core/lazy_import.py,sha256=aMhWYgbU2JOltyWBb32vnWBb6kykOghucEzI_F70yVE,470
59
60
  schemathesis/core/loaders.py,sha256=04WRkiWfWPH4xjgi0nMO1NyjGw8zvraIq6PqMqCq1c4,3590
60
61
  schemathesis/core/marks.py,sha256=SH7jsVuNRJjx2gZN9Ze5MY01u7FJiHeO0iruzKi5rm4,2135
61
- schemathesis/core/media_types.py,sha256=ThdAikBttdRD1RB9-83rMmtG_z-BdW8xidUxzhgdUqI,2168
62
+ schemathesis/core/media_types.py,sha256=VN1QhgfwBHpTw0CQquzAfhJstxXIXBzSSy0NZmAUcAo,2185
63
+ schemathesis/core/parameters.py,sha256=20pd4DLW1uXs61YuESKG1Fx9QJJQN3JY7CKnOJMgDb4,790
62
64
  schemathesis/core/rate_limit.py,sha256=7tg9Znk11erTfw8-ANutjEmu7hbfUHZx_iEdkoaP174,1757
63
65
  schemathesis/core/registries.py,sha256=T4jZB4y3zBHdeSgQc0pRbgSeMblvO-6z4I3zmzIfTi0,811
64
66
  schemathesis/core/result.py,sha256=d449YvyONjqjDs-A5DAPgtAI96iT753K8sU6_1HLo2Q,461
65
- schemathesis/core/transforms.py,sha256=63aeLkR93r3krq4CwYtDcoS_pFBky4L16c9DcFsBHuE,3535
67
+ schemathesis/core/transforms.py,sha256=rgr22JdVjFj0di9Oeo94Leo1JmdLJdCjnA-eGpfszV8,4095
66
68
  schemathesis/core/transport.py,sha256=LQcamAkFqJ0HuXQzepevAq2MCJW-uq5Nm-HE9yc7HMI,7503
67
- schemathesis/core/validation.py,sha256=rnhzsqWukMWyrc7sRm0kZNHTePoPCQ3A4kLpLxrb0jM,1641
69
+ schemathesis/core/validation.py,sha256=b0USkKzkWvdz3jOW1JXYc_TfYshfKZeP7xAUnMqcNoc,2303
68
70
  schemathesis/core/version.py,sha256=dOBUWrY3-uA2NQXJp9z7EtZgkR6jYeLg8sMhQCL1mcI,205
71
+ schemathesis/core/jsonschema/__init__.py,sha256=gBZGsXIpK2EFfcp8x0b69dqzWAm2OeZHepKImkkLvoE,320
72
+ schemathesis/core/jsonschema/bundler.py,sha256=ECNAHrXl5nh52crm5Qu1QvRWVV2Vv9gU8H722oKA7k0,7711
73
+ schemathesis/core/jsonschema/keywords.py,sha256=pjseXTfH9OItNs_Qq6ubkhNWQOrxTnwHmrP_jxrHeJU,631
74
+ schemathesis/core/jsonschema/references.py,sha256=uB7-DGYhLFqbIAvuO-IDc9xSatoGw54FOYn4xE4qE6A,4667
75
+ schemathesis/core/jsonschema/types.py,sha256=C7f9g8yKFuoxC5_0YNIh8QAyGU0-tj8pzTMfMDjjjVM,1248
69
76
  schemathesis/core/output/__init__.py,sha256=SiHqONFskXl73AtP5dV29L14nZoKo7B-IeG52KZB32M,1446
70
77
  schemathesis/core/output/sanitization.py,sha256=Ev3tae8dVwsYd7yVb2_1VBFYs92WFsQ4Eu1fGaymItE,2013
71
78
  schemathesis/engine/__init__.py,sha256=QaFE-FinaTAaarteADo2RRMJ-Sz6hZB9TzD5KjMinIA,706
72
- schemathesis/engine/context.py,sha256=Kz-Z_CEZPDgOe1uOJU7ElyjY7Q2E6V9rtFi-tlFov8I,5367
79
+ schemathesis/engine/context.py,sha256=40L4rEu34Y6a4jrag5O7N7sYh3qG5asE2ErF8w9-ktA,5362
73
80
  schemathesis/engine/control.py,sha256=FXzP8dxL47j1Giqpy2-Bsr_MdMw9YiATSK_UfpFwDtk,1348
74
81
  schemathesis/engine/core.py,sha256=qlPHnZVq2RrUe93fOciXd1hC3E1gVyF2BIWMPMeLIj8,6655
75
- schemathesis/engine/errors.py,sha256=wbFTOE0pmpU79oOzx1l-ypKG92wdFySmNzrN_KTNizM,19168
82
+ schemathesis/engine/errors.py,sha256=FlpEk44WRLzRkdK9m37z93EQuY3kbeMIQRGwU5e3Qm4,19005
76
83
  schemathesis/engine/events.py,sha256=jpCtMkWWfNe2jUeZh_Ly_wfZEF44EOodL-I_W4C9rgg,6594
77
84
  schemathesis/engine/observations.py,sha256=T-5R8GeVIqvxpCMxc6vZ04UUxUTx3w7689r3Dc6bIcE,1416
78
85
  schemathesis/engine/recorder.py,sha256=K3HfMARrT5mPWXPnYebjjcq5CcsBRhMrtZwEL9_Lvtg,8432
79
86
  schemathesis/engine/phases/__init__.py,sha256=7Yp7dQbd6-K9pavIJeURg6jiNeMpW8UU-Iiikr668ts,3278
80
87
  schemathesis/engine/phases/probes.py,sha256=YogjJcZJcTMS8sMdGnG4oXKmMUj_4r_J7MY-BBJtCRU,5690
81
88
  schemathesis/engine/phases/stateful/__init__.py,sha256=Lz1rgNqCfUSIz173XqCGsiMuUI5bh4L-RIFexU1-c_Q,2461
82
- schemathesis/engine/phases/stateful/_executor.py,sha256=6YOgAGynP4UKKTITe7S39SCcnRp5OXQ7fCc8BJIFW3A,15592
89
+ schemathesis/engine/phases/stateful/_executor.py,sha256=yRpUJqKLTKMVRy7hEXPwmI23CtgGIprz341lCJwvTrU,15613
83
90
  schemathesis/engine/phases/stateful/context.py,sha256=A7X1SLDOWFpCvFN9IiIeNVZM0emjqatmJL_k9UsO7vM,2946
84
91
  schemathesis/engine/phases/unit/__init__.py,sha256=9dDcxyj887pktnE9YDIPNaR-vc7iqKQWIrFr77SbUTQ,8786
85
- schemathesis/engine/phases/unit/_executor.py,sha256=pqUISTWvnXb61rgrnzwlFn7PyR-ZsGis2kbRgBMH4EA,16519
92
+ schemathesis/engine/phases/unit/_executor.py,sha256=UkOcmR23rl5PSIuNMjthZxadbAOHYSmTWft7Wa91yLs,17206
86
93
  schemathesis/engine/phases/unit/_pool.py,sha256=iU0hdHDmohPnEv7_S1emcabuzbTf-Cznqwn0pGQ5wNQ,2480
87
94
  schemathesis/generation/__init__.py,sha256=tvNO2FLiY8z3fZ_kL_QJhSgzXfnT4UqwSXMHCwfLI0g,645
88
95
  schemathesis/generation/case.py,sha256=Qc2_5JrWuUkCzAFTTgnVqNUJ2sioslmINTXiY7nHHgA,12326
89
- schemathesis/generation/coverage.py,sha256=_mqzT_ZtnfvOM0I9X4Qul-uw__U-gVqL2x7OOVADACU,56643
90
- schemathesis/generation/meta.py,sha256=yYR7EB1f5n7RrzWHZ6YATepurnnc_hEe7HnztRbaaA0,2699
96
+ schemathesis/generation/coverage.py,sha256=dZYX0gkHDHDenrubVQ58P3ww2xf91fEqk9s54AIokw4,59699
97
+ schemathesis/generation/meta.py,sha256=tXhUZBEdpQMn68uMx1SW8Vv59Uf6Wl6yzs-VB9lu_8o,2589
91
98
  schemathesis/generation/metrics.py,sha256=cZU5HdeAMcLFEDnTbNE56NuNq4P0N4ew-g1NEz5-kt4,2836
92
99
  schemathesis/generation/modes.py,sha256=Q1fhjWr3zxabU5qdtLvKfpMFZJAwlW9pnxgenjeXTyU,481
93
- schemathesis/generation/overrides.py,sha256=OBWqDQPreiliaf2M-oyXppVKHoJkCRzxtwSJx1b6AFw,3759
94
- schemathesis/generation/hypothesis/__init__.py,sha256=jK3G4i0SdcyhqwPQg91RH_yg437lSY-smeIQ-wZLWPc,1959
95
- schemathesis/generation/hypothesis/builder.py,sha256=HOZLev-b-fkaFwDIxQHlpS59y7anyK9mJ-qw5IeQZqY,36777
100
+ schemathesis/generation/overrides.py,sha256=xI2djHsa42fzP32xpxgxO52INixKagf5DjDAWJYswM8,3890
101
+ schemathesis/generation/hypothesis/__init__.py,sha256=Dfdz6_Wa7ez6GxrMBxnWQnLaNjPUweTxfi01jiFqso4,4900
102
+ schemathesis/generation/hypothesis/builder.py,sha256=ZdY68aDGeZLLtIld288KF_O6ardFKZdFMBogwltTx2o,38362
96
103
  schemathesis/generation/hypothesis/examples.py,sha256=6eGaKUEC3elmKsaqfKj1sLvM8EHc-PWT4NRBq4NI0Rs,1409
97
104
  schemathesis/generation/hypothesis/given.py,sha256=sTZR1of6XaHAPWtHx2_WLlZ50M8D5Rjux0GmWkWjDq4,2337
98
105
  schemathesis/generation/hypothesis/reporting.py,sha256=uDVow6Ya8YFkqQuOqRsjbzsbyP4KKfr3jA7ZaY4FuKY,279
@@ -109,9 +116,9 @@ schemathesis/openapi/generation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
109
116
  schemathesis/openapi/generation/filters.py,sha256=pY9cUZdL_kQK80Z2aylTOqqa12zmaYUlYC5BfYgeQMk,2395
110
117
  schemathesis/pytest/__init__.py,sha256=7W0q-Thcw03IAQfXE_Mo8JPZpUdHJzfu85fjK1ZdfQM,88
111
118
  schemathesis/pytest/control_flow.py,sha256=F8rAPsPeNv_sJiJgbZYtTpwKWjauZmqFUaKroY2GmQI,217
112
- schemathesis/pytest/lazy.py,sha256=u58q0orI0zisivLJKJkSo53RaQMPLSMiE0vJ1TQ9_uA,11073
119
+ schemathesis/pytest/lazy.py,sha256=wP0sqcVFcD-OjDIFUpYdJdFQ-BY18CVyL0iB6eHiWRw,11088
113
120
  schemathesis/pytest/loaders.py,sha256=Sbv8e5F77_x4amLP50iwubfm6kpOhx7LhLFGsVXW5Ys,925
114
- schemathesis/pytest/plugin.py,sha256=-c92Qi2aEvW45KLAzHj9EDXbY_mYq5B5ZdkRY9Ks_DY,14463
121
+ schemathesis/pytest/plugin.py,sha256=8VaaYoO4RtgtZLOAHiheFNjd0xceyKe0U1n6AV5s9kY,14253
115
122
  schemathesis/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
123
  schemathesis/python/asgi.py,sha256=5PyvuTBaivvyPUEi3pwJni91K1kX5Zc0u9c6c1D8a1Q,287
117
124
  schemathesis/python/wsgi.py,sha256=uShAgo_NChbfYaV1117e6UHp0MTg7jaR0Sy_to3Jmf8,219
@@ -119,46 +126,54 @@ schemathesis/specs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
119
126
  schemathesis/specs/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
120
127
  schemathesis/specs/graphql/nodes.py,sha256=bE3G1kNmqJ8OV4igBvIK-UORrkQA6Nofduf87O3TD9I,541
121
128
  schemathesis/specs/graphql/scalars.py,sha256=6lew8mnwhrtg23leiEbG43mLGPLlRln8mClCY94XpDA,2680
122
- schemathesis/specs/graphql/schemas.py,sha256=B6FULWIIWoN_gx9OeQOd-6qWsz9yVg5h1XlxFe06XPM,14097
129
+ schemathesis/specs/graphql/schemas.py,sha256=GKJcnTAT1wUzzUr3r6wiTfiAdFLcgFQjYRRz7x4VQl0,14457
123
130
  schemathesis/specs/graphql/validation.py,sha256=-W1Noc1MQmTb4RX-gNXMeU2qkgso4mzVfHxtdLkCPKM,1422
124
131
  schemathesis/specs/openapi/__init__.py,sha256=C5HOsfuDJGq_3mv8CRBvRvb0Diy1p0BFdqyEXMS-loE,238
125
- schemathesis/specs/openapi/_hypothesis.py,sha256=XK-g2284wCsqOuPhubpE-PQ5_YotUwNodAnjeHs_-R0,21712
126
- schemathesis/specs/openapi/checks.py,sha256=CVUBhJgdVZZdgCIydsO0OYf3K4gGgnYw6XDSJo3q6OU,30623
127
- schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
128
- schemathesis/specs/openapi/converter.py,sha256=LkpCCAxZzET4Qa_3YStSNuhGlsm5G6TVwpxYu6lPO4g,4169
132
+ schemathesis/specs/openapi/_hypothesis.py,sha256=g5476s_ArzheWKHHlOfKwx46tqoiehP3KaQM7L_AoEI,22359
133
+ schemathesis/specs/openapi/checks.py,sha256=YYV6j6idyw2ubY4sLp-avs2OVEkAWeIihjT0xiV1RRA,30669
134
+ schemathesis/specs/openapi/converter.py,sha256=4a6-8STT5snF7B-t6IsOIGdK5rV16oNqsdvWL7VFf2M,6472
129
135
  schemathesis/specs/openapi/definitions.py,sha256=8htclglV3fW6JPBqs59lgM4LnA25Mm9IptXBPb_qUT0,93949
130
- schemathesis/specs/openapi/examples.py,sha256=JsAy8Dexw36SUAO5MBB44ji3zEK9Y_JU5d2LRshjEI4,22023
136
+ schemathesis/specs/openapi/examples.py,sha256=UquzOwy5QhmpHjFXv_QnZGpWZTU-N4CkQ1PQOxACIb8,22981
131
137
  schemathesis/specs/openapi/formats.py,sha256=4tYRdckauHxkJCmOhmdwDq_eOpHPaKloi89lzMPbPzw,3975
132
138
  schemathesis/specs/openapi/media_types.py,sha256=F5M6TKl0s6Z5X8mZpPsWDEdPBvxclKRcUOc41eEwKbo,2472
133
- schemathesis/specs/openapi/parameters.py,sha256=XpuZ2sex2aYUzKDK17GXVNWFBmvamuyVtloQ1oGQhLk,14468
134
139
  schemathesis/specs/openapi/patterns.py,sha256=GqPZEXMRdWENQxanWjBOalIZ2MQUjuxk21kmdiI703E,18027
135
- schemathesis/specs/openapi/references.py,sha256=40YcDExPLR2B8EOwt-Csw-5MYFi2xj_DXf91J0Pc9d4,8855
136
- schemathesis/specs/openapi/schemas.py,sha256=qJ0ChkZuXQafQ-nPwMzckSk3iC32H2O5W9Cbd7DN_2I,51379
137
- schemathesis/specs/openapi/security.py,sha256=Vv5Y76hM49ZqLlivViSURKQlxDd1F_FQRj5gEUfyBU0,7552
138
- schemathesis/specs/openapi/serialization.py,sha256=VdDLmeHqxlWM4cxQQcCkvrU6XurivolwEEaT13ohelA,11972
139
- schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
140
+ schemathesis/specs/openapi/references.py,sha256=AW1laU23BkiRf0EEFM538vyVFLXycGUiucGVV461le0,1927
141
+ schemathesis/specs/openapi/schemas.py,sha256=vwBgw7kznPlQJIufgJ48oRxCzDFkUWKfb4uK7rMZUT4,33704
142
+ schemathesis/specs/openapi/serialization.py,sha256=RPNdadne5wdhsGmjSvgKLRF58wpzpRx3wura8PsHM3o,12152
143
+ schemathesis/specs/openapi/utils.py,sha256=XkOJT8qD-6uhq-Tmwxk_xYku1Gy5F9pKL3ldNg_DRZw,522
144
+ schemathesis/specs/openapi/adapter/__init__.py,sha256=YEovBgLjnXd3WGPMJXq0KbSGHezkRlEv4dNRO7_evfk,249
145
+ schemathesis/specs/openapi/adapter/parameters.py,sha256=jX6tQuJ8k0Ml9w4jAquncGv2ZbJzsG2fUwLu6Grmlq8,18614
146
+ schemathesis/specs/openapi/adapter/protocol.py,sha256=6Ioe563EL_ZAyRe8Kj8AE6l6grpFbIVn4C3GDuqizTA,2567
147
+ schemathesis/specs/openapi/adapter/references.py,sha256=6M59pJy_U_sLh3Xzgu6-izWXtz3bjXnqJYSD65wRHtk,549
148
+ schemathesis/specs/openapi/adapter/responses.py,sha256=bti5FhqZaq_8g95kdpYx5lD2_1cUZEq56yIjlASji8I,12455
149
+ schemathesis/specs/openapi/adapter/security.py,sha256=W3cqlbs80NxF9SAavOi7BhtNGzdxHO476lYxiWN0D08,4945
150
+ schemathesis/specs/openapi/adapter/v2.py,sha256=tWbq3EuJnSomWylPw_BT6TfEw8sIJQEFnVKpxCiq5XE,1153
151
+ schemathesis/specs/openapi/adapter/v3_0.py,sha256=Q6b1Rfajx2tiO5W6uEwLosxQcdFqVgT5TS4r2jYFwg4,1145
152
+ schemathesis/specs/openapi/adapter/v3_1.py,sha256=lvLvoxMC_AEwm8c_d3RGHk0BptaOFCdDcV8RrH-uOGw,1155
140
153
  schemathesis/specs/openapi/expressions/__init__.py,sha256=hfuRtXD75tQFhzSo6QgDZ3zByyWeZRKevB8edszAVj4,2272
141
154
  schemathesis/specs/openapi/expressions/errors.py,sha256=YLVhps-sYcslgVaahfcUYxUSHlIfWL-rQMeT5PZSMZ8,219
142
155
  schemathesis/specs/openapi/expressions/extractors.py,sha256=IvOrgq_1IWNnirOSV_wLi0UcWOTiL-mLvBLFzLwRpVA,498
143
156
  schemathesis/specs/openapi/expressions/lexer.py,sha256=ZbYPbVX-2c2Dan-6fi4NrDlFT6N55Wrz-4921TKHlZs,4030
144
157
  schemathesis/specs/openapi/expressions/nodes.py,sha256=qaFpAM3seIzmlYLr9So2kRCSNrteZTa7djcRiOD_ji4,4811
145
158
  schemathesis/specs/openapi/expressions/parser.py,sha256=e-ZxshrGE_5CVbgcZLYgdGSjdifgyzgKkLQp0dI0cJY,4503
146
- schemathesis/specs/openapi/negative/__init__.py,sha256=1sajF22SrE4pUK7-C6PiseZ9PiR5trN33cfUqEMGIbo,3915
147
- schemathesis/specs/openapi/negative/mutations.py,sha256=xDSUVnGWjuuIcvmW_mJGChf-G-nXst-JBX1okQAzon4,19865
159
+ schemathesis/specs/openapi/negative/__init__.py,sha256=B78vps314fJOMZwlPdv7vUHo78-jEoaGUhhnrTtNaqw,4173
160
+ schemathesis/specs/openapi/negative/mutations.py,sha256=9U352xJsdZBR-Zfy1V7_X3a5i91LIUS9Zqotrzp3BLA,21000
148
161
  schemathesis/specs/openapi/negative/types.py,sha256=a7buCcVxNBG6ILBM3A7oNTAX0lyDseEtZndBuej8MbI,174
149
162
  schemathesis/specs/openapi/negative/utils.py,sha256=ozcOIuASufLqZSgnKUACjX-EOZrrkuNdXX0SDnLoGYA,168
150
- schemathesis/specs/openapi/stateful/__init__.py,sha256=DaV7Uuo1GTgZF1JjjoQzbzZw5HQhL6pTByiWqIlWwy4,15996
163
+ schemathesis/specs/openapi/stateful/__init__.py,sha256=nD5f9pP2Rx2DKIeXtbc_KqUukC4Nf2834cHeOp52byM,16247
151
164
  schemathesis/specs/openapi/stateful/control.py,sha256=QaXLSbwQWtai5lxvvVtQV3BLJ8n5ePqSKB00XFxp-MA,3695
152
- schemathesis/specs/openapi/stateful/inference.py,sha256=RSkmA_fyXreCxVpgnHKYNDRgT3av33HGU1NPNtPcg2g,9602
153
- schemathesis/specs/openapi/stateful/links.py,sha256=h5q40jUbcIk5DS_Tih1cvFJxS_QxxG0_9ZQnTs1A_zo,8806
165
+ schemathesis/specs/openapi/stateful/inference.py,sha256=TCgEnDdTg2syk8KM8YCM96eE6-hMRNMW4OvVCxuyZkc,9603
166
+ schemathesis/specs/openapi/stateful/links.py,sha256=G6vqW6JFOdhF044ZjG6PsSwAHU1yP4E3FolcNFE55NM,7918
167
+ schemathesis/specs/openapi/types/__init__.py,sha256=VPsWtLJle__Kodw_QqtQ3OuvBzBcCIKsTOrXy3eA7OU,66
168
+ schemathesis/specs/openapi/types/v3.py,sha256=Vondr9Amk6JKCIM6i6RGcmTUjFfPgOOqzBXqerccLpo,1468
154
169
  schemathesis/transport/__init__.py,sha256=6yg_RfV_9L0cpA6qpbH-SL9_3ggtHQji9CZrpIkbA6s,5321
155
170
  schemathesis/transport/asgi.py,sha256=qTClt6oT_xUEWnRHokACN_uqCNNUZrRPT6YG0PjbElY,926
156
171
  schemathesis/transport/prepare.py,sha256=erYXRaxpQokIDzaIuvt_csHcw72iHfCyNq8VNEzXd0o,4743
157
- schemathesis/transport/requests.py,sha256=XWiQVG4rGnFX0rOhOZAKVIPbrlknLuS7pHYwUcOiEGs,10942
158
- schemathesis/transport/serialization.py,sha256=igUXKZ_VJ9gV7P0TUc5PDQBJXl_s0kK9T3ljGWWvo6E,10339
159
- schemathesis/transport/wsgi.py,sha256=KoAfvu6RJtzyj24VGB8e-Iaa9smpgXJ3VsM8EgAz2tc,6152
160
- schemathesis-4.1.4.dist-info/METADATA,sha256=XzysnOK9zHTGzi9iMRMusdXqaIyIinOClMIrjNYk6gg,8540
161
- schemathesis-4.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
162
- schemathesis-4.1.4.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
163
- schemathesis-4.1.4.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
164
- schemathesis-4.1.4.dist-info/RECORD,,
172
+ schemathesis/transport/requests.py,sha256=wriRI9fprTplE_qEZLEz1TerX6GwkE3pwr6ZnU2o6vQ,10648
173
+ schemathesis/transport/serialization.py,sha256=GwO6OAVTmL1JyKw7HiZ256tjV4CbrRbhQN0ep1uaZwI,11157
174
+ schemathesis/transport/wsgi.py,sha256=kQtasFre6pjdJWRKwLA_Qb-RyQHCFNpaey9ubzlFWKI,5907
175
+ schemathesis-4.2.1.dist-info/METADATA,sha256=66gKdf-zvd-gHePTQubZs_QnlCvuuC3fELYv4hHK8NY,8540
176
+ schemathesis-4.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
177
+ schemathesis-4.2.1.dist-info/entry_points.txt,sha256=hiK3un-xfgPdwj9uj16YVDtTNpO128bmk0U82SMv8ZQ,152
178
+ schemathesis-4.2.1.dist-info/licenses/LICENSE,sha256=2Ve4J8v5jMQAWrT7r1nf3bI8Vflk3rZVQefiF2zpxwg,1121
179
+ schemathesis-4.2.1.dist-info/RECORD,,
@@ -1,405 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import TYPE_CHECKING, Any, ClassVar, Iterable
5
-
6
- from schemathesis.core.errors import InvalidSchema
7
- from schemathesis.schemas import Parameter
8
-
9
- from .converter import to_json_schema_recursive
10
-
11
- if TYPE_CHECKING:
12
- from ...schemas import APIOperation
13
-
14
-
15
- @dataclass(eq=False)
16
- class OpenAPIParameter(Parameter):
17
- """A single Open API operation parameter."""
18
-
19
- example_field: ClassVar[str]
20
- examples_field: ClassVar[str]
21
- nullable_field: ClassVar[str]
22
- supported_jsonschema_keywords: ClassVar[tuple[str, ...]]
23
-
24
- def _repr_pretty_(self, *args: Any, **kwargs: Any) -> None: ...
25
-
26
- @property
27
- def description(self) -> str | None:
28
- """A brief parameter description."""
29
- return self.definition.get("description")
30
-
31
- @property
32
- def location(self) -> str:
33
- """Where this parameter is located.
34
-
35
- E.g. "query".
36
- """
37
- return {"formData": "body"}.get(self.raw_location, self.raw_location)
38
-
39
- @property
40
- def raw_location(self) -> str:
41
- """Open API specific location name."""
42
- return self.definition["in"]
43
-
44
- @property
45
- def name(self) -> str:
46
- """Parameter name."""
47
- return self.definition["name"]
48
-
49
- @property
50
- def is_required(self) -> bool:
51
- return self.definition.get("required", False)
52
-
53
- @property
54
- def is_header(self) -> bool:
55
- return self.location in ("header", "cookie")
56
-
57
- def as_json_schema(self, operation: APIOperation, *, update_quantifiers: bool = True) -> dict[str, Any]:
58
- """Convert parameter's definition to JSON Schema."""
59
- # JSON Schema allows `examples` as an array
60
- examples = []
61
- if self.examples_field in self.definition:
62
- container = self.definition[self.examples_field]
63
- if isinstance(container, dict):
64
- examples.extend([example["value"] for example in container.values() if "value" in example])
65
- elif isinstance(container, list):
66
- examples.extend(container)
67
- if self.example_field in self.definition:
68
- examples.append(self.definition[self.example_field])
69
- schema = self.from_open_api_to_json_schema(operation, self.definition)
70
- if examples:
71
- schema["examples"] = examples
72
- return self.transform_keywords(schema, update_quantifiers=update_quantifiers)
73
-
74
- def transform_keywords(self, schema: dict[str, Any], *, update_quantifiers: bool = True) -> dict[str, Any]:
75
- """Transform Open API specific keywords into JSON Schema compatible form."""
76
- definition = to_json_schema_recursive(schema, self.nullable_field, update_quantifiers=update_quantifiers)
77
- # Headers are strings, but it is not always explicitly defined in the schema. By preparing them properly, we
78
- # can achieve significant performance improvements for such cases.
79
- # For reference (my machine) - running a single test with 100 examples with the resulting strategy:
80
- # - without: 4.37 s
81
- # - with: 294 ms
82
- #
83
- # It also reduces the number of cases when the "filter_too_much" health check fails during testing.
84
- if self.is_header:
85
- definition.setdefault("type", "string")
86
- return definition
87
-
88
- def from_open_api_to_json_schema(self, operation: APIOperation, open_api_schema: dict[str, Any]) -> dict[str, Any]:
89
- """Convert Open API's `Schema` to JSON Schema."""
90
- return {
91
- key: value
92
- for key, value in open_api_schema.items()
93
- # Allow only supported keywords or vendor extensions
94
- if key in self.supported_jsonschema_keywords or key.startswith("x-") or key == self.nullable_field
95
- }
96
-
97
-
98
- @dataclass(eq=False)
99
- class OpenAPI20Parameter(OpenAPIParameter):
100
- """Open API 2.0 parameter.
101
-
102
- https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#parameterObject
103
- """
104
-
105
- example_field = "x-example"
106
- examples_field = "x-examples"
107
- nullable_field = "x-nullable"
108
- # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#parameterObject
109
- # Excluding informative keywords - `title`, `description`, `default`.
110
- # `required` is not included because it has a different meaning here. It determines whether or not this parameter
111
- # is required, which is not relevant because these parameters are later constructed
112
- # into an "object" schema, and the value of this keyword is used there.
113
- # The following keywords are relevant only for non-body parameters.
114
- supported_jsonschema_keywords: ClassVar[tuple[str, ...]] = (
115
- "$ref",
116
- "type", # only as a string
117
- "format",
118
- "items",
119
- "maximum",
120
- "exclusiveMaximum",
121
- "minimum",
122
- "exclusiveMinimum",
123
- "maxLength",
124
- "minLength",
125
- "pattern",
126
- "maxItems",
127
- "minItems",
128
- "uniqueItems",
129
- "enum",
130
- "multipleOf",
131
- "example",
132
- "examples",
133
- "default",
134
- )
135
-
136
-
137
- @dataclass(eq=False)
138
- class OpenAPI30Parameter(OpenAPIParameter):
139
- """Open API 3.0 parameter.
140
-
141
- https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#parameter-object
142
- """
143
-
144
- example_field = "example"
145
- examples_field = "examples"
146
- nullable_field = "nullable"
147
- # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#schema-object
148
- # Excluding informative keywords - `title`, `description`, `default`.
149
- # In contrast with Open API 2.0 non-body parameters, in Open API 3.0, all parameters have the `schema` keyword.
150
- supported_jsonschema_keywords = (
151
- "$ref",
152
- "multipleOf",
153
- "maximum",
154
- "exclusiveMaximum",
155
- "minimum",
156
- "exclusiveMinimum",
157
- "maxLength",
158
- "minLength",
159
- "pattern",
160
- "maxItems",
161
- "minItems",
162
- "uniqueItems",
163
- "maxProperties",
164
- "minProperties",
165
- "required",
166
- "enum",
167
- "const",
168
- "type",
169
- "allOf",
170
- "oneOf",
171
- "anyOf",
172
- "not",
173
- "items",
174
- "properties",
175
- "additionalProperties",
176
- "additionalItems",
177
- "dependencies",
178
- "if",
179
- "then",
180
- "else",
181
- "patternProperties",
182
- "propertyNames",
183
- "contains",
184
- "format",
185
- "example",
186
- "examples",
187
- "default",
188
- )
189
-
190
- def from_open_api_to_json_schema(self, operation: APIOperation, open_api_schema: dict[str, Any]) -> dict[str, Any]:
191
- open_api_schema = get_parameter_schema(operation, open_api_schema)
192
- return super().from_open_api_to_json_schema(operation, open_api_schema)
193
-
194
-
195
- @dataclass(eq=False)
196
- class OpenAPIBody(OpenAPIParameter):
197
- media_type: str
198
-
199
- @property
200
- def location(self) -> str:
201
- return "body"
202
-
203
- @property
204
- def name(self) -> str:
205
- # The name doesn't matter but is here for the interface completeness.
206
- return "body"
207
-
208
-
209
- @dataclass(eq=False)
210
- class OpenAPI20Body(OpenAPIBody, OpenAPI20Parameter):
211
- """Open API 2.0 body variant."""
212
-
213
- # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject
214
- # The `body` parameter contains the `schema` keyword that represents the `Schema Object`.
215
- # It has slightly different keywords than other parameters. Informational keywords are excluded as well.
216
- supported_jsonschema_keywords = (
217
- "$ref",
218
- "format",
219
- "multipleOf",
220
- "maximum",
221
- "exclusiveMaximum",
222
- "minimum",
223
- "exclusiveMinimum",
224
- "maxLength",
225
- "minLength",
226
- "pattern",
227
- "maxItems",
228
- "minItems",
229
- "uniqueItems",
230
- "maxProperties",
231
- "minProperties",
232
- "enum",
233
- "type",
234
- "items",
235
- "allOf",
236
- "properties",
237
- "additionalProperties",
238
- "example",
239
- "examples",
240
- "default",
241
- )
242
- # NOTE. For Open API 2.0 bodies, we still give `x-example` precedence over the schema-level `example` field to keep
243
- # the precedence rules consistent.
244
-
245
- def as_json_schema(self, operation: APIOperation, *, update_quantifiers: bool = True) -> dict[str, Any]:
246
- """Convert body definition to JSON Schema."""
247
- # `schema` is required in Open API 2.0 when the `in` keyword is `body`
248
- schema = self.definition["schema"]
249
- return self.transform_keywords(schema, update_quantifiers=update_quantifiers)
250
-
251
-
252
- FORM_MEDIA_TYPES = ("multipart/form-data", "application/x-www-form-urlencoded")
253
-
254
-
255
- @dataclass(eq=False)
256
- class OpenAPI30Body(OpenAPIBody, OpenAPI30Parameter):
257
- """Open API 3.0 body variant.
258
-
259
- We consider each media type defined in the schema as a separate variant that can be chosen for data generation.
260
- The value of the `definition` field is essentially the Open API 3.0 `MediaType`.
261
- """
262
-
263
- # The `required` keyword is located above the schema for concrete media-type;
264
- # Therefore, it is passed here explicitly
265
- required: bool = False
266
- description: str | None = None
267
-
268
- def as_json_schema(self, operation: APIOperation, *, update_quantifiers: bool = True) -> dict[str, Any]:
269
- """Convert body definition to JSON Schema."""
270
- schema = get_media_type_schema(self.definition)
271
- return self.transform_keywords(schema, update_quantifiers=update_quantifiers)
272
-
273
- def transform_keywords(self, schema: dict[str, Any], *, update_quantifiers: bool = True) -> dict[str, Any]:
274
- definition = super().transform_keywords(schema, update_quantifiers=update_quantifiers)
275
- if self.is_form:
276
- # It significantly reduces the "filtering" part of data generation.
277
- definition.setdefault("type", "object")
278
- return definition
279
-
280
- @property
281
- def is_form(self) -> bool:
282
- """Whether this payload represent a form."""
283
- return self.media_type in FORM_MEDIA_TYPES
284
-
285
- @property
286
- def is_required(self) -> bool:
287
- return self.required
288
-
289
-
290
- @dataclass(eq=False)
291
- class OpenAPI20CompositeBody(OpenAPIBody, OpenAPI20Parameter):
292
- """A special container to abstract over multiple `formData` parameters."""
293
-
294
- definition: list[OpenAPI20Parameter]
295
-
296
- @classmethod
297
- def from_parameters(cls, *parameters: dict[str, Any], media_type: str) -> OpenAPI20CompositeBody:
298
- return cls(
299
- definition=[OpenAPI20Parameter(parameter) for parameter in parameters],
300
- media_type=media_type,
301
- )
302
-
303
- @property
304
- def description(self) -> str | None:
305
- return None
306
-
307
- @property
308
- def is_required(self) -> bool:
309
- # We generate an object for formData - it is always required.
310
- return bool(self.definition)
311
-
312
- def as_json_schema(self, operation: APIOperation, *, update_quantifiers: bool = True) -> dict[str, Any]:
313
- """The composite body is transformed into an "object" JSON Schema."""
314
- return parameters_to_json_schema(operation, self.definition, update_quantifiers=update_quantifiers)
315
-
316
-
317
- def parameters_to_json_schema(
318
- operation: APIOperation, parameters: Iterable[OpenAPIParameter], *, update_quantifiers: bool = True
319
- ) -> dict[str, Any]:
320
- """Create an "object" JSON schema from a list of Open API parameters.
321
-
322
- For each input parameter, there will be a property in the output schema.
323
-
324
- This:
325
-
326
- [
327
- {
328
- "in": "query",
329
- "name": "id",
330
- "type": "string",
331
- "required": True
332
- }
333
- ]
334
-
335
- Will become:
336
-
337
- {
338
- "properties": {
339
- "id": {"type": "string"}
340
- },
341
- "additionalProperties": False,
342
- "type": "object",
343
- "required": ["id"]
344
- }
345
-
346
- We need this transformation for locations that imply multiple components with a unique name within
347
- the same location.
348
-
349
- For example, "query" - first, we generate an object that contains all defined parameters and then serialize it
350
- to the proper format.
351
- """
352
- properties = {}
353
- required = []
354
- for parameter in parameters:
355
- name = parameter.name
356
- properties[name] = parameter.as_json_schema(operation, update_quantifiers=update_quantifiers)
357
- # If parameter names are duplicated, we need to avoid duplicate entries in `required` anyway
358
- if parameter.is_required and name not in required:
359
- required.append(name)
360
- return {"properties": properties, "additionalProperties": False, "type": "object", "required": required}
361
-
362
-
363
- MISSING_SCHEMA_OR_CONTENT_MESSAGE = (
364
- 'Can not generate data for {location} parameter "{name}"! '
365
- "It should have either `schema` or `content` keywords defined"
366
- )
367
-
368
- INVALID_SCHEMA_MESSAGE = (
369
- 'Can not generate data for {location} parameter "{name}"! Its schema should be an object, got {schema}'
370
- )
371
-
372
-
373
- def get_parameter_schema(operation: APIOperation, data: dict[str, Any]) -> dict[str, Any]:
374
- """Extract `schema` from Open API 3.0 `Parameter`."""
375
- # In Open API 3.0, there could be "schema" or "content" field. They are mutually exclusive.
376
- if "schema" in data:
377
- if not isinstance(data["schema"], dict):
378
- raise InvalidSchema(
379
- INVALID_SCHEMA_MESSAGE.format(
380
- location=data.get("in", ""), name=data.get("name", "<UNKNOWN>"), schema=data["schema"]
381
- ),
382
- path=operation.path,
383
- method=operation.method,
384
- )
385
- return data["schema"]
386
- # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#fixed-fields-10
387
- # > The map MUST only contain one entry.
388
- try:
389
- content = data["content"]
390
- except KeyError as exc:
391
- raise InvalidSchema(
392
- MISSING_SCHEMA_OR_CONTENT_MESSAGE.format(location=data.get("in", ""), name=data.get("name", "<UNKNOWN>")),
393
- path=operation.path,
394
- method=operation.method,
395
- ) from exc
396
- options = iter(content.values())
397
- media_type_object = next(options)
398
- return get_media_type_schema(media_type_object)
399
-
400
-
401
- def get_media_type_schema(definition: dict[str, Any]) -> dict[str, Any]:
402
- """Extract `schema` from Open API 3.0 `MediaType`."""
403
- # The `schema` keyword is optional, and we treat it as the payload could be any value of the specified media type
404
- # Note, the main reason to have this function is to have an explicit name for the action we're doing.
405
- return definition.get("schema", {})