ccxt 4.2.77__py2.py3-none-any.whl → 4.4.48__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 +3104 -880
  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 +1513 -563
  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 +206 -89
  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 +557 -323
  126. ccxt/async_support/digifinex.py +340 -223
  127. ccxt/async_support/ellipx.py +1826 -0
  128. ccxt/async_support/exmo.py +259 -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 +334 -178
  133. ccxt/async_support/hollaex.py +134 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +105 -56
  136. ccxt/async_support/hyperliquid.py +1633 -268
  137. ccxt/async_support/idex.py +148 -95
  138. ccxt/async_support/independentreserve.py +236 -31
  139. ccxt/async_support/indodax.py +165 -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 +138 -106
  145. ccxt/async_support/latoken.py +135 -79
  146. ccxt/async_support/lbank.py +290 -113
  147. ccxt/async_support/luno.py +112 -62
  148. ccxt/async_support/lykke.py +104 -55
  149. ccxt/async_support/mercado.py +36 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +43 -0
  152. ccxt/async_support/ndax.py +163 -82
  153. ccxt/async_support/novadax.py +121 -75
  154. ccxt/async_support/oceanex.py +175 -59
  155. ccxt/async_support/okcoin.py +222 -163
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +132 -414
  158. ccxt/async_support/oxfun.py +2832 -0
  159. ccxt/async_support/p2b.py +79 -51
  160. ccxt/async_support/paradex.py +2017 -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 +3104 -880
  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 +1513 -563
  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 +206 -89
  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 +557 -323
  234. ccxt/digifinex.py +340 -223
  235. ccxt/ellipx.py +1826 -0
  236. ccxt/exmo.py +259 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +334 -178
  241. ccxt/hollaex.py +134 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +105 -56
  244. ccxt/hyperliquid.py +1632 -268
  245. ccxt/idex.py +148 -95
  246. ccxt/independentreserve.py +235 -31
  247. ccxt/indodax.py +165 -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 +138 -106
  253. ccxt/latoken.py +135 -79
  254. ccxt/lbank.py +290 -113
  255. ccxt/luno.py +112 -62
  256. ccxt/lykke.py +104 -55
  257. ccxt/mercado.py +36 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +43 -0
  260. ccxt/ndax.py +163 -82
  261. ccxt/novadax.py +121 -75
  262. ccxt/oceanex.py +175 -59
  263. ccxt/okcoin.py +222 -163
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +132 -414
  266. ccxt/oxfun.py +2831 -0
  267. ccxt/p2b.py +79 -51
  268. ccxt/paradex.py +2017 -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 +138 -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.48.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.48.dist-info/METADATA +646 -0
  497. ccxt-4.4.48.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.48.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.48.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,186 @@
