ccxt 4.2.77__py2.py3-none-any.whl → 4.4.49__py2.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 (546) hide show
  1. ccxt/__init__.py +36 -14
  2. ccxt/abstract/alpaca.py +4 -0
  3. ccxt/abstract/bigone.py +1 -1
  4. ccxt/abstract/binance.py +112 -48
  5. ccxt/abstract/binancecoinm.py +112 -48
  6. ccxt/abstract/binanceus.py +147 -83
  7. ccxt/abstract/binanceusdm.py +112 -48
  8. ccxt/abstract/bingx.py +133 -78
  9. ccxt/abstract/bitbank.py +5 -0
  10. ccxt/abstract/bitfinex.py +136 -65
  11. ccxt/abstract/bitfinex1.py +69 -0
  12. ccxt/abstract/bitflyer.py +1 -0
  13. ccxt/abstract/bitget.py +8 -1
  14. ccxt/abstract/bitmart.py +13 -1
  15. ccxt/abstract/bitopro.py +1 -0
  16. ccxt/abstract/bitpanda.py +0 -12
  17. ccxt/abstract/bitrue.py +3 -3
  18. ccxt/abstract/bitstamp.py +26 -3
  19. ccxt/abstract/blofin.py +24 -0
  20. ccxt/abstract/btcbox.py +1 -0
  21. ccxt/abstract/bybit.py +29 -14
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbase.py +6 -0
  24. ccxt/abstract/coinbaseadvanced.py +94 -0
  25. ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
  26. ccxt/abstract/coinbaseinternational.py +1 -1
  27. ccxt/abstract/coincatch.py +94 -0
  28. ccxt/abstract/coinex.py +233 -123
  29. ccxt/abstract/coinmetro.py +1 -0
  30. ccxt/abstract/cryptocom.py +14 -0
  31. ccxt/abstract/defx.py +69 -0
  32. ccxt/abstract/deribit.py +1 -0
  33. ccxt/abstract/digifinex.py +1 -0
  34. ccxt/abstract/ellipx.py +25 -0
  35. ccxt/abstract/gate.py +20 -0
  36. ccxt/abstract/gateio.py +20 -0
  37. ccxt/abstract/gemini.py +1 -0
  38. ccxt/abstract/hashkey.py +67 -0
  39. ccxt/abstract/hyperliquid.py +1 -1
  40. ccxt/abstract/independentreserve.py +6 -0
  41. ccxt/abstract/kraken.py +4 -3
  42. ccxt/abstract/krakenfutures.py +4 -0
  43. ccxt/abstract/kucoin.py +24 -0
  44. ccxt/abstract/kucoinfutures.py +34 -0
  45. ccxt/abstract/luno.py +2 -0
  46. ccxt/abstract/mexc.py +4 -0
  47. ccxt/abstract/myokx.py +340 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +30 -0
  50. ccxt/abstract/onetrading.py +0 -12
  51. ccxt/abstract/oxfun.py +34 -0
  52. ccxt/abstract/paradex.py +40 -0
  53. ccxt/abstract/phemex.py +1 -0
  54. ccxt/abstract/upbit.py +4 -0
  55. ccxt/abstract/vertex.py +19 -0
  56. ccxt/abstract/whitebit.py +31 -1
  57. ccxt/abstract/woo.py +6 -2
  58. ccxt/abstract/woofipro.py +119 -0
  59. ccxt/abstract/xt.py +153 -0
  60. ccxt/abstract/zonda.py +6 -0
  61. ccxt/ace.py +164 -60
  62. ccxt/alpaca.py +727 -63
  63. ccxt/ascendex.py +395 -249
  64. ccxt/async_support/__init__.py +36 -14
  65. ccxt/async_support/ace.py +164 -60
  66. ccxt/async_support/alpaca.py +727 -63
  67. ccxt/async_support/ascendex.py +396 -249
  68. ccxt/async_support/base/exchange.py +531 -155
  69. ccxt/async_support/base/ws/aiohttp_client.py +28 -5
  70. ccxt/async_support/base/ws/cache.py +3 -2
  71. ccxt/async_support/base/ws/client.py +26 -5
  72. ccxt/async_support/base/ws/fast_client.py +4 -3
  73. ccxt/async_support/base/ws/functions.py +1 -1
  74. ccxt/async_support/base/ws/future.py +40 -31
  75. ccxt/async_support/base/ws/order_book_side.py +3 -0
  76. ccxt/async_support/bequant.py +1 -1
  77. ccxt/async_support/bigone.py +329 -202
  78. ccxt/async_support/binance.py +3030 -1087
  79. ccxt/async_support/binancecoinm.py +2 -1
  80. ccxt/async_support/binanceus.py +12 -1
  81. ccxt/async_support/binanceusdm.py +3 -1
  82. ccxt/async_support/bingx.py +3205 -937
  83. ccxt/async_support/bit2c.py +119 -38
  84. ccxt/async_support/bitbank.py +215 -76
  85. ccxt/async_support/bitbns.py +124 -53
  86. ccxt/async_support/bitfinex.py +3236 -1078
  87. ccxt/async_support/bitfinex1.py +1711 -0
  88. ccxt/async_support/bitflyer.py +238 -49
  89. ccxt/async_support/bitget.py +1525 -573
  90. ccxt/async_support/bithumb.py +199 -65
  91. ccxt/async_support/bitmart.py +1320 -435
  92. ccxt/async_support/bitmex.py +308 -111
  93. ccxt/async_support/bitopro.py +256 -96
  94. ccxt/async_support/bitrue.py +365 -233
  95. ccxt/async_support/bitso.py +201 -89
  96. ccxt/async_support/bitstamp.py +438 -269
  97. ccxt/async_support/bitteam.py +179 -73
  98. ccxt/async_support/bitvavo.py +180 -70
  99. ccxt/async_support/bl3p.py +92 -25
  100. ccxt/async_support/blockchaincom.py +193 -79
  101. ccxt/async_support/blofin.py +392 -148
  102. ccxt/async_support/btcalpha.py +161 -55
  103. ccxt/async_support/btcbox.py +250 -34
  104. ccxt/async_support/btcmarkets.py +232 -85
  105. ccxt/async_support/btcturk.py +159 -60
  106. ccxt/async_support/bybit.py +2231 -1193
  107. ccxt/async_support/cex.py +1409 -1329
  108. ccxt/async_support/coinbase.py +1454 -287
  109. ccxt/async_support/coinbaseadvanced.py +17 -0
  110. ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
  111. ccxt/async_support/coinbaseinternational.py +428 -88
  112. ccxt/async_support/coincatch.py +5152 -0
  113. ccxt/async_support/coincheck.py +121 -38
  114. ccxt/async_support/coinex.py +4020 -3339
  115. ccxt/async_support/coinlist.py +273 -116
  116. ccxt/async_support/coinmate.py +204 -97
  117. ccxt/async_support/coinmetro.py +203 -110
  118. ccxt/async_support/coinone.py +142 -68
  119. ccxt/async_support/coinsph.py +223 -97
  120. ccxt/async_support/coinspot.py +137 -62
  121. ccxt/async_support/cryptocom.py +515 -185
  122. ccxt/async_support/currencycom.py +203 -85
  123. ccxt/async_support/defx.py +2066 -0
  124. ccxt/async_support/delta.py +404 -109
  125. ccxt/async_support/deribit.py +639 -323
  126. ccxt/async_support/digifinex.py +465 -233
  127. ccxt/async_support/ellipx.py +1887 -0
  128. ccxt/async_support/exmo.py +317 -128
  129. ccxt/async_support/gate.py +1472 -463
  130. ccxt/async_support/gemini.py +206 -84
  131. ccxt/async_support/hashkey.py +4164 -0
  132. ccxt/async_support/hitbtc.py +433 -178
  133. ccxt/async_support/hollaex.py +207 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +178 -56
  136. ccxt/async_support/hyperliquid.py +1678 -292
  137. ccxt/async_support/idex.py +219 -95
  138. ccxt/async_support/independentreserve.py +300 -31
  139. ccxt/async_support/indodax.py +226 -62
  140. ccxt/async_support/kraken.py +871 -354
  141. ccxt/async_support/krakenfutures.py +324 -100
  142. ccxt/async_support/kucoin.py +917 -357
  143. ccxt/async_support/kucoinfutures.py +1004 -149
  144. ccxt/async_support/kuna.py +198 -107
  145. ccxt/async_support/latoken.py +199 -79
  146. ccxt/async_support/lbank.py +360 -113
  147. ccxt/async_support/luno.py +185 -62
  148. ccxt/async_support/lykke.py +168 -55
  149. ccxt/async_support/mercado.py +101 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +53 -0
  152. ccxt/async_support/ndax.py +234 -82
  153. ccxt/async_support/novadax.py +195 -75
  154. ccxt/async_support/oceanex.py +244 -59
  155. ccxt/async_support/okcoin.py +301 -165
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +198 -414
  158. ccxt/async_support/oxfun.py +2898 -0
  159. ccxt/async_support/p2b.py +142 -52
  160. ccxt/async_support/paradex.py +2085 -0
  161. ccxt/async_support/paymium.py +56 -32
  162. ccxt/async_support/phemex.py +572 -196
  163. ccxt/async_support/poloniex.py +218 -95
  164. ccxt/async_support/poloniexfutures.py +260 -92
  165. ccxt/async_support/probit.py +143 -110
  166. ccxt/async_support/timex.py +123 -70
  167. ccxt/async_support/tokocrypto.py +129 -93
  168. ccxt/async_support/tradeogre.py +39 -25
  169. ccxt/async_support/upbit.py +322 -113
  170. ccxt/async_support/vertex.py +2983 -0
  171. ccxt/async_support/wavesexchange.py +227 -173
  172. ccxt/async_support/wazirx.py +145 -65
  173. ccxt/async_support/whitebit.py +533 -138
  174. ccxt/async_support/woo.py +1137 -296
  175. ccxt/async_support/woofipro.py +2716 -0
  176. ccxt/async_support/xt.py +4628 -0
  177. ccxt/async_support/yobit.py +160 -92
  178. ccxt/async_support/zaif.py +80 -33
  179. ccxt/async_support/zonda.py +140 -69
  180. ccxt/base/errors.py +51 -20
  181. ccxt/base/exchange.py +1722 -480
  182. ccxt/base/precise.py +10 -0
  183. ccxt/base/types.py +223 -4
  184. ccxt/bequant.py +1 -1
  185. ccxt/bigone.py +329 -202
  186. ccxt/binance.py +3030 -1087
  187. ccxt/binancecoinm.py +2 -1
  188. ccxt/binanceus.py +12 -1
  189. ccxt/binanceusdm.py +3 -1
  190. ccxt/bingx.py +3205 -937
  191. ccxt/bit2c.py +119 -38
  192. ccxt/bitbank.py +215 -76
  193. ccxt/bitbns.py +124 -53
  194. ccxt/bitfinex.py +3235 -1078
  195. ccxt/bitfinex1.py +1710 -0
  196. ccxt/bitflyer.py +238 -49
  197. ccxt/bitget.py +1525 -573
  198. ccxt/bithumb.py +198 -65
  199. ccxt/bitmart.py +1320 -435
  200. ccxt/bitmex.py +308 -111
  201. ccxt/bitopro.py +256 -96
  202. ccxt/bitrue.py +365 -233
  203. ccxt/bitso.py +201 -89
  204. ccxt/bitstamp.py +438 -269
  205. ccxt/bitteam.py +179 -73
  206. ccxt/bitvavo.py +180 -70
  207. ccxt/bl3p.py +92 -25
  208. ccxt/blockchaincom.py +193 -79
  209. ccxt/blofin.py +392 -148
  210. ccxt/btcalpha.py +161 -55
  211. ccxt/btcbox.py +250 -34
  212. ccxt/btcmarkets.py +232 -85
  213. ccxt/btcturk.py +159 -60
  214. ccxt/bybit.py +2231 -1193
  215. ccxt/cex.py +1408 -1329
  216. ccxt/coinbase.py +1454 -287
  217. ccxt/coinbaseadvanced.py +17 -0
  218. ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
  219. ccxt/coinbaseinternational.py +428 -88
  220. ccxt/coincatch.py +5152 -0
  221. ccxt/coincheck.py +121 -38
  222. ccxt/coinex.py +4020 -3339
  223. ccxt/coinlist.py +273 -116
  224. ccxt/coinmate.py +204 -97
  225. ccxt/coinmetro.py +203 -110
  226. ccxt/coinone.py +142 -68
  227. ccxt/coinsph.py +223 -97
  228. ccxt/coinspot.py +137 -62
  229. ccxt/cryptocom.py +515 -185
  230. ccxt/currencycom.py +203 -85
  231. ccxt/defx.py +2065 -0
  232. ccxt/delta.py +404 -109
  233. ccxt/deribit.py +639 -323
  234. ccxt/digifinex.py +465 -233
  235. ccxt/ellipx.py +1887 -0
  236. ccxt/exmo.py +317 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +433 -178
  241. ccxt/hollaex.py +207 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +178 -56
  244. ccxt/hyperliquid.py +1677 -292
  245. ccxt/idex.py +219 -95
  246. ccxt/independentreserve.py +299 -31
  247. ccxt/indodax.py +226 -62
  248. ccxt/kraken.py +871 -354
  249. ccxt/krakenfutures.py +324 -100
  250. ccxt/kucoin.py +917 -357
  251. ccxt/kucoinfutures.py +1004 -149
  252. ccxt/kuna.py +198 -107
  253. ccxt/latoken.py +199 -79
  254. ccxt/lbank.py +360 -113
  255. ccxt/luno.py +185 -62
  256. ccxt/lykke.py +168 -55
  257. ccxt/mercado.py +101 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +53 -0
  260. ccxt/ndax.py +234 -82
  261. ccxt/novadax.py +195 -75
  262. ccxt/oceanex.py +244 -59
  263. ccxt/okcoin.py +301 -165
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +198 -414
  266. ccxt/oxfun.py +2897 -0
  267. ccxt/p2b.py +142 -52
  268. ccxt/paradex.py +2085 -0
  269. ccxt/paymium.py +56 -32
  270. ccxt/phemex.py +572 -196
  271. ccxt/poloniex.py +218 -95
  272. ccxt/poloniexfutures.py +260 -92
  273. ccxt/pro/__init__.py +29 -5
  274. ccxt/pro/alpaca.py +32 -17
  275. ccxt/pro/ascendex.py +62 -14
  276. ccxt/pro/bequant.py +4 -0
  277. ccxt/pro/binance.py +1596 -329
  278. ccxt/pro/binancecoinm.py +1 -0
  279. ccxt/pro/binanceus.py +2 -9
  280. ccxt/pro/binanceusdm.py +2 -0
  281. ccxt/pro/bingx.py +527 -134
  282. ccxt/pro/bitcoincom.py +4 -1
  283. ccxt/pro/bitfinex.py +731 -266
  284. ccxt/pro/bitfinex1.py +635 -0
  285. ccxt/pro/bitget.py +726 -357
  286. ccxt/pro/bithumb.py +380 -0
  287. ccxt/pro/bitmart.py +143 -39
  288. ccxt/pro/bitmex.py +199 -40
  289. ccxt/pro/bitopro.py +25 -13
  290. ccxt/pro/bitrue.py +31 -32
  291. ccxt/pro/bitstamp.py +7 -6
  292. ccxt/pro/bitvavo.py +203 -81
  293. ccxt/pro/blockchaincom.py +30 -17
  294. ccxt/pro/blofin.py +692 -0
  295. ccxt/pro/bybit.py +791 -82
  296. ccxt/pro/cex.py +99 -51
  297. ccxt/pro/coinbase.py +220 -30
  298. ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
  299. ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
  300. ccxt/pro/coinbaseinternational.py +193 -30
  301. ccxt/pro/coincatch.py +1464 -0
  302. ccxt/pro/coincheck.py +11 -6
  303. ccxt/pro/coinex.py +965 -665
  304. ccxt/pro/coinone.py +17 -10
  305. ccxt/pro/cryptocom.py +446 -66
  306. ccxt/pro/currencycom.py +11 -10
  307. ccxt/pro/defx.py +832 -0
  308. ccxt/pro/deribit.py +167 -31
  309. ccxt/pro/exmo.py +252 -20
  310. ccxt/pro/gate.py +729 -64
  311. ccxt/pro/gemini.py +44 -26
  312. ccxt/pro/hashkey.py +802 -0
  313. ccxt/pro/hitbtc.py +208 -103
  314. ccxt/pro/hollaex.py +25 -9
  315. ccxt/pro/htx.py +83 -39
  316. ccxt/pro/huobijp.py +17 -16
  317. ccxt/pro/hyperliquid.py +502 -31
  318. ccxt/pro/idex.py +28 -13
  319. ccxt/pro/independentreserve.py +21 -16
  320. ccxt/pro/kraken.py +298 -51
  321. ccxt/pro/krakenfutures.py +166 -75
  322. ccxt/pro/kucoin.py +395 -77
  323. ccxt/pro/kucoinfutures.py +400 -99
  324. ccxt/pro/lbank.py +52 -31
  325. ccxt/pro/luno.py +12 -10
  326. ccxt/pro/mexc.py +400 -50
  327. ccxt/pro/myokx.py +28 -0
  328. ccxt/pro/ndax.py +25 -12
  329. ccxt/pro/okcoin.py +28 -9
  330. ccxt/pro/okx.py +935 -124
  331. ccxt/pro/onetrading.py +41 -24
  332. ccxt/pro/oxfun.py +1054 -0
  333. ccxt/pro/p2b.py +100 -24
  334. ccxt/pro/paradex.py +352 -0
  335. ccxt/pro/phemex.py +92 -33
  336. ccxt/pro/poloniex.py +128 -49
  337. ccxt/pro/poloniexfutures.py +53 -32
  338. ccxt/pro/probit.py +92 -85
  339. ccxt/pro/upbit.py +401 -8
  340. ccxt/pro/vertex.py +943 -0
  341. ccxt/pro/wazirx.py +46 -28
  342. ccxt/pro/whitebit.py +65 -12
  343. ccxt/pro/woo.py +437 -65
  344. ccxt/pro/woofipro.py +1271 -0
  345. ccxt/pro/xt.py +1067 -0
  346. ccxt/probit.py +143 -110
  347. ccxt/static_dependencies/__init__.py +1 -1
  348. ccxt/static_dependencies/lark/__init__.py +38 -0
  349. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  350. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  351. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  352. ccxt/static_dependencies/lark/common.py +86 -0
  353. ccxt/static_dependencies/lark/exceptions.py +292 -0
  354. ccxt/static_dependencies/lark/grammar.py +130 -0
  355. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  356. ccxt/static_dependencies/lark/indenter.py +143 -0
  357. ccxt/static_dependencies/lark/lark.py +658 -0
  358. ccxt/static_dependencies/lark/lexer.py +678 -0
  359. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  360. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  361. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  362. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  363. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  364. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  365. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  366. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  367. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  368. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  369. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  370. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  371. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  372. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  373. ccxt/static_dependencies/lark/py.typed +0 -0
  374. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  375. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  376. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  377. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  378. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  379. ccxt/static_dependencies/lark/tree.py +267 -0
  380. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  381. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  382. ccxt/static_dependencies/lark/utils.py +343 -0
  383. ccxt/static_dependencies/lark/visitors.py +596 -0
  384. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  385. ccxt/static_dependencies/marshmallow/base.py +65 -0
  386. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  387. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  388. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  389. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  390. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  391. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  392. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  393. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  394. ccxt/static_dependencies/marshmallow/types.py +12 -0
  395. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  396. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  397. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  398. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  399. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  400. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  401. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  402. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  403. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  404. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  405. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  406. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  407. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  408. ccxt/static_dependencies/starknet/__init__.py +0 -0
  409. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  410. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  411. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  412. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  413. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  414. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  415. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  416. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  417. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  418. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  419. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  420. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  421. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  422. ccxt/static_dependencies/starknet/common.py +15 -0
  423. ccxt/static_dependencies/starknet/constants.py +39 -0
  424. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  425. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  426. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  427. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  428. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  429. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  430. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  431. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  432. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  433. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  434. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  435. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  436. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  437. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  438. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  439. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  440. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  441. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  442. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  443. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  444. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  445. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  446. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  447. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  448. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  449. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  450. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  451. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  452. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  453. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  454. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  455. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  456. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  457. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  458. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  459. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  460. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  461. ccxt/static_dependencies/starkware/__init__.py +0 -0
  462. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  463. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  464. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  465. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  466. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  467. ccxt/static_dependencies/sympy/__init__.py +0 -0
  468. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  469. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  470. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  471. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  472. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  473. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  474. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  475. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  476. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  477. ccxt/test/{test_async.py → tests_async.py} +456 -391
  478. ccxt/test/tests_helpers.py +285 -0
  479. ccxt/test/tests_init.py +39 -0
  480. ccxt/test/{test_sync.py → tests_sync.py} +456 -393
  481. ccxt/timex.py +123 -70
  482. ccxt/tokocrypto.py +129 -93
  483. ccxt/tradeogre.py +39 -25
  484. ccxt/upbit.py +322 -113
  485. ccxt/vertex.py +2983 -0
  486. ccxt/wavesexchange.py +227 -173
  487. ccxt/wazirx.py +145 -65
  488. ccxt/whitebit.py +533 -138
  489. ccxt/woo.py +1137 -296
  490. ccxt/woofipro.py +2716 -0
  491. ccxt/xt.py +4627 -0
  492. ccxt/yobit.py +159 -92
  493. ccxt/zaif.py +80 -33
  494. ccxt/zonda.py +140 -69
  495. ccxt-4.4.49.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.49.dist-info/METADATA +646 -0
  497. ccxt-4.4.49.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/WHEEL +1 -1
  499. ccxt/abstract/bitbay.py +0 -47
  500. ccxt/abstract/bitfinex2.py +0 -139
  501. ccxt/abstract/hitbtc3.py +0 -115
  502. ccxt/async_support/bitbay.py +0 -17
  503. ccxt/async_support/bitfinex2.py +0 -3496
  504. ccxt/async_support/flowbtc.py +0 -34
  505. ccxt/bitbay.py +0 -17
  506. ccxt/bitfinex2.py +0 -3496
  507. ccxt/flowbtc.py +0 -34
  508. ccxt/hitbtc3.py +0 -16
  509. ccxt/pro/bitfinex2.py +0 -1081
  510. ccxt/test/base/__init__.py +0 -28
  511. ccxt/test/base/test_account.py +0 -26
  512. ccxt/test/base/test_balance.py +0 -56
  513. ccxt/test/base/test_borrow_interest.py +0 -35
  514. ccxt/test/base/test_borrow_rate.py +0 -32
  515. ccxt/test/base/test_calculate_fee.py +0 -51
  516. ccxt/test/base/test_crypto.py +0 -127
  517. ccxt/test/base/test_currency.py +0 -76
  518. ccxt/test/base/test_datetime.py +0 -103
  519. ccxt/test/base/test_decimal_to_precision.py +0 -392
  520. ccxt/test/base/test_deep_extend.py +0 -68
  521. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  522. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  523. ccxt/test/base/test_funding_rate_history.py +0 -29
  524. ccxt/test/base/test_last_price.py +0 -32
  525. ccxt/test/base/test_ledger_entry.py +0 -45
  526. ccxt/test/base/test_ledger_item.py +0 -48
  527. ccxt/test/base/test_leverage_tier.py +0 -33
  528. ccxt/test/base/test_margin_mode.py +0 -24
  529. ccxt/test/base/test_margin_modification.py +0 -35
  530. ccxt/test/base/test_market.py +0 -190
  531. ccxt/test/base/test_number.py +0 -411
  532. ccxt/test/base/test_ohlcv.py +0 -32
  533. ccxt/test/base/test_open_interest.py +0 -32
  534. ccxt/test/base/test_order.py +0 -64
  535. ccxt/test/base/test_order_book.py +0 -63
  536. ccxt/test/base/test_position.py +0 -60
  537. ccxt/test/base/test_shared_methods.py +0 -345
  538. ccxt/test/base/test_status.py +0 -24
  539. ccxt/test/base/test_throttle.py +0 -126
  540. ccxt/test/base/test_ticker.py +0 -86
  541. ccxt/test/base/test_trade.py +0 -47
  542. ccxt/test/base/test_trading_fee.py +0 -26
  543. ccxt/test/base/test_transaction.py +0 -39
  544. ccxt-4.2.77.dist-info/METADATA +0 -626
  545. ccxt-4.2.77.dist-info/RECORD +0 -534
  546. {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1047 @@
1
+ """
2
+ This library allows the conversion of python 3.7's :mod:`dataclasses`
3
+ to :mod:`marshmallow` schemas.
4
+
5
+ It takes a python class, and generates a marshmallow schema for it.
6
+
7
+ Simple example::
8
+
9
+ from marshmallow import Schema
10
+ from marshmallow_dataclass import dataclass
11
+
12
+ @dataclass
13
+ class Point:
14
+ x:float
15
+ y:float
16
+
17
+ point = Point(x=0, y=0)
18
+ point_json = Point.Schema().dumps(point)
19
+
20
+ Full example::
21
+
22
+ from marshmallow import Schema
23
+ from dataclasses import field
24
+ from marshmallow_dataclass import dataclass
25
+ import datetime
26
+
27
+ @dataclass
28
+ class User:
29
+ birth: datetime.date = field(metadata= {
30
+ "required": True # A parameter to pass to marshmallow's field
31
+ })
32
+ website:str = field(metadata = {
33
+ "marshmallow_field": marshmallow.fields.Url() # Custom marshmallow field
34
+ })
35
+ Schema: ClassVar[Type[Schema]] = Schema # For the type checker
36
+ """
37
+
38
+ import collections.abc
39
+ import dataclasses
40
+ import inspect
41
+ import sys
42
+ import threading
43
+ import types
44
+ import warnings
45
+ from enum import Enum
46
+ from functools import lru_cache, partial
47
+ from typing import (
48
+ Any,
49
+ Callable,
50
+ Dict,
51
+ FrozenSet,
52
+ Generic,
53
+ List,
54
+ Mapping,
55
+ NewType as typing_NewType,
56
+ Optional,
57
+ Sequence,
58
+ Set,
59
+ Tuple,
60
+ Type,
61
+ TypeVar,
62
+ Union,
63
+ cast,
64
+ get_type_hints,
65
+ overload,
66
+ )
67
+
68
+ from .. import marshmallow
69
+ from ..typing_extensions import *
70
+ from ..typing_inspect import *
71
+
72
+ from .lazy_class_attribute import lazy_class_attribute
73
+
74
+ if sys.version_info >= (3, 9):
75
+ from typing import Annotated
76
+ else:
77
+ from ..typing_extensions import Annotated
78
+
79
+ if sys.version_info >= (3, 11):
80
+ from typing import dataclass_transform
81
+ else:
82
+ from ..typing_extensions import dataclass_transform
83
+
84
+
85
+ __all__ = ["dataclass", "add_schema", "class_schema", "field_for_schema", "NewType"]
86
+
87
+ NoneType = type(None)
88
+ _U = TypeVar("_U")
89
+
90
+ # Whitelist of dataclass members that will be copied to generated schema.
91
+ MEMBERS_WHITELIST: Set[str] = {"Meta"}
92
+
93
+ # Max number of generated schemas that class_schema keeps of generated schemas. Removes duplicates.
94
+ MAX_CLASS_SCHEMA_CACHE_SIZE = 1024
95
+
96
+
97
+ def _maybe_get_callers_frame(
98
+ cls: type, stacklevel: int = 1
99
+ ) -> Optional[types.FrameType]:
100
+ """Return the caller's frame, but only if it will help resolve forward type references.
101
+
102
+ We sometimes need the caller's frame to get access to the caller's
103
+ local namespace in order to be able to resolve forward type
104
+ references in dataclasses.
105
+
106
+ Notes
107
+ -----
108
+
109
+ If the caller's locals are the same as the dataclass' module
110
+ globals — this is the case for the common case of dataclasses
111
+ defined at the module top-level — we don't need the locals.
112
+ (Typing.get_type_hints() knows how to check the class module
113
+ globals on its own.)
114
+
115
+ In that case, we don't need the caller's frame. Not holding a
116
+ reference to the frame in our our lazy ``.Scheme`` class attribute
117
+ is a significant win, memory-wise.
118
+
119
+ """
120
+ try:
121
+ frame = inspect.currentframe()
122
+ for _ in range(stacklevel + 1):
123
+ if frame is None:
124
+ return None
125
+ frame = frame.f_back
126
+
127
+ if frame is None:
128
+ return None
129
+
130
+ globalns = getattr(sys.modules.get(cls.__module__), "__dict__", None)
131
+ if frame.f_locals is globalns:
132
+ # Locals are the globals
133
+ return None
134
+
135
+ return frame
136
+
137
+ finally:
138
+ # Paranoia, per https://docs.python.org/3/library/inspect.html#the-interpreter-stack
139
+ del frame
140
+
141
+
142
+ @overload
143
+ def dataclass(
144
+ _cls: Type[_U],
145
+ *,
146
+ repr: bool = True,
147
+ eq: bool = True,
148
+ order: bool = False,
149
+ unsafe_hash: bool = False,
150
+ frozen: bool = False,
151
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
152
+ cls_frame: Optional[types.FrameType] = None,
153
+ ) -> Type[_U]:
154
+ ...
155
+
156
+
157
+ @overload
158
+ def dataclass(
159
+ *,
160
+ repr: bool = True,
161
+ eq: bool = True,
162
+ order: bool = False,
163
+ unsafe_hash: bool = False,
164
+ frozen: bool = False,
165
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
166
+ cls_frame: Optional[types.FrameType] = None,
167
+ ) -> Callable[[Type[_U]], Type[_U]]:
168
+ ...
169
+
170
+
171
+ # _cls should never be specified by keyword, so start it with an
172
+ # underscore. The presence of _cls is used to detect if this
173
+ # decorator is being called with parameters or not.
174
+ @dataclass_transform(field_specifiers=(dataclasses.Field, dataclasses.field))
175
+ def dataclass(
176
+ _cls: Optional[Type[_U]] = None,
177
+ *,
178
+ repr: bool = True,
179
+ eq: bool = True,
180
+ order: bool = False,
181
+ unsafe_hash: bool = False,
182
+ frozen: bool = False,
183
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
184
+ cls_frame: Optional[types.FrameType] = None,
185
+ stacklevel: int = 1,
186
+ ) -> Union[Type[_U], Callable[[Type[_U]], Type[_U]]]:
187
+ """
188
+ This decorator does the same as dataclasses.dataclass, but also applies :func:`add_schema`.
189
+ It adds a `.Schema` attribute to the class object
190
+
191
+ :param base_schema: marshmallow schema used as a base class when deriving dataclass schema
192
+ :param cls_frame: frame of cls definition, used to obtain locals with other classes definitions.
193
+ If None is passed the caller frame will be treated as cls_frame
194
+
195
+ >>> @dataclass
196
+ ... class Artist:
197
+ ... name: str
198
+ >>> Artist.Schema
199
+ <class 'marshmallow.schema.Artist'>
200
+
201
+ >>> from typing import ClassVar
202
+ >>> from marshmallow import Schema
203
+ >>> @dataclass(order=True) # preserve field order
204
+ ... class Point:
205
+ ... x:float
206
+ ... y:float
207
+ ... Schema: ClassVar[Type[Schema]] = Schema # For the type checker
208
+ ...
209
+ >>> Point.Schema().load({'x':0, 'y':0}) # This line can be statically type checked
210
+ Point(x=0.0, y=0.0)
211
+ """
212
+ dc = dataclasses.dataclass(
213
+ repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen
214
+ )
215
+
216
+ def decorator(cls: Type[_U], stacklevel: int = 1) -> Type[_U]:
217
+ return add_schema(
218
+ dc(cls), base_schema, cls_frame=cls_frame, stacklevel=stacklevel + 1
219
+ )
220
+
221
+ if _cls is None:
222
+ return decorator
223
+ return decorator(_cls, stacklevel=stacklevel + 1)
224
+
225
+
226
+ @overload
227
+ def add_schema(_cls: Type[_U]) -> Type[_U]:
228
+ ...
229
+
230
+
231
+ @overload
232
+ def add_schema(
233
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
234
+ ) -> Callable[[Type[_U]], Type[_U]]:
235
+ ...
236
+
237
+
238
+ @overload
239
+ def add_schema(
240
+ _cls: Type[_U],
241
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
242
+ cls_frame: Optional[types.FrameType] = None,
243
+ stacklevel: int = 1,
244
+ ) -> Type[_U]:
245
+ ...
246
+
247
+
248
+ def add_schema(_cls=None, base_schema=None, cls_frame=None, stacklevel=1):
249
+ """
250
+ This decorator adds a marshmallow schema as the 'Schema' attribute in a dataclass.
251
+ It uses :func:`class_schema` internally.
252
+
253
+ :param type _cls: The dataclass to which a Schema should be added
254
+ :param base_schema: marshmallow schema used as a base class when deriving dataclass schema
255
+ :param cls_frame: frame of cls definition
256
+
257
+ >>> class BaseSchema(marshmallow.Schema):
258
+ ... def on_bind_field(self, field_name, field_obj):
259
+ ... field_obj.data_key = (field_obj.data_key or field_name).upper()
260
+
261
+ >>> @add_schema(base_schema=BaseSchema)
262
+ ... @dataclasses.dataclass
263
+ ... class Artist:
264
+ ... names: Tuple[str, str]
265
+ >>> artist = Artist.Schema().loads('{"NAMES": ["Martin", "Ramirez"]}')
266
+ >>> artist
267
+ Artist(names=('Martin', 'Ramirez'))
268
+ """
269
+
270
+ def decorator(clazz: Type[_U], stacklevel: int = stacklevel) -> Type[_U]:
271
+ if cls_frame is not None:
272
+ frame = cls_frame
273
+ else:
274
+ frame = _maybe_get_callers_frame(clazz, stacklevel=stacklevel)
275
+
276
+ # noinspection PyTypeHints
277
+ clazz.Schema = lazy_class_attribute( # type: ignore
278
+ partial(class_schema, clazz, base_schema, frame),
279
+ "Schema",
280
+ clazz.__name__,
281
+ )
282
+ return clazz
283
+
284
+ if _cls is None:
285
+ return decorator
286
+ return decorator(_cls, stacklevel=stacklevel + 1)
287
+
288
+
289
+ @overload
290
+ def class_schema(
291
+ clazz: type,
292
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
293
+ *,
294
+ globalns: Optional[Dict[str, Any]] = None,
295
+ localns: Optional[Dict[str, Any]] = None,
296
+ ) -> Type[marshmallow.Schema]:
297
+ ...
298
+
299
+
300
+ @overload
301
+ def class_schema(
302
+ clazz: type,
303
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
304
+ clazz_frame: Optional[types.FrameType] = None,
305
+ *,
306
+ globalns: Optional[Dict[str, Any]] = None,
307
+ ) -> Type[marshmallow.Schema]:
308
+ ...
309
+
310
+
311
+ def class_schema(
312
+ clazz: type,
313
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
314
+ # FIXME: delete clazz_frame from API?
315
+ clazz_frame: Optional[types.FrameType] = None,
316
+ *,
317
+ globalns: Optional[Dict[str, Any]] = None,
318
+ localns: Optional[Dict[str, Any]] = None,
319
+ ) -> Type[marshmallow.Schema]:
320
+ """
321
+ Convert a class to a marshmallow schema
322
+
323
+ :param clazz: A python class (may be a dataclass)
324
+ :param base_schema: marshmallow schema used as a base class when deriving dataclass schema
325
+ :param clazz_frame: frame of cls definition
326
+ :return: A marshmallow Schema corresponding to the dataclass
327
+
328
+ .. note::
329
+ All the arguments supported by marshmallow field classes can
330
+ be passed in the `metadata` dictionary of a field.
331
+
332
+
333
+ If you want to use a custom marshmallow field
334
+ (one that has no equivalent python type), you can pass it as the
335
+ ``marshmallow_field`` key in the metadata dictionary.
336
+
337
+ >>> import typing
338
+ >>> Meters = typing.NewType('Meters', float)
339
+ >>> @dataclasses.dataclass()
340
+ ... class Building:
341
+ ... height: Optional[Meters]
342
+ ... name: str = dataclasses.field(default="anonymous")
343
+ ... class Meta:
344
+ ... ordered = True
345
+ ...
346
+ >>> class_schema(Building) # Returns a marshmallow schema class (not an instance)
347
+ <class 'marshmallow.schema.Building'>
348
+ >>> @dataclasses.dataclass()
349
+ ... class City:
350
+ ... name: str = dataclasses.field(metadata={'required':True})
351
+ ... best_building: Building # Reference to another dataclass. A schema will be created for it too.
352
+ ... other_buildings: List[Building] = dataclasses.field(default_factory=lambda: [])
353
+ ...
354
+ >>> citySchema = class_schema(City)()
355
+ >>> city = citySchema.load({"name":"Paris", "best_building": {"name": "Eiffel Tower"}})
356
+ >>> city
357
+ City(name='Paris', best_building=Building(height=None, name='Eiffel Tower'), other_buildings=[])
358
+
359
+ >>> citySchema.load({"name":"Paris"})
360
+ Traceback (most recent call last):
361
+ ...
362
+ marshmallow.exceptions.ValidationError: {'best_building': ['Missing data for required field.']}
363
+
364
+ >>> city_json = citySchema.dump(city)
365
+ >>> city_json['best_building'] # We get an OrderedDict because we specified order = True in the Meta class
366
+ OrderedDict([('height', None), ('name', 'Eiffel Tower')])
367
+
368
+ >>> @dataclasses.dataclass()
369
+ ... class Person:
370
+ ... name: str = dataclasses.field(default="Anonymous")
371
+ ... friends: List['Person'] = dataclasses.field(default_factory=lambda:[]) # Recursive field
372
+ ...
373
+ >>> person = class_schema(Person)().load({
374
+ ... "friends": [{"name": "Roger Boucher"}]
375
+ ... })
376
+ >>> person
377
+ Person(name='Anonymous', friends=[Person(name='Roger Boucher', friends=[])])
378
+
379
+ Marking dataclass fields as non-initialized (``init=False``), by default, will result in those
380
+ fields from being exluded in the schema. To override this behaviour, set the ``Meta`` option
381
+ ``include_non_init=True``.
382
+
383
+ >>> @dataclasses.dataclass()
384
+ ... class C:
385
+ ... important: int = dataclasses.field(init=True, default=0)
386
+ ... # Only fields that are in the __init__ method will be added:
387
+ ... unimportant: int = dataclasses.field(init=False, default=0)
388
+ ...
389
+ >>> c = class_schema(C)().load({
390
+ ... "important": 9, # This field will be imported
391
+ ... "unimportant": 9 # This field will NOT be imported
392
+ ... }, unknown=marshmallow.EXCLUDE)
393
+ >>> c
394
+ C(important=9, unimportant=0)
395
+
396
+ >>> @dataclasses.dataclass()
397
+ ... class C:
398
+ ... class Meta:
399
+ ... include_non_init = True
400
+ ... important: int = dataclasses.field(init=True, default=0)
401
+ ... unimportant: int = dataclasses.field(init=False, default=0)
402
+ ...
403
+ >>> c = class_schema(C)().load({
404
+ ... "important": 9, # This field will be imported
405
+ ... "unimportant": 9 # This field will be imported
406
+ ... }, unknown=marshmallow.EXCLUDE)
407
+ >>> c
408
+ C(important=9, unimportant=9)
409
+
410
+ >>> @dataclasses.dataclass
411
+ ... class Website:
412
+ ... url:str = dataclasses.field(metadata = {
413
+ ... "marshmallow_field": marshmallow.fields.Url() # Custom marshmallow field
414
+ ... })
415
+ ...
416
+ >>> class_schema(Website)().load({"url": "I am not a good URL !"})
417
+ Traceback (most recent call last):
418
+ ...
419
+ marshmallow.exceptions.ValidationError: {'url': ['Not a valid URL.']}
420
+
421
+ >>> @dataclasses.dataclass
422
+ ... class NeverValid:
423
+ ... @marshmallow.validates_schema
424
+ ... def validate(self, data, **_):
425
+ ... raise marshmallow.ValidationError('never valid')
426
+ ...
427
+ >>> class_schema(NeverValid)().load({})
428
+ Traceback (most recent call last):
429
+ ...
430
+ marshmallow.exceptions.ValidationError: {'_schema': ['never valid']}
431
+
432
+ >>> @dataclasses.dataclass
433
+ ... class Anything:
434
+ ... name: str
435
+ ... @marshmallow.validates('name')
436
+ ... def validates(self, value):
437
+ ... if len(value) > 5: raise marshmallow.ValidationError("Name too long")
438
+ >>> class_schema(Anything)().load({"name": "aaaaaargh"})
439
+ Traceback (most recent call last):
440
+ ...
441
+ marshmallow.exceptions.ValidationError: {'name': ['Name too long']}
442
+
443
+ You can use the ``metadata`` argument to override default field behaviour, e.g. the fact that
444
+ ``Optional`` fields allow ``None`` values:
445
+
446
+ >>> @dataclasses.dataclass
447
+ ... class Custom:
448
+ ... name: Optional[str] = dataclasses.field(metadata={"allow_none": False})
449
+ >>> class_schema(Custom)().load({"name": None})
450
+ Traceback (most recent call last):
451
+ ...
452
+ marshmallow.exceptions.ValidationError: {'name': ['Field may not be null.']}
453
+ >>> class_schema(Custom)().load({})
454
+ Custom(name=None)
455
+ """
456
+ if not dataclasses.is_dataclass(clazz):
457
+ clazz = dataclasses.dataclass(clazz)
458
+ if localns is None:
459
+ if clazz_frame is None:
460
+ clazz_frame = _maybe_get_callers_frame(clazz)
461
+ if clazz_frame is not None:
462
+ localns = clazz_frame.f_locals
463
+ with _SchemaContext(globalns, localns):
464
+ return _internal_class_schema(clazz, base_schema)
465
+
466
+
467
+ class _SchemaContext:
468
+ """Global context for an invocation of class_schema."""
469
+
470
+ def __init__(
471
+ self,
472
+ globalns: Optional[Dict[str, Any]] = None,
473
+ localns: Optional[Dict[str, Any]] = None,
474
+ ):
475
+ self.seen_classes: Dict[type, str] = {}
476
+ self.globalns = globalns
477
+ self.localns = localns
478
+
479
+ def __enter__(self) -> "_SchemaContext":
480
+ _schema_ctx_stack.push(self)
481
+ return self
482
+
483
+ def __exit__(
484
+ self,
485
+ _typ: Optional[Type[BaseException]],
486
+ _value: Optional[BaseException],
487
+ _tb: Optional[types.TracebackType],
488
+ ) -> None:
489
+ _schema_ctx_stack.pop()
490
+
491
+
492
+ class _LocalStack(threading.local, Generic[_U]):
493
+ def __init__(self) -> None:
494
+ self.stack: List[_U] = []
495
+
496
+ def push(self, value: _U) -> None:
497
+ self.stack.append(value)
498
+
499
+ def pop(self) -> None:
500
+ self.stack.pop()
501
+
502
+ @property
503
+ def top(self) -> _U:
504
+ return self.stack[-1]
505
+
506
+
507
+ _schema_ctx_stack = _LocalStack[_SchemaContext]()
508
+
509
+
510
+ @lru_cache(maxsize=MAX_CLASS_SCHEMA_CACHE_SIZE)
511
+ def _internal_class_schema(
512
+ clazz: type,
513
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
514
+ ) -> Type[marshmallow.Schema]:
515
+ schema_ctx = _schema_ctx_stack.top
516
+
517
+ if typing_extensions.get_origin(clazz) is Annotated and sys.version_info < (3, 10):
518
+ # https://github.com/python/cpython/blob/3.10/Lib/typing.py#L977
519
+ class_name = clazz._name or clazz.__origin__.__name__ # type: ignore[attr-defined]
520
+ else:
521
+ class_name = clazz.__name__
522
+
523
+ schema_ctx.seen_classes[clazz] = class_name
524
+
525
+ try:
526
+ # noinspection PyDataclass
527
+ fields: Tuple[dataclasses.Field, ...] = dataclasses.fields(clazz)
528
+ except TypeError: # Not a dataclass
529
+ try:
530
+ warnings.warn(
531
+ "****** WARNING ****** "
532
+ f"marshmallow_dataclass was called on the class {clazz}, which is not a dataclass. "
533
+ "It is going to try and convert the class into a dataclass, which may have "
534
+ "undesirable side effects. To avoid this message, make sure all your classes and "
535
+ "all the classes of their fields are either explicitly supported by "
536
+ "marshmallow_dataclass, or define the schema explicitly using "
537
+ "field(metadata=dict(marshmallow_field=...)). For more information, see "
538
+ "https://github.com/lovasoa/marshmallow_dataclass/issues/51 "
539
+ "****** WARNING ******"
540
+ )
541
+ created_dataclass: type = dataclasses.dataclass(clazz)
542
+ return _internal_class_schema(created_dataclass, base_schema)
543
+ except Exception as exc:
544
+ raise TypeError(
545
+ f"{getattr(clazz, '__name__', repr(clazz))} is not a dataclass and cannot be turned into one."
546
+ ) from exc
547
+
548
+ # Copy all marshmallow hooks and whitelisted members of the dataclass to the schema.
549
+ attributes = {
550
+ k: v
551
+ for k, v in inspect.getmembers(clazz)
552
+ if hasattr(v, "__marshmallow_hook__") or k in MEMBERS_WHITELIST
553
+ }
554
+
555
+ # Determine whether we should include non-init fields
556
+ include_non_init = getattr(getattr(clazz, "Meta", None), "include_non_init", False)
557
+
558
+ # Update the schema members to contain marshmallow fields instead of dataclass fields
559
+
560
+ if sys.version_info >= (3, 9):
561
+ type_hints = get_type_hints(
562
+ clazz,
563
+ globalns=schema_ctx.globalns,
564
+ localns=schema_ctx.localns,
565
+ include_extras=True,
566
+ )
567
+ else:
568
+ type_hints = get_type_hints(
569
+ clazz, globalns=schema_ctx.globalns, localns=schema_ctx.localns
570
+ )
571
+ attributes.update(
572
+ (
573
+ field.name,
574
+ _field_for_schema(
575
+ type_hints[field.name],
576
+ _get_field_default(field),
577
+ field.metadata,
578
+ base_schema,
579
+ ),
580
+ )
581
+ for field in fields
582
+ if field.init or include_non_init
583
+ )
584
+
585
+ schema_class = type(clazz.__name__, (_base_schema(clazz, base_schema),), attributes)
586
+ return cast(Type[marshmallow.Schema], schema_class)
587
+
588
+
589
+ def _field_by_type(
590
+ typ: Union[type, Any], base_schema: Optional[Type[marshmallow.Schema]]
591
+ ) -> Optional[Type[marshmallow.fields.Field]]:
592
+ return (
593
+ base_schema and base_schema.TYPE_MAPPING.get(typ)
594
+ ) or marshmallow.Schema.TYPE_MAPPING.get(typ)
595
+
596
+
597
+ def _field_by_supertype(
598
+ typ: Type,
599
+ default: Any,
600
+ newtype_supertype: Type,
601
+ metadata: dict,
602
+ base_schema: Optional[Type[marshmallow.Schema]],
603
+ ) -> marshmallow.fields.Field:
604
+ """
605
+ Return a new field for fields based on a super field. (Usually spawned from NewType)
606
+ """
607
+ # Add the information coming our custom NewType implementation
608
+
609
+ typ_args = getattr(typ, "_marshmallow_args", {})
610
+
611
+ # Handle multiple validators from both `typ` and `metadata`.
612
+ # See https://github.com/lovasoa/marshmallow_dataclass/issues/91
613
+ new_validators: List[Callable] = []
614
+ for meta_dict in (typ_args, metadata):
615
+ if "validate" in meta_dict:
616
+ if marshmallow.utils.is_iterable_but_not_string(meta_dict["validate"]):
617
+ new_validators.extend(meta_dict["validate"])
618
+ elif callable(meta_dict["validate"]):
619
+ new_validators.append(meta_dict["validate"])
620
+ metadata["validate"] = new_validators if new_validators else None
621
+
622
+ metadata = {**typ_args, **metadata}
623
+ metadata.setdefault("metadata", {}).setdefault("description", typ.__name__)
624
+ field = getattr(typ, "_marshmallow_field", None)
625
+ if field:
626
+ return field(**metadata)
627
+ else:
628
+ return _field_for_schema(
629
+ newtype_supertype,
630
+ metadata=metadata,
631
+ default=default,
632
+ base_schema=base_schema,
633
+ )
634
+
635
+
636
+ def _generic_type_add_any(typ: type) -> type:
637
+ """if typ is generic type without arguments, replace them by Any."""
638
+ if typ is list or typ is List:
639
+ typ = List[Any]
640
+ elif typ is dict or typ is Dict:
641
+ typ = Dict[Any, Any]
642
+ elif typ is Mapping:
643
+ typ = Mapping[Any, Any]
644
+ elif typ is Sequence:
645
+ typ = Sequence[Any]
646
+ elif typ is set or typ is Set:
647
+ typ = Set[Any]
648
+ elif typ is frozenset or typ is FrozenSet:
649
+ typ = FrozenSet[Any]
650
+ return typ
651
+
652
+
653
+ def _field_for_generic_type(
654
+ typ: type,
655
+ base_schema: Optional[Type[marshmallow.Schema]],
656
+ **metadata: Any,
657
+ ) -> Optional[marshmallow.fields.Field]:
658
+ """
659
+ If the type is a generic interface, resolve the arguments and construct the appropriate Field.
660
+ """
661
+ origin = typing_extensions.get_origin(typ)
662
+ arguments = typing_extensions.get_args(typ)
663
+ if origin:
664
+ # Override base_schema.TYPE_MAPPING to change the class used for generic types below
665
+ type_mapping = base_schema.TYPE_MAPPING if base_schema else {}
666
+
667
+ if origin in (list, List):
668
+ child_type = _field_for_schema(arguments[0], base_schema=base_schema)
669
+ list_type = cast(
670
+ Type[marshmallow.fields.List],
671
+ type_mapping.get(List, marshmallow.fields.List),
672
+ )
673
+ return list_type(child_type, **metadata)
674
+ if origin in (collections.abc.Sequence, Sequence) or (
675
+ origin in (tuple, Tuple)
676
+ and len(arguments) == 2
677
+ and arguments[1] is Ellipsis
678
+ ):
679
+ from . import collection_field
680
+
681
+ child_type = _field_for_schema(arguments[0], base_schema=base_schema)
682
+ return collection_field.Sequence(cls_or_instance=child_type, **metadata)
683
+ if origin in (set, Set):
684
+ from . import collection_field
685
+
686
+ child_type = _field_for_schema(arguments[0], base_schema=base_schema)
687
+ return collection_field.Set(
688
+ cls_or_instance=child_type, frozen=False, **metadata
689
+ )
690
+ if origin in (frozenset, FrozenSet):
691
+ from . import collection_field
692
+
693
+ child_type = _field_for_schema(arguments[0], base_schema=base_schema)
694
+ return collection_field.Set(
695
+ cls_or_instance=child_type, frozen=True, **metadata
696
+ )
697
+ if origin in (tuple, Tuple):
698
+ children = tuple(
699
+ _field_for_schema(arg, base_schema=base_schema) for arg in arguments
700
+ )
701
+ tuple_type = cast(
702
+ Type[marshmallow.fields.Tuple],
703
+ type_mapping.get( # type:ignore[call-overload]
704
+ Tuple, marshmallow.fields.Tuple
705
+ ),
706
+ )
707
+ return tuple_type(children, **metadata)
708
+ elif origin in (dict, Dict, collections.abc.Mapping, Mapping):
709
+ dict_type = type_mapping.get(Dict, marshmallow.fields.Dict)
710
+ return dict_type(
711
+ keys=_field_for_schema(arguments[0], base_schema=base_schema),
712
+ values=_field_for_schema(arguments[1], base_schema=base_schema),
713
+ **metadata,
714
+ )
715
+
716
+ return None
717
+
718
+
719
+ def _field_for_annotated_type(
720
+ typ: type,
721
+ **metadata: Any,
722
+ ) -> Optional[marshmallow.fields.Field]:
723
+ """
724
+ If the type is an Annotated interface, resolve the arguments and construct the appropriate Field.
725
+ """
726
+ origin = typing_extensions.get_origin(typ)
727
+ arguments = typing_extensions.get_args(typ)
728
+ if origin and origin is Annotated:
729
+ marshmallow_annotations = [
730
+ arg
731
+ for arg in arguments[1:]
732
+ if (inspect.isclass(arg) and issubclass(arg, marshmallow.fields.Field))
733
+ or isinstance(arg, marshmallow.fields.Field)
734
+ ]
735
+ if marshmallow_annotations:
736
+ if len(marshmallow_annotations) > 1:
737
+ warnings.warn(
738
+ "Multiple marshmallow Field annotations found. Using the last one."
739
+ )
740
+
741
+ field = marshmallow_annotations[-1]
742
+ # Got a field instance, return as is. User must know what they're doing
743
+ if isinstance(field, marshmallow.fields.Field):
744
+ return field
745
+
746
+ return field(**metadata)
747
+ return None
748
+
749
+
750
+ def _field_for_union_type(
751
+ typ: type,
752
+ base_schema: Optional[Type[marshmallow.Schema]],
753
+ **metadata: Any,
754
+ ) -> Optional[marshmallow.fields.Field]:
755
+ arguments = typing_extensions.get_args(typ)
756
+ if typing_inspect.is_union_type(typ):
757
+ if typing_inspect.is_optional_type(typ):
758
+ metadata["allow_none"] = metadata.get("allow_none", True)
759
+ metadata["dump_default"] = metadata.get("dump_default", None)
760
+ if not metadata.get("required"):
761
+ metadata["load_default"] = metadata.get("load_default", None)
762
+ metadata.setdefault("required", False)
763
+ subtypes = [t for t in arguments if t is not NoneType] # type: ignore
764
+ if len(subtypes) == 1:
765
+ return _field_for_schema(
766
+ subtypes[0],
767
+ metadata=metadata,
768
+ base_schema=base_schema,
769
+ )
770
+ from . import union_field
771
+
772
+ return union_field.Union(
773
+ [
774
+ (
775
+ subtyp,
776
+ _field_for_schema(
777
+ subtyp,
778
+ metadata={"required": True},
779
+ base_schema=base_schema,
780
+ ),
781
+ )
782
+ for subtyp in subtypes
783
+ ],
784
+ **metadata,
785
+ )
786
+ return None
787
+
788
+
789
+ def field_for_schema(
790
+ typ: type,
791
+ default: Any = marshmallow.missing,
792
+ metadata: Optional[Mapping[str, Any]] = None,
793
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
794
+ # FIXME: delete typ_frame from API?
795
+ typ_frame: Optional[types.FrameType] = None,
796
+ ) -> marshmallow.fields.Field:
797
+ """
798
+ Get a marshmallow Field corresponding to the given python type.
799
+ The metadata of the dataclass field is used as arguments to the marshmallow Field.
800
+
801
+ :param typ: The type for which a field should be generated
802
+ :param default: value to use for (de)serialization when the field is missing
803
+ :param metadata: Additional parameters to pass to the marshmallow field constructor
804
+ :param base_schema: marshmallow schema used as a base class when deriving dataclass schema
805
+ :param typ_frame: frame of type definition
806
+
807
+ >>> int_field = field_for_schema(int, default=9, metadata=dict(required=True))
808
+ >>> int_field.__class__
809
+ <class 'marshmallow.fields.Integer'>
810
+
811
+ >>> int_field.dump_default
812
+ 9
813
+
814
+ >>> field_for_schema(str, metadata={"marshmallow_field": marshmallow.fields.Url()}).__class__
815
+ <class 'marshmallow.fields.Url'>
816
+ """
817
+ with _SchemaContext(localns=typ_frame.f_locals if typ_frame is not None else None):
818
+ return _field_for_schema(typ, default, metadata, base_schema)
819
+
820
+
821
+ def _field_for_schema(
822
+ typ: type,
823
+ default: Any = marshmallow.missing,
824
+ metadata: Optional[Mapping[str, Any]] = None,
825
+ base_schema: Optional[Type[marshmallow.Schema]] = None,
826
+ ) -> marshmallow.fields.Field:
827
+ """
828
+ Get a marshmallow Field corresponding to the given python type.
829
+ The metadata of the dataclass field is used as arguments to the marshmallow Field.
830
+
831
+ This is an internal version of field_for_schema. It assumes a _SchemaContext
832
+ has been pushed onto the local stack.
833
+
834
+ :param typ: The type for which a field should be generated
835
+ :param default: value to use for (de)serialization when the field is missing
836
+ :param metadata: Additional parameters to pass to the marshmallow field constructor
837
+ :param base_schema: marshmallow schema used as a base class when deriving dataclass schema
838
+
839
+ """
840
+
841
+ metadata = {} if metadata is None else dict(metadata)
842
+
843
+ if default is not marshmallow.missing:
844
+ metadata.setdefault("dump_default", default)
845
+ # 'missing' must not be set for required fields.
846
+ if not metadata.get("required"):
847
+ metadata.setdefault("load_default", default)
848
+ else:
849
+ metadata.setdefault("required", not typing_inspect.is_optional_type(typ))
850
+
851
+ # If the field was already defined by the user
852
+ predefined_field = metadata.get("marshmallow_field")
853
+ if predefined_field:
854
+ return predefined_field
855
+
856
+ # Generic types specified without type arguments
857
+ typ = _generic_type_add_any(typ)
858
+
859
+ # Base types
860
+ field = _field_by_type(typ, base_schema)
861
+ if field:
862
+ return field(**metadata)
863
+
864
+ if typ is Any:
865
+ metadata.setdefault("allow_none", True)
866
+ return marshmallow.fields.Raw(**metadata)
867
+
868
+ # i.e.: Literal['abc']
869
+ if typing_inspect.is_literal_type(typ):
870
+ arguments = typing_inspect.get_args(typ)
871
+ return marshmallow.fields.Raw(
872
+ validate=(
873
+ marshmallow.validate.Equal(arguments[0])
874
+ if len(arguments) == 1
875
+ else marshmallow.validate.OneOf(arguments)
876
+ ),
877
+ **metadata,
878
+ )
879
+
880
+ # i.e.: Final[str] = 'abc'
881
+ if typing_inspect.is_final_type(typ):
882
+ arguments = typing_inspect.get_args(typ)
883
+ if arguments:
884
+ subtyp = arguments[0]
885
+ elif default is not marshmallow.missing:
886
+ if callable(default):
887
+ subtyp = Any
888
+ warnings.warn(
889
+ "****** WARNING ****** "
890
+ "marshmallow_dataclass was called on a dataclass with an "
891
+ 'attribute that is type-annotated with "Final" and uses '
892
+ "dataclasses.field for specifying a default value using a "
893
+ "factory. The Marshmallow field type cannot be inferred from the "
894
+ "factory and will fall back to a raw field which is equivalent to "
895
+ 'the type annotation "Any" and will result in no validation. '
896
+ "Provide a type to Final[...] to ensure accurate validation. "
897
+ "****** WARNING ******"
898
+ )
899
+ else:
900
+ subtyp = type(default)
901
+ warnings.warn(
902
+ "****** WARNING ****** "
903
+ "marshmallow_dataclass was called on a dataclass with an "
904
+ 'attribute that is type-annotated with "Final" with a default '
905
+ "value from which the Marshmallow field type is inferred. "
906
+ "Support for type inference from a default value is limited and "
907
+ "may result in inaccurate validation. Provide a type to "
908
+ "Final[...] to ensure accurate validation. "
909
+ "****** WARNING ******"
910
+ )
911
+ else:
912
+ subtyp = Any
913
+ return _field_for_schema(subtyp, default, metadata, base_schema)
914
+
915
+ annotated_field = _field_for_annotated_type(typ, **metadata)
916
+ if annotated_field:
917
+ return annotated_field
918
+
919
+ union_field = _field_for_union_type(typ, base_schema, **metadata)
920
+ if union_field:
921
+ return union_field
922
+
923
+ # Generic types
924
+ generic_field = _field_for_generic_type(typ, base_schema, **metadata)
925
+ if generic_field:
926
+ return generic_field
927
+
928
+ # typing.NewType returns a function (in python <= 3.9) or a class (python >= 3.10) with a
929
+ # __supertype__ attribute
930
+ newtype_supertype = getattr(typ, "__supertype__", None)
931
+ if typing_inspect.is_new_type(typ) and newtype_supertype is not None:
932
+ return _field_by_supertype(
933
+ typ=typ,
934
+ default=default,
935
+ newtype_supertype=newtype_supertype,
936
+ metadata=metadata,
937
+ base_schema=base_schema,
938
+ )
939
+
940
+ # enumerations
941
+ if inspect.isclass(typ) and issubclass(typ, Enum):
942
+ return marshmallow.fields.Enum(typ, **metadata)
943
+
944
+ # Nested marshmallow dataclass
945
+ # it would be just a class name instead of actual schema util the schema is not ready yet
946
+ nested_schema = getattr(typ, "Schema", None)
947
+
948
+ # Nested dataclasses
949
+ forward_reference = getattr(typ, "__forward_arg__", None)
950
+
951
+ nested = (
952
+ nested_schema
953
+ or forward_reference
954
+ or _schema_ctx_stack.top.seen_classes.get(typ)
955
+ or _internal_class_schema(typ, base_schema) # type: ignore[arg-type] # FIXME
956
+ )
957
+
958
+ return marshmallow.fields.Nested(nested, **metadata)
959
+
960
+
961
+ def _base_schema(
962
+ clazz: type, base_schema: Optional[Type[marshmallow.Schema]] = None
963
+ ) -> Type[marshmallow.Schema]:
964
+ """
965
+ Base schema factory that creates a schema for `clazz` derived either from `base_schema`
966
+ or `BaseSchema`
967
+ """
968
+
969
+ # Remove `type: ignore` when mypy handles dynamic base classes
970
+ # https://github.com/python/mypy/issues/2813
971
+ class BaseSchema(base_schema or marshmallow.Schema): # type: ignore
972
+ def load(self, data: Mapping, *, many: Optional[bool] = None, **kwargs):
973
+ all_loaded = super().load(data, many=many, **kwargs)
974
+ many = self.many if many is None else bool(many)
975
+ if many:
976
+ return [clazz(**loaded) for loaded in all_loaded]
977
+ else:
978
+ return clazz(**all_loaded)
979
+
980
+ return BaseSchema
981
+
982
+
983
+ def _get_field_default(field: dataclasses.Field):
984
+ """
985
+ Return a marshmallow default value given a dataclass default value
986
+
987
+ >>> _get_field_default(dataclasses.field())
988
+ <marshmallow.missing>
989
+ """
990
+ # Remove `type: ignore` when https://github.com/python/mypy/issues/6910 is fixed
991
+ default_factory = field.default_factory # type: ignore
992
+ if default_factory is not dataclasses.MISSING:
993
+ return default_factory
994
+ elif field.default is dataclasses.MISSING:
995
+ return marshmallow.missing
996
+ return field.default
997
+
998
+
999
+ def NewType(
1000
+ name: str,
1001
+ typ: Type[_U],
1002
+ field: Optional[Type[marshmallow.fields.Field]] = None,
1003
+ **kwargs,
1004
+ ) -> Callable[[_U], _U]:
1005
+ """DEPRECATED: Use typing.Annotated instead.
1006
+ NewType creates simple unique types
1007
+ to which you can attach custom marshmallow attributes.
1008
+ All the keyword arguments passed to this function will be transmitted
1009
+ to the marshmallow field constructor.
1010
+
1011
+ >>> import marshmallow.validate
1012
+ >>> IPv4 = NewType('IPv4', str, validate=marshmallow.validate.Regexp(r'^([0-9]{1,3}\\.){3}[0-9]{1,3}$'))
1013
+ >>> @dataclass
1014
+ ... class MyIps:
1015
+ ... ips: List[IPv4]
1016
+ >>> MyIps.Schema().load({"ips": ["0.0.0.0", "grumble grumble"]})
1017
+ Traceback (most recent call last):
1018
+ ...
1019
+ marshmallow.exceptions.ValidationError: {'ips': {1: ['String does not match expected pattern.']}}
1020
+ >>> MyIps.Schema().load({"ips": ["127.0.0.1"]})
1021
+ MyIps(ips=['127.0.0.1'])
1022
+
1023
+ >>> Email = NewType('Email', str, field=marshmallow.fields.Email)
1024
+ >>> @dataclass
1025
+ ... class ContactInfo:
1026
+ ... mail: Email = dataclasses.field(default="anonymous@example.org")
1027
+ >>> ContactInfo.Schema().load({})
1028
+ ContactInfo(mail='anonymous@example.org')
1029
+ >>> ContactInfo.Schema().load({"mail": "grumble grumble"})
1030
+ Traceback (most recent call last):
1031
+ ...
1032
+ marshmallow.exceptions.ValidationError: {'mail': ['Not a valid email address.']}
1033
+ """
1034
+
1035
+ # noinspection PyTypeHints
1036
+ new_type = typing_NewType(name, typ) # type: ignore
1037
+ # noinspection PyTypeHints
1038
+ new_type._marshmallow_field = field # type: ignore
1039
+ # noinspection PyTypeHints
1040
+ new_type._marshmallow_args = kwargs # type: ignore
1041
+ return new_type
1042
+
1043
+
1044
+ if __name__ == "__main__":
1045
+ import doctest
1046
+
1047
+ doctest.testmod(verbose=True)