1
+ """Tree matcher based on Lark grammar"""
2
+
3
+ import re
4
+ from collections import defaultdict
5
+
6
+ from . import Tree, Token
7
+ from .common import ParserConf
8
+ from .parsers import earley
9
+ from .grammar import Rule, Terminal, NonTerminal
10
+
11
+
12
+ def is_discarded_terminal(t):
13
+ return t.is_term and t.filter_out
14
+
15
+
16
+ class _MakeTreeMatch:
17
+ def __init__(self, name, expansion):
18
+ self.name = name
19
+ self.expansion = expansion
20
+
21
+ def __call__(self, args):
22
+ t = Tree(self.name, args)
23
+ t.meta.match_tree = True
24
+ t.meta.orig_expansion = self.expansion
25
+ return t
26
+
27
+
28
+ def _best_from_group(seq, group_key, cmp_key):
29
+ d = {}
30
+ for item in seq:
31
+ key = group_key(item)
32
+ if key in d:
33
+ v1 = cmp_key(item)
34
+ v2 = cmp_key(d[key])
35
+ if v2 > v1:
36
+ d[key] = item
37
+ else:
38
+ d[key] = item
39
+ return list(d.values())
40
+
41
+
42
+ def _best_rules_from_group(rules):
43
+ rules = _best_from_group(rules, lambda r: r, lambda r: -len(r.expansion))
44
+ rules.sort(key=lambda r: len(r.expansion))
45
+ return rules
46
+
47
+
48
+ def _match(term, token):
49
+ if isinstance(token, Tree):
50
+ name, _args = parse_rulename(term.name)
51
+ return token.data == name
52
+ elif isinstance(token, Token):
53
+ return term == Terminal(token.type)
54
+ assert False, (term, token)
55
+
56
+
57
+ def make_recons_rule(origin, expansion, old_expansion):
58
+ return Rule(origin, expansion, alias=_MakeTreeMatch(origin.name, old_expansion))
59
+
60
+
61
+ def make_recons_rule_to_term(origin, term):
62
+ return make_recons_rule(origin, [Terminal(term.name)], [term])
63
+
64
+
65
+ def parse_rulename(s):
66
+ "Parse rule names that may contain a template syntax (like rule{a, b, ...})"
67
+ name, args_str = re.match(r'(\w+)(?:{(.+)})?', s).groups()
68
+ args = args_str and [a.strip() for a in args_str.split(',')]
69
+ return name, args
70
+
71
+
72
+
73
+ class ChildrenLexer:
74
+ def __init__(self, children):
75
+ self.children = children
76
+
77
+ def lex(self, parser_state):
78
+ return self.children
79
+
80
+ class TreeMatcher:
81
+ """Match the elements of a tree node, based on an ontology
82
+ provided by a Lark grammar.
83
+
84
+ Supports templates and inlined rules (`rule{a, b,..}` and `_rule`)
85
+
86
+ Initialize with an instance of Lark.
87
+ """
88
+
89
+ def __init__(self, parser):
90
+ # XXX TODO calling compile twice returns different results!
91
+ assert not parser.options.maybe_placeholders
92
+ # XXX TODO: we just ignore the potential existence of a postlexer
93
+ self.tokens, rules, _extra = parser.grammar.compile(parser.options.start, set())
94
+
95
+ self.rules_for_root = defaultdict(list)
96
+
97
+ self.rules = list(self._build_recons_rules(rules))
98
+ self.rules.reverse()
99
+
100
+ # Choose the best rule from each group of {rule => [rule.alias]}, since we only really need one derivation.
101
+ self.rules = _best_rules_from_group(self.rules)
102
+
103
+ self.parser = parser
104
+ self._parser_cache = {}
105
+
106
+ def _build_recons_rules(self, rules):
107
+ "Convert tree-parsing/construction rules to tree-matching rules"
108
+ expand1s = {r.origin for r in rules if r.options.expand1}
109
+
110
+ aliases = defaultdict(list)
111
+ for r in rules:
112
+ if r.alias:
113
+ aliases[r.origin].append(r.alias)
114
+
115
+ rule_names = {r.origin for r in rules}
116
+ nonterminals = {sym for sym in rule_names
117
+ if sym.name.startswith('_') or sym in expand1s or sym in aliases}
118
+
119
+ seen = set()
120
+ for r in rules:
121
+ recons_exp = [sym if sym in nonterminals else Terminal(sym.name)
122
+ for sym in r.expansion if not is_discarded_terminal(sym)]
123
+
124
+ # Skip self-recursive constructs
125
+ if recons_exp == [r.origin] and r.alias is None:
126
+ continue
127
+
128
+ sym = NonTerminal(r.alias) if r.alias else r.origin
129
+ rule = make_recons_rule(sym, recons_exp, r.expansion)
130
+
131
+ if sym in expand1s and len(recons_exp) != 1:
132
+ self.rules_for_root[sym.name].append(rule)
133
+
134
+ if sym.name not in seen:
135
+ yield make_recons_rule_to_term(sym, sym)
136
+ seen.add(sym.name)
137
+ else:
138
+ if sym.name.startswith('_') or sym in expand1s:
139
+ yield rule
140
+ else:
141
+ self.rules_for_root[sym.name].append(rule)
142
+
143
+ for origin, rule_aliases in aliases.items():
144
+ for alias in rule_aliases:
145
+ yield make_recons_rule_to_term(origin, NonTerminal(alias))
146
+ yield make_recons_rule_to_term(origin, origin)
147
+
148
+ def match_tree(self, tree, rulename):
149
+ """Match the elements of `tree` to the symbols of rule `rulename`.
150
+
151
+ Parameters:
152
+ tree (Tree): the tree node to match
153
+ rulename (str): The expected full rule name (including template args)
154
+
155
+ Returns:
156
+ Tree: an unreduced tree that matches `rulename`
157
+
158
+ Raises:
159
+ UnexpectedToken: If no match was found.
160
+
161
+ Note:
162
+ It's the callers' responsibility match the tree recursively.
163
+ """
164
+ if rulename:
165
+ # validate
166
+ name, _args = parse_rulename(rulename)
167
+ assert tree.data == name
168
+ else:
169
+ rulename = tree.data
170
+
171
+ # TODO: ambiguity?
172
+ try:
173
+ parser = self._parser_cache[rulename]
174
+ except KeyError:
175
+ rules = self.rules + _best_rules_from_group(self.rules_for_root[rulename])
176
+
177
+ # TODO pass callbacks through dict, instead of alias?
178
+ callbacks = {rule: rule.alias for rule in rules}
179
+ conf = ParserConf(rules, callbacks, [rulename])
180
+ parser = earley.Parser(self.parser.lexer_conf, conf, _match, resolve_ambiguity=True)
181
+ self._parser_cache[rulename] = parser
182
+
183
+ # find a full derivation
184
+ unreduced_tree = parser.parse(ChildrenLexer(tree.children), rulename)
185
+ assert unreduced_tree.data == rulename
186
+ return unreduced_tree
@@ -0,0 +1,180 @@
1
+ """This module defines utilities for matching and translation tree templates.
2
+
3
+ A tree templates is a tree that contains nodes that are template variables.
4
+
5
+ """
6
+
7
+ from typing import Union, Optional, Mapping, Dict, Tuple, Iterator
8
+
9
+ from lark import Tree, Transformer
10
+ from lark.exceptions import MissingVariableError
11
+
12
+ Branch = Union[Tree[str], str]
13
+ TreeOrCode = Union[Tree[str], str]
14
+ MatchResult = Dict[str, Tree]
15
+ _TEMPLATE_MARKER = '$'
16
+
17
+
18
+ class TemplateConf:
19
+ """Template Configuration
20
+
21
+ Allows customization for different uses of Template
22
+
23
+ parse() must return a Tree instance.
24
+ """
25
+
26
+ def __init__(self, parse=None):
27
+ self._parse = parse
28
+
29
+ def test_var(self, var: Union[Tree[str], str]) -> Optional[str]:
30
+ """Given a tree node, if it is a template variable return its name. Otherwise, return None.
31
+
32
+ This method may be overridden for customization
33
+
34
+ Parameters:
35
+ var: Tree | str - The tree node to test
36
+
37
+ """
38
+ if isinstance(var, str):
39
+ return _get_template_name(var)
40
+
41
+ if (
42
+ isinstance(var, Tree)
43
+ and var.data == "var"
44
+ and len(var.children) > 0
45
+ and isinstance(var.children[0], str)
46
+ ):
47
+ return _get_template_name(var.children[0])
48
+
49
+ return None
50
+
51
+ def _get_tree(self, template: TreeOrCode) -> Tree[str]:
52
+ if isinstance(template, str):
53
+ assert self._parse
54
+ template = self._parse(template)
55
+
56
+ if not isinstance(template, Tree):
57
+ raise TypeError("template parser must return a Tree instance")
58
+
59
+ return template
60
+
61
+ def __call__(self, template: Tree[str]) -> 'Template':
62
+ return Template(template, conf=self)
63
+
64
+ def _match_tree_template(self, template: TreeOrCode, tree: Branch) -> Optional[MatchResult]:
65
+ """Returns dict of {var: match} if found a match, else None
66
+ """
67
+ template_var = self.test_var(template)
68
+ if template_var:
69
+ if not isinstance(tree, Tree):
70
+ raise TypeError(f"Template variables can only match Tree instances. Not {tree!r}")
71
+ return {template_var: tree}
72
+
73
+ if isinstance(template, str):
74
+ if template == tree:
75
+ return {}
76
+ return None
77
+
78
+ assert isinstance(template, Tree) and isinstance(tree, Tree), f"template={template} tree={tree}"
79
+
80
+ if template.data == tree.data and len(template.children) == len(tree.children):
81
+ res = {}
82
+ for t1, t2 in zip(template.children, tree.children):
83
+ matches = self._match_tree_template(t1, t2)
84
+ if matches is None:
85
+ return None
86
+
87
+ res.update(matches)
88
+
89
+ return res
90
+
91
+ return None
92
+
93
+
94
+ class _ReplaceVars(Transformer[str, Tree[str]]):
95
+ def __init__(self, conf: TemplateConf, vars: Mapping[str, Tree[str]]) -> None:
96
+ super().__init__()
97
+ self._conf = conf
98
+ self._vars = vars
99
+
100
+ def __default__(self, data, children, meta) -> Tree[str]:
101
+ tree = super().__default__(data, children, meta)
102
+
103
+ var = self._conf.test_var(tree)
104
+ if var:
105
+ try:
106
+ return self._vars[var]
107
+ except KeyError:
108
+ raise MissingVariableError(f"No mapping for template variable ({var})")
109
+ return tree
110
+
111
+
112
+ class Template:
113
+ """Represents a tree template, tied to a specific configuration
114
+
115
+ A tree template is a tree that contains nodes that are template variables.
116
+ Those variables will match any tree.
117
+ (future versions may support annotations on the variables, to allow more complex templates)
118
+ """
119
+
120
+ def __init__(self, tree: Tree[str], conf: TemplateConf = TemplateConf()):
121
+ self.conf = conf
122
+ self.tree = conf._get_tree(tree)
123
+
124
+ def match(self, tree: TreeOrCode) -> Optional[MatchResult]:
125
+ """Match a tree template to a tree.
126
+
127
+ A tree template without variables will only match ``tree`` if it is equal to the template.
128
+
129
+ Parameters:
130
+ tree (Tree): The tree to match to the template
131
+
132
+ Returns:
133
+ Optional[Dict[str, Tree]]: If match is found, returns a dictionary mapping
134
+ template variable names to their matching tree nodes.
135
+ If no match was found, returns None.
136
+ """
137
+ tree = self.conf._get_tree(tree)
138
+ return self.conf._match_tree_template(self.tree, tree)
139
+
140
+ def search(self, tree: TreeOrCode) -> Iterator[Tuple[Tree[str], MatchResult]]:
141
+ """Search for all occurrences of the tree template inside ``tree``.
142
+ """
143
+ tree = self.conf._get_tree(tree)
144
+ for subtree in tree.iter_subtrees():
145
+ res = self.match(subtree)
146
+ if res:
147
+ yield subtree, res
148
+
149
+ def apply_vars(self, vars: Mapping[str, Tree[str]]) -> Tree[str]:
150
+ """Apply vars to the template tree
151
+ """
152
+ return _ReplaceVars(self.conf, vars).transform(self.tree)
153
+
154
+
155
+ def translate(t1: Template, t2: Template, tree: TreeOrCode):
156
+ """Search tree and translate each occurrence of t1 into t2.
157
+ """
158
+ tree = t1.conf._get_tree(tree) # ensure it's a tree, parse if necessary and possible
159
+ for subtree, vars in t1.search(tree):
160
+ res = t2.apply_vars(vars)
161
+ subtree.set(res.data, res.children)
162
+ return tree
163
+
164
+
165
+ class TemplateTranslator:
166
+ """Utility class for translating a collection of patterns
167
+ """
168
+
169
+ def __init__(self, translations: Mapping[Template, Template]):
170
+ assert all(isinstance(k, Template) and isinstance(v, Template) for k, v in translations.items())
171
+ self.translations = translations
172
+
173
+ def translate(self, tree: Tree[str]):
174
+ for k, v in self.translations.items():
175
+ tree = translate(k, v, tree)
176
+ return tree
177
+
178
+
179
+ def _get_template_name(value: str) -> Optional[str]:
180
+ return value.lstrip(_TEMPLATE_MARKER) if value.startswith(_TEMPLATE_MARKER) else None
@@ -0,0 +1,343 @@
1
+ import unicodedata
2
+ import os
3
+ from itertools import product
4
+ from collections import deque
5
+ from typing import Callable, Iterator, List, Optional, Tuple, Type, TypeVar, Union, Dict, Any, Sequence, Iterable, AbstractSet
6
+
7
+ ###{standalone
8
+ import sys, re
9
+ import logging
10
+
11
+ logger: logging.Logger = logging.getLogger("lark")
12
+ logger.addHandler(logging.StreamHandler())
13
+ # Set to highest level, since we have some warnings amongst the code
14
+ # By default, we should not output any log messages
15
+ logger.setLevel(logging.CRITICAL)
16
+
17
+
18
+ NO_VALUE = object()
19
+
20
+ T = TypeVar("T")
21
+
22
+
23
+ def classify(seq: Iterable, key: Optional[Callable] = None, value: Optional[Callable] = None) -> Dict:
24
+ d: Dict[Any, Any] = {}
25
+ for item in seq:
26
+ k = key(item) if (key is not None) else item
27
+ v = value(item) if (value is not None) else item
28
+ try:
29
+ d[k].append(v)
30
+ except KeyError:
31
+ d[k] = [v]
32
+ return d
33
+
34
+
35
+ def _deserialize(data: Any, namespace: Dict[str, Any], memo: Dict) -> Any:
36
+ if isinstance(data, dict):
37
+ if '__type__' in data: # Object
38
+ class_ = namespace[data['__type__']]
39
+ return class_.deserialize(data, memo)
40
+ elif '@' in data:
41
+ return memo[data['@']]
42
+ return {key:_deserialize(value, namespace, memo) for key, value in data.items()}
43
+ elif isinstance(data, list):
44
+ return [_deserialize(value, namespace, memo) for value in data]
45
+ return data
46
+
47
+
48
+ _T = TypeVar("_T", bound="Serialize")
49
+
50
+ class Serialize:
51
+ """Safe-ish serialization interface that doesn't rely on Pickle
52
+
53
+ Attributes:
54
+ __serialize_fields__ (List[str]): Fields (aka attributes) to serialize.
55
+ __serialize_namespace__ (list): List of classes that deserialization is allowed to instantiate.
56
+ Should include all field types that aren't builtin types.
57
+ """
58
+
59
+ def memo_serialize(self, types_to_memoize: List) -> Any:
60
+ memo = SerializeMemoizer(types_to_memoize)
61
+ return self.serialize(memo), memo.serialize()
62
+
63
+ def serialize(self, memo = None) -> Dict[str, Any]:
64
+ if memo and memo.in_types(self):
65
+ return {'@': memo.memoized.get(self)}
66
+
67
+ fields = getattr(self, '__serialize_fields__')
68
+ res = {f: _serialize(getattr(self, f), memo) for f in fields}
69
+ res['__type__'] = type(self).__name__
70
+ if hasattr(self, '_serialize'):
71
+ self._serialize(res, memo)
72
+ return res
73
+
74
+ @classmethod
75
+ def deserialize(cls: Type[_T], data: Dict[str, Any], memo: Dict[int, Any]) -> _T:
76
+ namespace = getattr(cls, '__serialize_namespace__', [])
77
+ namespace = {c.__name__:c for c in namespace}
78
+
79
+ fields = getattr(cls, '__serialize_fields__')
80
+
81
+ if '@' in data:
82
+ return memo[data['@']]
83
+
84
+ inst = cls.__new__(cls)
85
+ for f in fields:
86
+ try:
87
+ setattr(inst, f, _deserialize(data[f], namespace, memo))
88
+ except KeyError as e:
89
+ raise KeyError("Cannot find key for class", cls, e)
90
+
91
+ if hasattr(inst, '_deserialize'):
92
+ inst._deserialize()
93
+
94
+ return inst
95
+
96
+
97
+ class SerializeMemoizer(Serialize):
98
+ "A version of serialize that memoizes objects to reduce space"
99
+
100
+ __serialize_fields__ = 'memoized',
101
+
102
+ def __init__(self, types_to_memoize: List) -> None:
103
+ self.types_to_memoize = tuple(types_to_memoize)
104
+ self.memoized = Enumerator()
105
+
106
+ def in_types(self, value: Serialize) -> bool:
107
+ return isinstance(value, self.types_to_memoize)
108
+
109
+ def serialize(self) -> Dict[int, Any]: # type: ignore[override]
110
+ return _serialize(self.memoized.reversed(), None)
111
+
112
+ @classmethod
113
+ def deserialize(cls, data: Dict[int, Any], namespace: Dict[str, Any], memo: Dict[Any, Any]) -> Dict[int, Any]: # type: ignore[override]
114
+ return _deserialize(data, namespace, memo)
115
+
116
+
117
+ try:
118
+ import regex
119
+ _has_regex = True
120
+ except ImportError:
121
+ _has_regex = False
122
+
123
+ if sys.version_info >= (3, 11):
124
+ import re._parser as sre_parse
125
+ import re._constants as sre_constants
126
+ else:
127
+ import sre_parse
128
+ import sre_constants
129
+
130
+ categ_pattern = re.compile(r'\\p{[A-Za-z_]+}')
131
+
132
+ def get_regexp_width(expr: str) -> Union[Tuple[int, int], List[int]]:
133
+ if _has_regex:
134
+ # Since `sre_parse` cannot deal with Unicode categories of the form `\p{Mn}`, we replace these with
135
+ # a simple letter, which makes no difference as we are only trying to get the possible lengths of the regex
136
+ # match here below.
137
+ regexp_final = re.sub(categ_pattern, 'A', expr)
138
+ else:
139
+ if re.search(categ_pattern, expr):
140
+ raise ImportError('`regex` module must be installed in order to use Unicode categories.', expr)
141
+ regexp_final = expr
142
+ try:
143
+ # Fixed in next version (past 0.960) of typeshed
144
+ return [int(x) for x in sre_parse.parse(regexp_final).getwidth()]
145
+ except sre_constants.error:
146
+ if not _has_regex:
147
+ raise ValueError(expr)
148
+ else:
149
+ # sre_parse does not support the new features in regex. To not completely fail in that case,
150
+ # we manually test for the most important info (whether the empty string is matched)
151
+ c = regex.compile(regexp_final)
152
+ # Python 3.11.7 introducded sre_parse.MAXWIDTH that is used instead of MAXREPEAT
153
+ # See lark-parser/lark#1376 and python/cpython#109859
154
+ MAXWIDTH = getattr(sre_parse, "MAXWIDTH", sre_constants.MAXREPEAT)
155
+ if c.match('') is None:
156
+ # MAXREPEAT is a none pickable subclass of int, therefore needs to be converted to enable caching
157
+ return 1, int(MAXWIDTH)
158
+ else:
159
+ return 0, int(MAXWIDTH)
160
+
161
+ ###}
162
+
163
+
164
+ _ID_START = 'Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Mn', 'Mc', 'Pc'
165
+ _ID_CONTINUE = _ID_START + ('Nd', 'Nl',)
166
+
167
+ def _test_unicode_category(s: str, categories: Sequence[str]) -> bool:
168
+ if len(s) != 1:
169
+ return all(_test_unicode_category(char, categories) for char in s)
170
+ return s == '_' or unicodedata.category(s) in categories
171
+
172
+ def is_id_continue(s: str) -> bool:
173
+ """
174
+ Checks if all characters in `s` are alphanumeric characters (Unicode standard, so diacritics, indian vowels, non-latin
175
+ numbers, etc. all pass). Synonymous with a Python `ID_CONTINUE` identifier. See PEP 3131 for details.
176
+ """
177
+ return _test_unicode_category(s, _ID_CONTINUE)
178
+
179
+ def is_id_start(s: str) -> bool:
180
+ """
181
+ Checks if all characters in `s` are alphabetic characters (Unicode standard, so diacritics, indian vowels, non-latin
182
+ numbers, etc. all pass). Synonymous with a Python `ID_START` identifier. See PEP 3131 for details.
183
+ """
184
+ return _test_unicode_category(s, _ID_START)
185
+
186
+
187
+ def dedup_list(l: Sequence[T]) -> List[T]:
188
+ """Given a list (l) will removing duplicates from the list,
189
+ preserving the original order of the list. Assumes that
190
+ the list entries are hashable."""
191
+ return list(dict.fromkeys(l))
192
+
193
+
194
+ class Enumerator(Serialize):
195
+ def __init__(self) -> None:
196
+ self.enums: Dict[Any, int] = {}
197
+
198
+ def get(self, item) -> int:
199
+ if item not in self.enums:
200
+ self.enums[item] = len(self.enums)
201
+ return self.enums[item]
202
+
203
+ def __len__(self):
204
+ return len(self.enums)
205
+
206
+ def reversed(self) -> Dict[int, Any]:
207
+ r = {v: k for k, v in self.enums.items()}
208
+ assert len(r) == len(self.enums)
209
+ return r
210
+
211
+
212
+
213
+ def combine_alternatives(lists):
214
+ """
215
+ Accepts a list of alternatives, and enumerates all their possible concatenations.
216
+
217
+ Examples:
218
+ >>> combine_alternatives([range(2), [4,5]])
219
+ [[0, 4], [0, 5], [1, 4], [1, 5]]
220
+
221
+ >>> combine_alternatives(["abc", "xy", '$'])
222
+ [['a', 'x', '$'], ['a', 'y', '$'], ['b', 'x', '$'], ['b', 'y', '$'], ['c', 'x', '$'], ['c', 'y', '$']]
223
+
224
+ >>> combine_alternatives([])
225
+ [[]]
226
+ """
227
+ if not lists:
228
+ return [[]]
229
+ assert all(l for l in lists), lists
230
+ return list(product(*lists))
231
+
232
+ try:
233
+ import atomicwrites
234
+ _has_atomicwrites = True
235
+ except ImportError:
236
+ _has_atomicwrites = False
237
+
238
+ class FS:
239
+ exists = staticmethod(os.path.exists)
240
+
241
+ @staticmethod
242
+ def open(name, mode="r", **kwargs):
243
+ if _has_atomicwrites and "w" in mode:
244
+ return atomicwrites.atomic_write(name, mode=mode, overwrite=True, **kwargs)
245
+ else:
246
+ return open(name, mode, **kwargs)
247
+
248
+
249
+ class fzset(frozenset):
250
+ def __repr__(self):
251
+ return '{%s}' % ', '.join(map(repr, self))
252
+
253
+
254
+ def classify_bool(seq: Iterable, pred: Callable) -> Any:
255
+ false_elems = []
256
+ true_elems = [elem for elem in seq if pred(elem) or false_elems.append(elem)] # type: ignore[func-returns-value]
257
+ return true_elems, false_elems
258
+
259
+
260
+ def bfs(initial: Iterable, expand: Callable) -> Iterator:
261
+ open_q = deque(list(initial))
262
+ visited = set(open_q)
263
+ while open_q:
264
+ node = open_q.popleft()
265
+ yield node
266
+ for next_node in expand(node):
267
+ if next_node not in visited:
268
+ visited.add(next_node)
269
+ open_q.append(next_node)
270
+
271
+ def bfs_all_unique(initial, expand):
272
+ "bfs, but doesn't keep track of visited (aka seen), because there can be no repetitions"
273
+ open_q = deque(list(initial))
274
+ while open_q:
275
+ node = open_q.popleft()
276
+ yield node
277
+ open_q += expand(node)
278
+
279
+
280
+ def _serialize(value: Any, memo: Optional[SerializeMemoizer]) -> Any:
281
+ if isinstance(value, Serialize):
282
+ return value.serialize(memo)
283
+ elif isinstance(value, list):
284
+ return [_serialize(elem, memo) for elem in value]
285
+ elif isinstance(value, frozenset):
286
+ return list(value) # TODO reversible?
287
+ elif isinstance(value, dict):
288
+ return {key:_serialize(elem, memo) for key, elem in value.items()}
289
+ # assert value is None or isinstance(value, (int, float, str, tuple)), value
290
+ return value
291
+
292
+
293
+
294
+
295
+ def small_factors(n: int, max_factor: int) -> List[Tuple[int, int]]:
296
+ """
297
+ Splits n up into smaller factors and summands <= max_factor.
298
+ Returns a list of [(a, b), ...]
299
+ so that the following code returns n:
300
+
301
+ n = 1
302
+ for a, b in values:
303
+ n = n * a + b
304
+
305
+ Currently, we also keep a + b <= max_factor, but that might change
306
+ """
307
+ assert n >= 0
308
+ assert max_factor > 2
309
+ if n <= max_factor:
310
+ return [(n, 0)]
311
+
312
+ for a in range(max_factor, 1, -1):
313
+ r, b = divmod(n, a)
314
+ if a + b <= max_factor:
315
+ return small_factors(r, max_factor) + [(a, b)]
316
+ assert False, "Failed to factorize %s" % n
317
+
318
+
319
+ class OrderedSet(AbstractSet[T]):
320
+ """A minimal OrderedSet implementation, using a dictionary.
321
+
322
+ (relies on the dictionary being ordered)
323
+ """
324
+ def __init__(self, items: Iterable[T] =()):
325
+ self.d = dict.fromkeys(items)
326
+
327
+ def __contains__(self, item: Any) -> bool:
328
+ return item in self.d
329
+
330
+ def add(self, item: T):
331
+ self.d[item] = None
332
+
333
+ def __iter__(self) -> Iterator[T]:
334
+ return iter(self.d)
335
+
336
+ def remove(self, item: T):
337
+ del self.d[item]
338
+
339
+ def __bool__(self):
340
+ return bool(self.d)
341
+
342
+ def __len__(self) -> int:
343
+ return len(self.d)