ccxt 4.2.76__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.
- ccxt/__init__.py +36 -14
- ccxt/abstract/alpaca.py +4 -0
- ccxt/abstract/bigone.py +1 -1
- ccxt/abstract/binance.py +112 -48
- ccxt/abstract/binancecoinm.py +112 -48
- ccxt/abstract/binanceus.py +147 -83
- ccxt/abstract/binanceusdm.py +112 -48
- ccxt/abstract/bingx.py +133 -78
- ccxt/abstract/bitbank.py +5 -0
- ccxt/abstract/bitfinex.py +136 -65
- ccxt/abstract/bitfinex1.py +69 -0
- ccxt/abstract/bitflyer.py +1 -0
- ccxt/abstract/bitget.py +8 -1
- ccxt/abstract/bitmart.py +13 -1
- ccxt/abstract/bitopro.py +1 -0
- ccxt/abstract/bitpanda.py +0 -12
- ccxt/abstract/bitrue.py +3 -3
- ccxt/abstract/bitstamp.py +26 -3
- ccxt/abstract/blofin.py +24 -0
- ccxt/abstract/btcbox.py +1 -0
- ccxt/abstract/bybit.py +29 -14
- ccxt/abstract/cex.py +28 -29
- ccxt/abstract/coinbase.py +6 -0
- ccxt/abstract/coinbaseadvanced.py +94 -0
- ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
- ccxt/abstract/coinbaseinternational.py +1 -1
- ccxt/abstract/coincatch.py +94 -0
- ccxt/abstract/coinex.py +233 -123
- ccxt/abstract/coinmetro.py +1 -0
- ccxt/abstract/cryptocom.py +14 -0
- ccxt/abstract/defx.py +69 -0
- ccxt/abstract/deribit.py +1 -0
- ccxt/abstract/digifinex.py +1 -0
- ccxt/abstract/ellipx.py +25 -0
- ccxt/abstract/gate.py +20 -0
- ccxt/abstract/gateio.py +20 -0
- ccxt/abstract/gemini.py +1 -0
- ccxt/abstract/hashkey.py +67 -0
- ccxt/abstract/hyperliquid.py +1 -1
- ccxt/abstract/independentreserve.py +6 -0
- ccxt/abstract/kraken.py +4 -3
- ccxt/abstract/krakenfutures.py +4 -0
- ccxt/abstract/kucoin.py +25 -0
- ccxt/abstract/kucoinfutures.py +35 -0
- ccxt/abstract/luno.py +2 -0
- ccxt/abstract/mexc.py +4 -0
- ccxt/abstract/myokx.py +340 -0
- ccxt/abstract/oceanex.py +5 -0
- ccxt/abstract/okx.py +30 -0
- ccxt/abstract/onetrading.py +0 -12
- ccxt/abstract/oxfun.py +34 -0
- ccxt/abstract/paradex.py +40 -0
- ccxt/abstract/phemex.py +1 -0
- ccxt/abstract/upbit.py +4 -0
- ccxt/abstract/vertex.py +19 -0
- ccxt/abstract/whitebit.py +31 -1
- ccxt/abstract/woo.py +6 -2
- ccxt/abstract/woofipro.py +119 -0
- ccxt/abstract/xt.py +153 -0
- ccxt/abstract/zonda.py +6 -0
- ccxt/ace.py +164 -60
- ccxt/alpaca.py +727 -63
- ccxt/ascendex.py +395 -249
- ccxt/async_support/__init__.py +36 -14
- ccxt/async_support/ace.py +164 -60
- ccxt/async_support/alpaca.py +727 -63
- ccxt/async_support/ascendex.py +396 -249
- ccxt/async_support/base/exchange.py +531 -155
- ccxt/async_support/base/ws/aiohttp_client.py +28 -5
- ccxt/async_support/base/ws/cache.py +3 -2
- ccxt/async_support/base/ws/client.py +26 -5
- ccxt/async_support/base/ws/fast_client.py +4 -3
- ccxt/async_support/base/ws/functions.py +1 -1
- ccxt/async_support/base/ws/future.py +40 -31
- ccxt/async_support/base/ws/order_book_side.py +3 -0
- ccxt/async_support/bequant.py +1 -1
- ccxt/async_support/bigone.py +329 -202
- ccxt/async_support/binance.py +3513 -1511
- ccxt/async_support/binancecoinm.py +2 -1
- ccxt/async_support/binanceus.py +12 -1
- ccxt/async_support/binanceusdm.py +3 -1
- ccxt/async_support/bingx.py +3105 -881
- ccxt/async_support/bit2c.py +119 -38
- ccxt/async_support/bitbank.py +215 -76
- ccxt/async_support/bitbns.py +124 -53
- ccxt/async_support/bitfinex.py +3236 -1078
- ccxt/async_support/bitfinex1.py +1711 -0
- ccxt/async_support/bitflyer.py +239 -50
- ccxt/async_support/bitget.py +1513 -563
- ccxt/async_support/bithumb.py +201 -67
- ccxt/async_support/bitmart.py +1320 -435
- ccxt/async_support/bitmex.py +308 -111
- ccxt/async_support/bitopro.py +256 -96
- ccxt/async_support/bitrue.py +365 -233
- ccxt/async_support/bitso.py +201 -89
- ccxt/async_support/bitstamp.py +438 -269
- ccxt/async_support/bitteam.py +179 -73
- ccxt/async_support/bitvavo.py +180 -70
- ccxt/async_support/bl3p.py +92 -25
- ccxt/async_support/blockchaincom.py +193 -79
- ccxt/async_support/blofin.py +403 -150
- ccxt/async_support/btcalpha.py +161 -55
- ccxt/async_support/btcbox.py +250 -34
- ccxt/async_support/btcmarkets.py +232 -85
- ccxt/async_support/btcturk.py +159 -60
- ccxt/async_support/bybit.py +2326 -1255
- ccxt/async_support/cex.py +1409 -1329
- ccxt/async_support/coinbase.py +1455 -288
- ccxt/async_support/coinbaseadvanced.py +17 -0
- ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
- ccxt/async_support/coinbaseinternational.py +428 -88
- ccxt/async_support/coincatch.py +5152 -0
- ccxt/async_support/coincheck.py +121 -38
- ccxt/async_support/coinex.py +4020 -3339
- ccxt/async_support/coinlist.py +273 -116
- ccxt/async_support/coinmate.py +204 -97
- ccxt/async_support/coinmetro.py +203 -110
- ccxt/async_support/coinone.py +142 -68
- ccxt/async_support/coinsph.py +206 -89
- ccxt/async_support/coinspot.py +137 -62
- ccxt/async_support/cryptocom.py +515 -185
- ccxt/async_support/currencycom.py +203 -85
- ccxt/async_support/defx.py +2066 -0
- ccxt/async_support/delta.py +467 -158
- ccxt/async_support/deribit.py +558 -324
- ccxt/async_support/digifinex.py +340 -223
- ccxt/async_support/ellipx.py +1826 -0
- ccxt/async_support/exmo.py +259 -128
- ccxt/async_support/gate.py +1473 -464
- ccxt/async_support/gemini.py +206 -84
- ccxt/async_support/hashkey.py +4164 -0
- ccxt/async_support/hitbtc.py +334 -178
- ccxt/async_support/hollaex.py +134 -83
- ccxt/async_support/htx.py +1095 -563
- ccxt/async_support/huobijp.py +105 -56
- ccxt/async_support/hyperliquid.py +1634 -269
- ccxt/async_support/idex.py +148 -95
- ccxt/async_support/independentreserve.py +236 -31
- ccxt/async_support/indodax.py +165 -62
- ccxt/async_support/kraken.py +871 -354
- ccxt/async_support/krakenfutures.py +324 -100
- ccxt/async_support/kucoin.py +1050 -355
- ccxt/async_support/kucoinfutures.py +1004 -149
- ccxt/async_support/kuna.py +138 -106
- ccxt/async_support/latoken.py +135 -79
- ccxt/async_support/lbank.py +290 -113
- ccxt/async_support/luno.py +112 -62
- ccxt/async_support/lykke.py +104 -55
- ccxt/async_support/mercado.py +36 -29
- ccxt/async_support/mexc.py +995 -429
- ccxt/async_support/myokx.py +43 -0
- ccxt/async_support/ndax.py +163 -82
- ccxt/async_support/novadax.py +121 -75
- ccxt/async_support/oceanex.py +175 -59
- ccxt/async_support/okcoin.py +222 -163
- ccxt/async_support/okx.py +1777 -455
- ccxt/async_support/onetrading.py +132 -414
- ccxt/async_support/oxfun.py +2832 -0
- ccxt/async_support/p2b.py +79 -51
- ccxt/async_support/paradex.py +2017 -0
- ccxt/async_support/paymium.py +56 -32
- ccxt/async_support/phemex.py +572 -196
- ccxt/async_support/poloniex.py +218 -95
- ccxt/async_support/poloniexfutures.py +260 -92
- ccxt/async_support/probit.py +143 -110
- ccxt/async_support/timex.py +123 -70
- ccxt/async_support/tokocrypto.py +129 -93
- ccxt/async_support/tradeogre.py +39 -25
- ccxt/async_support/upbit.py +322 -113
- ccxt/async_support/vertex.py +2983 -0
- ccxt/async_support/wavesexchange.py +227 -173
- ccxt/async_support/wazirx.py +145 -65
- ccxt/async_support/whitebit.py +533 -138
- ccxt/async_support/woo.py +1155 -295
- ccxt/async_support/woofipro.py +2716 -0
- ccxt/async_support/xt.py +4628 -0
- ccxt/async_support/yobit.py +160 -92
- ccxt/async_support/zaif.py +80 -33
- ccxt/async_support/zonda.py +140 -69
- ccxt/base/errors.py +51 -20
- ccxt/base/exchange.py +1729 -482
- ccxt/base/precise.py +10 -0
- ccxt/base/types.py +223 -4
- ccxt/bequant.py +1 -1
- ccxt/bigone.py +329 -202
- ccxt/binance.py +3513 -1511
- ccxt/binancecoinm.py +2 -1
- ccxt/binanceus.py +12 -1
- ccxt/binanceusdm.py +3 -1
- ccxt/bingx.py +3105 -881
- ccxt/bit2c.py +119 -38
- ccxt/bitbank.py +215 -76
- ccxt/bitbns.py +124 -53
- ccxt/bitfinex.py +3235 -1078
- ccxt/bitfinex1.py +1710 -0
- ccxt/bitflyer.py +239 -50
- ccxt/bitget.py +1513 -563
- ccxt/bithumb.py +200 -67
- ccxt/bitmart.py +1320 -435
- ccxt/bitmex.py +308 -111
- ccxt/bitopro.py +256 -96
- ccxt/bitrue.py +365 -233
- ccxt/bitso.py +201 -89
- ccxt/bitstamp.py +438 -269
- ccxt/bitteam.py +179 -73
- ccxt/bitvavo.py +180 -70
- ccxt/bl3p.py +92 -25
- ccxt/blockchaincom.py +193 -79
- ccxt/blofin.py +403 -150
- ccxt/btcalpha.py +161 -55
- ccxt/btcbox.py +250 -34
- ccxt/btcmarkets.py +232 -85
- ccxt/btcturk.py +159 -60
- ccxt/bybit.py +2326 -1255
- ccxt/cex.py +1408 -1329
- ccxt/coinbase.py +1455 -288
- ccxt/coinbaseadvanced.py +17 -0
- ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
- ccxt/coinbaseinternational.py +428 -88
- ccxt/coincatch.py +5152 -0
- ccxt/coincheck.py +121 -38
- ccxt/coinex.py +4020 -3339
- ccxt/coinlist.py +273 -116
- ccxt/coinmate.py +204 -97
- ccxt/coinmetro.py +203 -110
- ccxt/coinone.py +142 -68
- ccxt/coinsph.py +206 -89
- ccxt/coinspot.py +137 -62
- ccxt/cryptocom.py +515 -185
- ccxt/currencycom.py +203 -85
- ccxt/defx.py +2065 -0
- ccxt/delta.py +467 -158
- ccxt/deribit.py +558 -324
- ccxt/digifinex.py +340 -223
- ccxt/ellipx.py +1826 -0
- ccxt/exmo.py +259 -128
- ccxt/gate.py +1473 -464
- ccxt/gemini.py +206 -84
- ccxt/hashkey.py +4164 -0
- ccxt/hitbtc.py +334 -178
- ccxt/hollaex.py +134 -83
- ccxt/htx.py +1095 -563
- ccxt/huobijp.py +105 -56
- ccxt/hyperliquid.py +1633 -269
- ccxt/idex.py +148 -95
- ccxt/independentreserve.py +235 -31
- ccxt/indodax.py +165 -62
- ccxt/kraken.py +871 -354
- ccxt/krakenfutures.py +324 -100
- ccxt/kucoin.py +1050 -355
- ccxt/kucoinfutures.py +1004 -149
- ccxt/kuna.py +138 -106
- ccxt/latoken.py +135 -79
- ccxt/lbank.py +290 -113
- ccxt/luno.py +112 -62
- ccxt/lykke.py +104 -55
- ccxt/mercado.py +36 -29
- ccxt/mexc.py +994 -429
- ccxt/myokx.py +43 -0
- ccxt/ndax.py +163 -82
- ccxt/novadax.py +121 -75
- ccxt/oceanex.py +175 -59
- ccxt/okcoin.py +222 -163
- ccxt/okx.py +1777 -455
- ccxt/onetrading.py +132 -414
- ccxt/oxfun.py +2831 -0
- ccxt/p2b.py +79 -51
- ccxt/paradex.py +2017 -0
- ccxt/paymium.py +56 -32
- ccxt/phemex.py +572 -196
- ccxt/poloniex.py +218 -95
- ccxt/poloniexfutures.py +260 -92
- ccxt/pro/__init__.py +29 -5
- ccxt/pro/alpaca.py +32 -17
- ccxt/pro/ascendex.py +63 -15
- ccxt/pro/bequant.py +4 -0
- ccxt/pro/binance.py +1596 -329
- ccxt/pro/binancecoinm.py +1 -0
- ccxt/pro/binanceus.py +2 -9
- ccxt/pro/binanceusdm.py +2 -0
- ccxt/pro/bingx.py +527 -134
- ccxt/pro/bitcoincom.py +4 -1
- ccxt/pro/bitfinex.py +731 -266
- ccxt/pro/bitfinex1.py +635 -0
- ccxt/pro/bitget.py +726 -357
- ccxt/pro/bithumb.py +380 -0
- ccxt/pro/bitmart.py +138 -39
- ccxt/pro/bitmex.py +199 -40
- ccxt/pro/bitopro.py +25 -13
- ccxt/pro/bitrue.py +31 -32
- ccxt/pro/bitstamp.py +7 -6
- ccxt/pro/bitvavo.py +204 -82
- ccxt/pro/blockchaincom.py +30 -17
- ccxt/pro/blofin.py +692 -0
- ccxt/pro/bybit.py +791 -82
- ccxt/pro/cex.py +99 -51
- ccxt/pro/coinbase.py +220 -30
- ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
- ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
- ccxt/pro/coinbaseinternational.py +193 -30
- ccxt/pro/coincatch.py +1464 -0
- ccxt/pro/coincheck.py +11 -6
- ccxt/pro/coinex.py +967 -661
- ccxt/pro/coinone.py +17 -10
- ccxt/pro/cryptocom.py +446 -66
- ccxt/pro/currencycom.py +11 -10
- ccxt/pro/defx.py +832 -0
- ccxt/pro/deribit.py +168 -32
- ccxt/pro/exmo.py +253 -21
- ccxt/pro/gate.py +729 -64
- ccxt/pro/gemini.py +44 -26
- ccxt/pro/hashkey.py +802 -0
- ccxt/pro/hitbtc.py +208 -103
- ccxt/pro/hollaex.py +25 -9
- ccxt/pro/htx.py +83 -39
- ccxt/pro/huobijp.py +17 -16
- ccxt/pro/hyperliquid.py +502 -31
- ccxt/pro/idex.py +28 -13
- ccxt/pro/independentreserve.py +21 -16
- ccxt/pro/kraken.py +298 -51
- ccxt/pro/krakenfutures.py +166 -75
- ccxt/pro/kucoin.py +395 -77
- ccxt/pro/kucoinfutures.py +400 -99
- ccxt/pro/lbank.py +52 -31
- ccxt/pro/luno.py +12 -10
- ccxt/pro/mexc.py +400 -50
- ccxt/pro/myokx.py +28 -0
- ccxt/pro/ndax.py +25 -12
- ccxt/pro/okcoin.py +28 -9
- ccxt/pro/okx.py +935 -124
- ccxt/pro/onetrading.py +41 -24
- ccxt/pro/oxfun.py +1054 -0
- ccxt/pro/p2b.py +100 -24
- ccxt/pro/paradex.py +352 -0
- ccxt/pro/phemex.py +93 -34
- ccxt/pro/poloniex.py +129 -50
- ccxt/pro/poloniexfutures.py +53 -32
- ccxt/pro/probit.py +93 -86
- ccxt/pro/upbit.py +401 -8
- ccxt/pro/vertex.py +943 -0
- ccxt/pro/wazirx.py +46 -28
- ccxt/pro/whitebit.py +65 -12
- ccxt/pro/woo.py +486 -70
- ccxt/pro/woofipro.py +1271 -0
- ccxt/pro/xt.py +1067 -0
- ccxt/probit.py +143 -110
- ccxt/static_dependencies/__init__.py +1 -1
- ccxt/static_dependencies/lark/__init__.py +38 -0
- ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
- ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
- ccxt/static_dependencies/lark/ast_utils.py +59 -0
- ccxt/static_dependencies/lark/common.py +86 -0
- ccxt/static_dependencies/lark/exceptions.py +292 -0
- ccxt/static_dependencies/lark/grammar.py +130 -0
- ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
- ccxt/static_dependencies/lark/indenter.py +143 -0
- ccxt/static_dependencies/lark/lark.py +658 -0
- ccxt/static_dependencies/lark/lexer.py +678 -0
- ccxt/static_dependencies/lark/load_grammar.py +1428 -0
- ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
- ccxt/static_dependencies/lark/parser_frontends.py +257 -0
- ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
- ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
- ccxt/static_dependencies/lark/parsers/earley.py +314 -0
- ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
- ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
- ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
- ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
- ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
- ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
- ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
- ccxt/static_dependencies/lark/py.typed +0 -0
- ccxt/static_dependencies/lark/reconstruct.py +107 -0
- ccxt/static_dependencies/lark/tools/__init__.py +70 -0
- ccxt/static_dependencies/lark/tools/nearley.py +202 -0
- ccxt/static_dependencies/lark/tools/serialize.py +32 -0
- ccxt/static_dependencies/lark/tools/standalone.py +196 -0
- ccxt/static_dependencies/lark/tree.py +267 -0
- ccxt/static_dependencies/lark/tree_matcher.py +186 -0
- ccxt/static_dependencies/lark/tree_templates.py +180 -0
- ccxt/static_dependencies/lark/utils.py +343 -0
- ccxt/static_dependencies/lark/visitors.py +596 -0
- ccxt/static_dependencies/marshmallow/__init__.py +81 -0
- ccxt/static_dependencies/marshmallow/base.py +65 -0
- ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
- ccxt/static_dependencies/marshmallow/decorators.py +231 -0
- ccxt/static_dependencies/marshmallow/error_store.py +60 -0
- ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
- ccxt/static_dependencies/marshmallow/fields.py +2114 -0
- ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
- ccxt/static_dependencies/marshmallow/py.typed +0 -0
- ccxt/static_dependencies/marshmallow/schema.py +1228 -0
- ccxt/static_dependencies/marshmallow/types.py +12 -0
- ccxt/static_dependencies/marshmallow/utils.py +378 -0
- ccxt/static_dependencies/marshmallow/validate.py +678 -0
- ccxt/static_dependencies/marshmallow/warnings.py +2 -0
- ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
- ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
- ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
- ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
- ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
- ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
- ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
- ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
- ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
- ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
- ccxt/static_dependencies/starknet/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
- ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
- ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
- ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
- ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
- ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
- ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
- ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
- ccxt/static_dependencies/starknet/common.py +15 -0
- ccxt/static_dependencies/starknet/constants.py +39 -0
- ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
- ccxt/static_dependencies/starknet/hash/address.py +79 -0
- ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
- ccxt/static_dependencies/starknet/hash/selector.py +16 -0
- ccxt/static_dependencies/starknet/hash/storage.py +12 -0
- ccxt/static_dependencies/starknet/hash/utils.py +78 -0
- ccxt/static_dependencies/starknet/models/__init__.py +0 -0
- ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
- ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
- ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
- ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
- ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
- ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
- ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
- ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
- ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
- ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
- ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
- ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
- ccxt/static_dependencies/starknet/utils/schema.py +13 -0
- ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
- ccxt/static_dependencies/starkware/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
- ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
- ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
- ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
- ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
- ccxt/static_dependencies/sympy/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/__init__.py +0 -0
- ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
- ccxt/static_dependencies/sympy/external/__init__.py +0 -0
- ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
- ccxt/static_dependencies/sympy/external/importtools.py +187 -0
- ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
- ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
- ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
- ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
- ccxt/test/{test_async.py → tests_async.py} +465 -407
- ccxt/test/tests_helpers.py +285 -0
- ccxt/test/tests_init.py +39 -0
- ccxt/test/{test_sync.py → tests_sync.py} +465 -409
- ccxt/timex.py +123 -70
- ccxt/tokocrypto.py +129 -93
- ccxt/tradeogre.py +39 -25
- ccxt/upbit.py +322 -113
- ccxt/vertex.py +2983 -0
- ccxt/wavesexchange.py +227 -173
- ccxt/wazirx.py +145 -65
- ccxt/whitebit.py +533 -138
- ccxt/woo.py +1155 -295
- ccxt/woofipro.py +2716 -0
- ccxt/xt.py +4627 -0
- ccxt/yobit.py +159 -92
- ccxt/zaif.py +80 -33
- ccxt/zonda.py +140 -69
- ccxt-4.4.48.dist-info/LICENSE.txt +21 -0
- ccxt-4.4.48.dist-info/METADATA +646 -0
- ccxt-4.4.48.dist-info/RECORD +669 -0
- {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/WHEEL +1 -1
- ccxt/abstract/bitbay.py +0 -47
- ccxt/abstract/bitfinex2.py +0 -139
- ccxt/abstract/hitbtc3.py +0 -115
- ccxt/async_support/bitbay.py +0 -17
- ccxt/async_support/bitfinex2.py +0 -3496
- ccxt/async_support/flowbtc.py +0 -34
- ccxt/bitbay.py +0 -17
- ccxt/bitfinex2.py +0 -3496
- ccxt/flowbtc.py +0 -34
- ccxt/hitbtc3.py +0 -16
- ccxt/pro/bitfinex2.py +0 -1081
- ccxt/test/base/__init__.py +0 -28
- ccxt/test/base/test_account.py +0 -26
- ccxt/test/base/test_balance.py +0 -56
- ccxt/test/base/test_borrow_interest.py +0 -35
- ccxt/test/base/test_borrow_rate.py +0 -32
- ccxt/test/base/test_calculate_fee.py +0 -51
- ccxt/test/base/test_crypto.py +0 -127
- ccxt/test/base/test_currency.py +0 -76
- ccxt/test/base/test_datetime.py +0 -103
- ccxt/test/base/test_decimal_to_precision.py +0 -392
- ccxt/test/base/test_deep_extend.py +0 -68
- ccxt/test/base/test_deposit_withdrawal.py +0 -50
- ccxt/test/base/test_exchange_datetime_functions.py +0 -76
- ccxt/test/base/test_funding_rate_history.py +0 -29
- ccxt/test/base/test_last_price.py +0 -32
- ccxt/test/base/test_ledger_entry.py +0 -45
- ccxt/test/base/test_ledger_item.py +0 -48
- ccxt/test/base/test_leverage_tier.py +0 -33
- ccxt/test/base/test_margin_mode.py +0 -24
- ccxt/test/base/test_margin_modification.py +0 -35
- ccxt/test/base/test_market.py +0 -190
- ccxt/test/base/test_number.py +0 -411
- ccxt/test/base/test_ohlcv.py +0 -32
- ccxt/test/base/test_open_interest.py +0 -32
- ccxt/test/base/test_order.py +0 -64
- ccxt/test/base/test_order_book.py +0 -63
- ccxt/test/base/test_position.py +0 -60
- ccxt/test/base/test_shared_methods.py +0 -345
- ccxt/test/base/test_status.py +0 -24
- ccxt/test/base/test_throttle.py +0 -126
- ccxt/test/base/test_ticker.py +0 -86
- ccxt/test/base/test_trade.py +0 -47
- ccxt/test/base/test_trading_fee.py +0 -26
- ccxt/test/base/test_transaction.py +0 -39
- ccxt-4.2.76.dist-info/METADATA +0 -626
- ccxt-4.2.76.dist-info/RECORD +0 -534
- {ccxt-4.2.76.dist-info → ccxt-4.4.48.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,203 @@
|
|
1
|
+
"Provides for superficial grammar analysis."
|
2
|
+
|
3
|
+
from collections import Counter, defaultdict
|
4
|
+
from typing import List, Dict, Iterator, FrozenSet, Set
|
5
|
+
|
6
|
+
from ..utils import bfs, fzset, classify
|
7
|
+
from ..exceptions import GrammarError
|
8
|
+
from ..grammar import Rule, Terminal, NonTerminal, Symbol
|
9
|
+
from ..common import ParserConf
|
10
|
+
|
11
|
+
|
12
|
+
class RulePtr:
|
13
|
+
__slots__ = ('rule', 'index')
|
14
|
+
rule: Rule
|
15
|
+
index: int
|
16
|
+
|
17
|
+
def __init__(self, rule: Rule, index: int):
|
18
|
+
assert isinstance(rule, Rule)
|
19
|
+
assert index <= len(rule.expansion)
|
20
|
+
self.rule = rule
|
21
|
+
self.index = index
|
22
|
+
|
23
|
+
def __repr__(self):
|
24
|
+
before = [x.name for x in self.rule.expansion[:self.index]]
|
25
|
+
after = [x.name for x in self.rule.expansion[self.index:]]
|
26
|
+
return '<%s : %s * %s>' % (self.rule.origin.name, ' '.join(before), ' '.join(after))
|
27
|
+
|
28
|
+
@property
|
29
|
+
def next(self) -> Symbol:
|
30
|
+
return self.rule.expansion[self.index]
|
31
|
+
|
32
|
+
def advance(self, sym: Symbol) -> 'RulePtr':
|
33
|
+
assert self.next == sym
|
34
|
+
return RulePtr(self.rule, self.index+1)
|
35
|
+
|
36
|
+
@property
|
37
|
+
def is_satisfied(self) -> bool:
|
38
|
+
return self.index == len(self.rule.expansion)
|
39
|
+
|
40
|
+
def __eq__(self, other) -> bool:
|
41
|
+
if not isinstance(other, RulePtr):
|
42
|
+
return NotImplemented
|
43
|
+
return self.rule == other.rule and self.index == other.index
|
44
|
+
|
45
|
+
def __hash__(self) -> int:
|
46
|
+
return hash((self.rule, self.index))
|
47
|
+
|
48
|
+
|
49
|
+
State = FrozenSet[RulePtr]
|
50
|
+
|
51
|
+
# state generation ensures no duplicate LR0ItemSets
|
52
|
+
class LR0ItemSet:
|
53
|
+
__slots__ = ('kernel', 'closure', 'transitions', 'lookaheads')
|
54
|
+
|
55
|
+
kernel: State
|
56
|
+
closure: State
|
57
|
+
transitions: Dict[Symbol, 'LR0ItemSet']
|
58
|
+
lookaheads: Dict[Symbol, Set[Rule]]
|
59
|
+
|
60
|
+
def __init__(self, kernel, closure):
|
61
|
+
self.kernel = fzset(kernel)
|
62
|
+
self.closure = fzset(closure)
|
63
|
+
self.transitions = {}
|
64
|
+
self.lookaheads = defaultdict(set)
|
65
|
+
|
66
|
+
def __repr__(self):
|
67
|
+
return '{%s | %s}' % (', '.join([repr(r) for r in self.kernel]), ', '.join([repr(r) for r in self.closure]))
|
68
|
+
|
69
|
+
|
70
|
+
def update_set(set1, set2):
|
71
|
+
if not set2 or set1 > set2:
|
72
|
+
return False
|
73
|
+
|
74
|
+
copy = set(set1)
|
75
|
+
set1 |= set2
|
76
|
+
return set1 != copy
|
77
|
+
|
78
|
+
def calculate_sets(rules):
|
79
|
+
"""Calculate FOLLOW sets.
|
80
|
+
|
81
|
+
Adapted from: http://lara.epfl.ch/w/cc09:algorithm_for_first_and_follow_sets"""
|
82
|
+
symbols = {sym for rule in rules for sym in rule.expansion} | {rule.origin for rule in rules}
|
83
|
+
|
84
|
+
# foreach grammar rule X ::= Y(1) ... Y(k)
|
85
|
+
# if k=0 or {Y(1),...,Y(k)} subset of NULLABLE then
|
86
|
+
# NULLABLE = NULLABLE union {X}
|
87
|
+
# for i = 1 to k
|
88
|
+
# if i=1 or {Y(1),...,Y(i-1)} subset of NULLABLE then
|
89
|
+
# FIRST(X) = FIRST(X) union FIRST(Y(i))
|
90
|
+
# for j = i+1 to k
|
91
|
+
# if i=k or {Y(i+1),...Y(k)} subset of NULLABLE then
|
92
|
+
# FOLLOW(Y(i)) = FOLLOW(Y(i)) union FOLLOW(X)
|
93
|
+
# if i+1=j or {Y(i+1),...,Y(j-1)} subset of NULLABLE then
|
94
|
+
# FOLLOW(Y(i)) = FOLLOW(Y(i)) union FIRST(Y(j))
|
95
|
+
# until none of NULLABLE,FIRST,FOLLOW changed in last iteration
|
96
|
+
|
97
|
+
NULLABLE = set()
|
98
|
+
FIRST = {}
|
99
|
+
FOLLOW = {}
|
100
|
+
for sym in symbols:
|
101
|
+
FIRST[sym]={sym} if sym.is_term else set()
|
102
|
+
FOLLOW[sym]=set()
|
103
|
+
|
104
|
+
# Calculate NULLABLE and FIRST
|
105
|
+
changed = True
|
106
|
+
while changed:
|
107
|
+
changed = False
|
108
|
+
|
109
|
+
for rule in rules:
|
110
|
+
if set(rule.expansion) <= NULLABLE:
|
111
|
+
if update_set(NULLABLE, {rule.origin}):
|
112
|
+
changed = True
|
113
|
+
|
114
|
+
for i, sym in enumerate(rule.expansion):
|
115
|
+
if set(rule.expansion[:i]) <= NULLABLE:
|
116
|
+
if update_set(FIRST[rule.origin], FIRST[sym]):
|
117
|
+
changed = True
|
118
|
+
else:
|
119
|
+
break
|
120
|
+
|
121
|
+
# Calculate FOLLOW
|
122
|
+
changed = True
|
123
|
+
while changed:
|
124
|
+
changed = False
|
125
|
+
|
126
|
+
for rule in rules:
|
127
|
+
for i, sym in enumerate(rule.expansion):
|
128
|
+
if i==len(rule.expansion)-1 or set(rule.expansion[i+1:]) <= NULLABLE:
|
129
|
+
if update_set(FOLLOW[sym], FOLLOW[rule.origin]):
|
130
|
+
changed = True
|
131
|
+
|
132
|
+
for j in range(i+1, len(rule.expansion)):
|
133
|
+
if set(rule.expansion[i+1:j]) <= NULLABLE:
|
134
|
+
if update_set(FOLLOW[sym], FIRST[rule.expansion[j]]):
|
135
|
+
changed = True
|
136
|
+
|
137
|
+
return FIRST, FOLLOW, NULLABLE
|
138
|
+
|
139
|
+
|
140
|
+
class GrammarAnalyzer:
|
141
|
+
def __init__(self, parser_conf: ParserConf, debug: bool=False, strict: bool=False):
|
142
|
+
self.debug = debug
|
143
|
+
self.strict = strict
|
144
|
+
|
145
|
+
root_rules = {start: Rule(NonTerminal('$root_' + start), [NonTerminal(start), Terminal('$END')])
|
146
|
+
for start in parser_conf.start}
|
147
|
+
|
148
|
+
rules = parser_conf.rules + list(root_rules.values())
|
149
|
+
self.rules_by_origin: Dict[NonTerminal, List[Rule]] = classify(rules, lambda r: r.origin)
|
150
|
+
|
151
|
+
if len(rules) != len(set(rules)):
|
152
|
+
duplicates = [item for item, count in Counter(rules).items() if count > 1]
|
153
|
+
raise GrammarError("Rules defined twice: %s" % ', '.join(str(i) for i in duplicates))
|
154
|
+
|
155
|
+
for r in rules:
|
156
|
+
for sym in r.expansion:
|
157
|
+
if not (sym.is_term or sym in self.rules_by_origin):
|
158
|
+
raise GrammarError("Using an undefined rule: %s" % sym)
|
159
|
+
|
160
|
+
self.start_states = {start: self.expand_rule(root_rule.origin)
|
161
|
+
for start, root_rule in root_rules.items()}
|
162
|
+
|
163
|
+
self.end_states = {start: fzset({RulePtr(root_rule, len(root_rule.expansion))})
|
164
|
+
for start, root_rule in root_rules.items()}
|
165
|
+
|
166
|
+
lr0_root_rules = {start: Rule(NonTerminal('$root_' + start), [NonTerminal(start)])
|
167
|
+
for start in parser_conf.start}
|
168
|
+
|
169
|
+
lr0_rules = parser_conf.rules + list(lr0_root_rules.values())
|
170
|
+
assert(len(lr0_rules) == len(set(lr0_rules)))
|
171
|
+
|
172
|
+
self.lr0_rules_by_origin = classify(lr0_rules, lambda r: r.origin)
|
173
|
+
|
174
|
+
# cache RulePtr(r, 0) in r (no duplicate RulePtr objects)
|
175
|
+
self.lr0_start_states = {start: LR0ItemSet([RulePtr(root_rule, 0)], self.expand_rule(root_rule.origin, self.lr0_rules_by_origin))
|
176
|
+
for start, root_rule in lr0_root_rules.items()}
|
177
|
+
|
178
|
+
self.FIRST, self.FOLLOW, self.NULLABLE = calculate_sets(rules)
|
179
|
+
|
180
|
+
def expand_rule(self, source_rule: NonTerminal, rules_by_origin=None) -> State:
|
181
|
+
"Returns all init_ptrs accessible by rule (recursive)"
|
182
|
+
|
183
|
+
if rules_by_origin is None:
|
184
|
+
rules_by_origin = self.rules_by_origin
|
185
|
+
|
186
|
+
init_ptrs = set()
|
187
|
+
def _expand_rule(rule: NonTerminal) -> Iterator[NonTerminal]:
|
188
|
+
assert not rule.is_term, rule
|
189
|
+
|
190
|
+
for r in rules_by_origin[rule]:
|
191
|
+
init_ptr = RulePtr(r, 0)
|
192
|
+
init_ptrs.add(init_ptr)
|
193
|
+
|
194
|
+
if r.expansion: # if not empty rule
|
195
|
+
new_r = init_ptr.next
|
196
|
+
if not new_r.is_term:
|
197
|
+
assert isinstance(new_r, NonTerminal)
|
198
|
+
yield new_r
|
199
|
+
|
200
|
+
for _ in bfs([source_rule], _expand_rule):
|
201
|
+
pass
|
202
|
+
|
203
|
+
return fzset(init_ptrs)
|
@@ -0,0 +1,332 @@
|
|
1
|
+
"""This module builds a LALR(1) transition-table for lalr_parser.py
|
2
|
+
|
3
|
+
For now, shift/reduce conflicts are automatically resolved as shifts.
|
4
|
+
"""
|
5
|
+
|
6
|
+
# Author: Erez Shinan (2017)
|
7
|
+
# Email : erezshin@gmail.com
|
8
|
+
|
9
|
+
from typing import Dict, Set, Iterator, Tuple, List, TypeVar, Generic
|
10
|
+
from collections import defaultdict
|
11
|
+
|
12
|
+
from ..utils import classify, classify_bool, bfs, fzset, Enumerator, logger
|
13
|
+
from ..exceptions import GrammarError
|
14
|
+
|
15
|
+
from .grammar_analysis import GrammarAnalyzer, Terminal, LR0ItemSet, RulePtr, State
|
16
|
+
from ..grammar import Rule, Symbol
|
17
|
+
from ..common import ParserConf
|
18
|
+
|
19
|
+
###{standalone
|
20
|
+
|
21
|
+
class Action:
|
22
|
+
def __init__(self, name):
|
23
|
+
self.name = name
|
24
|
+
def __str__(self):
|
25
|
+
return self.name
|
26
|
+
def __repr__(self):
|
27
|
+
return str(self)
|
28
|
+
|
29
|
+
Shift = Action('Shift')
|
30
|
+
Reduce = Action('Reduce')
|
31
|
+
|
32
|
+
StateT = TypeVar("StateT")
|
33
|
+
|
34
|
+
class ParseTableBase(Generic[StateT]):
|
35
|
+
states: Dict[StateT, Dict[str, Tuple]]
|
36
|
+
start_states: Dict[str, StateT]
|
37
|
+
end_states: Dict[str, StateT]
|
38
|
+
|
39
|
+
def __init__(self, states, start_states, end_states):
|
40
|
+
self.states = states
|
41
|
+
self.start_states = start_states
|
42
|
+
self.end_states = end_states
|
43
|
+
|
44
|
+
def serialize(self, memo):
|
45
|
+
tokens = Enumerator()
|
46
|
+
|
47
|
+
states = {
|
48
|
+
state: {tokens.get(token): ((1, arg.serialize(memo)) if action is Reduce else (0, arg))
|
49
|
+
for token, (action, arg) in actions.items()}
|
50
|
+
for state, actions in self.states.items()
|
51
|
+
}
|
52
|
+
|
53
|
+
return {
|
54
|
+
'tokens': tokens.reversed(),
|
55
|
+
'states': states,
|
56
|
+
'start_states': self.start_states,
|
57
|
+
'end_states': self.end_states,
|
58
|
+
}
|
59
|
+
|
60
|
+
@classmethod
|
61
|
+
def deserialize(cls, data, memo):
|
62
|
+
tokens = data['tokens']
|
63
|
+
states = {
|
64
|
+
state: {tokens[token]: ((Reduce, Rule.deserialize(arg, memo)) if action==1 else (Shift, arg))
|
65
|
+
for token, (action, arg) in actions.items()}
|
66
|
+
for state, actions in data['states'].items()
|
67
|
+
}
|
68
|
+
return cls(states, data['start_states'], data['end_states'])
|
69
|
+
|
70
|
+
class ParseTable(ParseTableBase['State']):
|
71
|
+
"""Parse-table whose key is State, i.e. set[RulePtr]
|
72
|
+
|
73
|
+
Slower than IntParseTable, but useful for debugging
|
74
|
+
"""
|
75
|
+
pass
|
76
|
+
|
77
|
+
|
78
|
+
class IntParseTable(ParseTableBase[int]):
|
79
|
+
"""Parse-table whose key is int. Best for performance."""
|
80
|
+
|
81
|
+
@classmethod
|
82
|
+
def from_ParseTable(cls, parse_table: ParseTable):
|
83
|
+
enum = list(parse_table.states)
|
84
|
+
state_to_idx: Dict['State', int] = {s:i for i,s in enumerate(enum)}
|
85
|
+
int_states = {}
|
86
|
+
|
87
|
+
for s, la in parse_table.states.items():
|
88
|
+
la = {k:(v[0], state_to_idx[v[1]]) if v[0] is Shift else v
|
89
|
+
for k,v in la.items()}
|
90
|
+
int_states[ state_to_idx[s] ] = la
|
91
|
+
|
92
|
+
|
93
|
+
start_states = {start:state_to_idx[s] for start, s in parse_table.start_states.items()}
|
94
|
+
end_states = {start:state_to_idx[s] for start, s in parse_table.end_states.items()}
|
95
|
+
return cls(int_states, start_states, end_states)
|
96
|
+
|
97
|
+
###}
|
98
|
+
|
99
|
+
|
100
|
+
# digraph and traverse, see The Theory and Practice of Compiler Writing
|
101
|
+
|
102
|
+
# computes F(x) = G(x) union (union { G(y) | x R y })
|
103
|
+
# X: nodes
|
104
|
+
# R: relation (function mapping node -> list of nodes that satisfy the relation)
|
105
|
+
# G: set valued function
|
106
|
+
def digraph(X, R, G):
|
107
|
+
F = {}
|
108
|
+
S = []
|
109
|
+
N = dict.fromkeys(X, 0)
|
110
|
+
for x in X:
|
111
|
+
# this is always true for the first iteration, but N[x] may be updated in traverse below
|
112
|
+
if N[x] == 0:
|
113
|
+
traverse(x, S, N, X, R, G, F)
|
114
|
+
return F
|
115
|
+
|
116
|
+
# x: single node
|
117
|
+
# S: stack
|
118
|
+
# N: weights
|
119
|
+
# X: nodes
|
120
|
+
# R: relation (see above)
|
121
|
+
# G: set valued function
|
122
|
+
# F: set valued function we are computing (map of input -> output)
|
123
|
+
def traverse(x, S, N, X, R, G, F):
|
124
|
+
S.append(x)
|
125
|
+
d = len(S)
|
126
|
+
N[x] = d
|
127
|
+
F[x] = G[x]
|
128
|
+
for y in R[x]:
|
129
|
+
if N[y] == 0:
|
130
|
+
traverse(y, S, N, X, R, G, F)
|
131
|
+
n_x = N[x]
|
132
|
+
assert(n_x > 0)
|
133
|
+
n_y = N[y]
|
134
|
+
assert(n_y != 0)
|
135
|
+
if (n_y > 0) and (n_y < n_x):
|
136
|
+
N[x] = n_y
|
137
|
+
F[x].update(F[y])
|
138
|
+
if N[x] == d:
|
139
|
+
f_x = F[x]
|
140
|
+
while True:
|
141
|
+
z = S.pop()
|
142
|
+
N[z] = -1
|
143
|
+
F[z] = f_x
|
144
|
+
if z == x:
|
145
|
+
break
|
146
|
+
|
147
|
+
|
148
|
+
class LALR_Analyzer(GrammarAnalyzer):
|
149
|
+
lr0_itemsets: Set[LR0ItemSet]
|
150
|
+
nonterminal_transitions: List[Tuple[LR0ItemSet, Symbol]]
|
151
|
+
lookback: Dict[Tuple[LR0ItemSet, Symbol], Set[Tuple[LR0ItemSet, Rule]]]
|
152
|
+
includes: Dict[Tuple[LR0ItemSet, Symbol], Set[Tuple[LR0ItemSet, Symbol]]]
|
153
|
+
reads: Dict[Tuple[LR0ItemSet, Symbol], Set[Tuple[LR0ItemSet, Symbol]]]
|
154
|
+
directly_reads: Dict[Tuple[LR0ItemSet, Symbol], Set[Symbol]]
|
155
|
+
|
156
|
+
|
157
|
+
def __init__(self, parser_conf: ParserConf, debug: bool=False, strict: bool=False):
|
158
|
+
GrammarAnalyzer.__init__(self, parser_conf, debug, strict)
|
159
|
+
self.nonterminal_transitions = []
|
160
|
+
self.directly_reads = defaultdict(set)
|
161
|
+
self.reads = defaultdict(set)
|
162
|
+
self.includes = defaultdict(set)
|
163
|
+
self.lookback = defaultdict(set)
|
164
|
+
|
165
|
+
|
166
|
+
def compute_lr0_states(self) -> None:
|
167
|
+
self.lr0_itemsets = set()
|
168
|
+
# map of kernels to LR0ItemSets
|
169
|
+
cache: Dict['State', LR0ItemSet] = {}
|
170
|
+
|
171
|
+
def step(state: LR0ItemSet) -> Iterator[LR0ItemSet]:
|
172
|
+
_, unsat = classify_bool(state.closure, lambda rp: rp.is_satisfied)
|
173
|
+
|
174
|
+
d = classify(unsat, lambda rp: rp.next)
|
175
|
+
for sym, rps in d.items():
|
176
|
+
kernel = fzset({rp.advance(sym) for rp in rps})
|
177
|
+
new_state = cache.get(kernel, None)
|
178
|
+
if new_state is None:
|
179
|
+
closure = set(kernel)
|
180
|
+
for rp in kernel:
|
181
|
+
if not rp.is_satisfied and not rp.next.is_term:
|
182
|
+
closure |= self.expand_rule(rp.next, self.lr0_rules_by_origin)
|
183
|
+
new_state = LR0ItemSet(kernel, closure)
|
184
|
+
cache[kernel] = new_state
|
185
|
+
|
186
|
+
state.transitions[sym] = new_state
|
187
|
+
yield new_state
|
188
|
+
|
189
|
+
self.lr0_itemsets.add(state)
|
190
|
+
|
191
|
+
for _ in bfs(self.lr0_start_states.values(), step):
|
192
|
+
pass
|
193
|
+
|
194
|
+
def compute_reads_relations(self):
|
195
|
+
# handle start state
|
196
|
+
for root in self.lr0_start_states.values():
|
197
|
+
assert(len(root.kernel) == 1)
|
198
|
+
for rp in root.kernel:
|
199
|
+
assert(rp.index == 0)
|
200
|
+
self.directly_reads[(root, rp.next)] = set([ Terminal('$END') ])
|
201
|
+
|
202
|
+
for state in self.lr0_itemsets:
|
203
|
+
seen = set()
|
204
|
+
for rp in state.closure:
|
205
|
+
if rp.is_satisfied:
|
206
|
+
continue
|
207
|
+
s = rp.next
|
208
|
+
# if s is a not a nonterminal
|
209
|
+
if s not in self.lr0_rules_by_origin:
|
210
|
+
continue
|
211
|
+
if s in seen:
|
212
|
+
continue
|
213
|
+
seen.add(s)
|
214
|
+
nt = (state, s)
|
215
|
+
self.nonterminal_transitions.append(nt)
|
216
|
+
dr = self.directly_reads[nt]
|
217
|
+
r = self.reads[nt]
|
218
|
+
next_state = state.transitions[s]
|
219
|
+
for rp2 in next_state.closure:
|
220
|
+
if rp2.is_satisfied:
|
221
|
+
continue
|
222
|
+
s2 = rp2.next
|
223
|
+
# if s2 is a terminal
|
224
|
+
if s2 not in self.lr0_rules_by_origin:
|
225
|
+
dr.add(s2)
|
226
|
+
if s2 in self.NULLABLE:
|
227
|
+
r.add((next_state, s2))
|
228
|
+
|
229
|
+
def compute_includes_lookback(self):
|
230
|
+
for nt in self.nonterminal_transitions:
|
231
|
+
state, nonterminal = nt
|
232
|
+
includes = []
|
233
|
+
lookback = self.lookback[nt]
|
234
|
+
for rp in state.closure:
|
235
|
+
if rp.rule.origin != nonterminal:
|
236
|
+
continue
|
237
|
+
# traverse the states for rp(.rule)
|
238
|
+
state2 = state
|
239
|
+
for i in range(rp.index, len(rp.rule.expansion)):
|
240
|
+
s = rp.rule.expansion[i]
|
241
|
+
nt2 = (state2, s)
|
242
|
+
state2 = state2.transitions[s]
|
243
|
+
if nt2 not in self.reads:
|
244
|
+
continue
|
245
|
+
for j in range(i + 1, len(rp.rule.expansion)):
|
246
|
+
if rp.rule.expansion[j] not in self.NULLABLE:
|
247
|
+
break
|
248
|
+
else:
|
249
|
+
includes.append(nt2)
|
250
|
+
# state2 is at the final state for rp.rule
|
251
|
+
if rp.index == 0:
|
252
|
+
for rp2 in state2.closure:
|
253
|
+
if (rp2.rule == rp.rule) and rp2.is_satisfied:
|
254
|
+
lookback.add((state2, rp2.rule))
|
255
|
+
for nt2 in includes:
|
256
|
+
self.includes[nt2].add(nt)
|
257
|
+
|
258
|
+
def compute_lookaheads(self):
|
259
|
+
read_sets = digraph(self.nonterminal_transitions, self.reads, self.directly_reads)
|
260
|
+
follow_sets = digraph(self.nonterminal_transitions, self.includes, read_sets)
|
261
|
+
|
262
|
+
for nt, lookbacks in self.lookback.items():
|
263
|
+
for state, rule in lookbacks:
|
264
|
+
for s in follow_sets[nt]:
|
265
|
+
state.lookaheads[s].add(rule)
|
266
|
+
|
267
|
+
def compute_lalr1_states(self) -> None:
|
268
|
+
m: Dict[LR0ItemSet, Dict[str, Tuple]] = {}
|
269
|
+
reduce_reduce = []
|
270
|
+
for itemset in self.lr0_itemsets:
|
271
|
+
actions: Dict[Symbol, Tuple] = {la: (Shift, next_state.closure)
|
272
|
+
for la, next_state in itemset.transitions.items()}
|
273
|
+
for la, rules in itemset.lookaheads.items():
|
274
|
+
if len(rules) > 1:
|
275
|
+
# Try to resolve conflict based on priority
|
276
|
+
p = [(r.options.priority or 0, r) for r in rules]
|
277
|
+
p.sort(key=lambda r: r[0], reverse=True)
|
278
|
+
best, second_best = p[:2]
|
279
|
+
if best[0] > second_best[0]:
|
280
|
+
rules = {best[1]}
|
281
|
+
else:
|
282
|
+
reduce_reduce.append((itemset, la, rules))
|
283
|
+
continue
|
284
|
+
|
285
|
+
rule ,= rules
|
286
|
+
if la in actions:
|
287
|
+
if self.strict:
|
288
|
+
raise GrammarError(f"Shift/Reduce conflict for terminal {la.name}. [strict-mode]\n ")
|
289
|
+
elif self.debug:
|
290
|
+
logger.warning('Shift/Reduce conflict for terminal %s: (resolving as shift)', la.name)
|
291
|
+
logger.warning(' * %s', rule)
|
292
|
+
else:
|
293
|
+
logger.debug('Shift/Reduce conflict for terminal %s: (resolving as shift)', la.name)
|
294
|
+
logger.debug(' * %s', rule)
|
295
|
+
else:
|
296
|
+
actions[la] = (Reduce, rule)
|
297
|
+
m[itemset] = { k.name: v for k, v in actions.items() }
|
298
|
+
|
299
|
+
if reduce_reduce:
|
300
|
+
msgs = []
|
301
|
+
for itemset, la, rules in reduce_reduce:
|
302
|
+
msg = 'Reduce/Reduce collision in %s between the following rules: %s' % (la, ''.join([ '\n\t- ' + str(r) for r in rules ]))
|
303
|
+
if self.debug:
|
304
|
+
msg += '\n collision occurred in state: {%s\n }' % ''.join(['\n\t' + str(x) for x in itemset.closure])
|
305
|
+
msgs.append(msg)
|
306
|
+
raise GrammarError('\n\n'.join(msgs))
|
307
|
+
|
308
|
+
states = { k.closure: v for k, v in m.items() }
|
309
|
+
|
310
|
+
# compute end states
|
311
|
+
end_states: Dict[str, 'State'] = {}
|
312
|
+
for state in states:
|
313
|
+
for rp in state:
|
314
|
+
for start in self.lr0_start_states:
|
315
|
+
if rp.rule.origin.name == ('$root_' + start) and rp.is_satisfied:
|
316
|
+
assert start not in end_states
|
317
|
+
end_states[start] = state
|
318
|
+
|
319
|
+
start_states = { start: state.closure for start, state in self.lr0_start_states.items() }
|
320
|
+
_parse_table = ParseTable(states, start_states, end_states)
|
321
|
+
|
322
|
+
if self.debug:
|
323
|
+
self.parse_table = _parse_table
|
324
|
+
else:
|
325
|
+
self.parse_table = IntParseTable.from_ParseTable(_parse_table)
|
326
|
+
|
327
|
+
def compute_lalr(self):
|
328
|
+
self.compute_lr0_states()
|
329
|
+
self.compute_reads_relations()
|
330
|
+
self.compute_includes_lookback()
|
331
|
+
self.compute_lookaheads()
|
332
|
+
self.compute_lalr1_states()
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# This module provides a LALR interactive parser, which is used for debugging and error handling
|
2
|
+
|
3
|
+
from typing import Iterator, List
|
4
|
+
from copy import copy
|
5
|
+
import warnings
|
6
|
+
|
7
|
+
from ..exceptions import UnexpectedToken
|
8
|
+
from ..lexer import Token, LexerThread
|
9
|
+
from .lalr_parser_state import ParserState
|
10
|
+
|
11
|
+
###{standalone
|
12
|
+
|
13
|
+
class InteractiveParser:
|
14
|
+
"""InteractiveParser gives you advanced control over parsing and error handling when parsing with LALR.
|
15
|
+
|
16
|
+
For a simpler interface, see the ``on_error`` argument to ``Lark.parse()``.
|
17
|
+
"""
|
18
|
+
def __init__(self, parser, parser_state: ParserState, lexer_thread: LexerThread):
|
19
|
+
self.parser = parser
|
20
|
+
self.parser_state = parser_state
|
21
|
+
self.lexer_thread = lexer_thread
|
22
|
+
self.result = None
|
23
|
+
|
24
|
+
@property
|
25
|
+
def lexer_state(self) -> LexerThread:
|
26
|
+
warnings.warn("lexer_state will be removed in subsequent releases. Use lexer_thread instead.", DeprecationWarning)
|
27
|
+
return self.lexer_thread
|
28
|
+
|
29
|
+
def feed_token(self, token: Token):
|
30
|
+
"""Feed the parser with a token, and advance it to the next state, as if it received it from the lexer.
|
31
|
+
|
32
|
+
Note that ``token`` has to be an instance of ``Token``.
|
33
|
+
"""
|
34
|
+
return self.parser_state.feed_token(token, token.type == '$END')
|
35
|
+
|
36
|
+
def iter_parse(self) -> Iterator[Token]:
|
37
|
+
"""Step through the different stages of the parse, by reading tokens from the lexer
|
38
|
+
and feeding them to the parser, one per iteration.
|
39
|
+
|
40
|
+
Returns an iterator of the tokens it encounters.
|
41
|
+
|
42
|
+
When the parse is over, the resulting tree can be found in ``InteractiveParser.result``.
|
43
|
+
"""
|
44
|
+
for token in self.lexer_thread.lex(self.parser_state):
|
45
|
+
yield token
|
46
|
+
self.result = self.feed_token(token)
|
47
|
+
|
48
|
+
def exhaust_lexer(self) -> List[Token]:
|
49
|
+
"""Try to feed the rest of the lexer state into the interactive parser.
|
50
|
+
|
51
|
+
Note that this modifies the instance in place and does not feed an '$END' Token
|
52
|
+
"""
|
53
|
+
return list(self.iter_parse())
|
54
|
+
|
55
|
+
|
56
|
+
def feed_eof(self, last_token=None):
|
57
|
+
"""Feed a '$END' Token. Borrows from 'last_token' if given."""
|
58
|
+
eof = Token.new_borrow_pos('$END', '', last_token) if last_token is not None else self.lexer_thread._Token('$END', '', 0, 1, 1)
|
59
|
+
return self.feed_token(eof)
|
60
|
+
|
61
|
+
|
62
|
+
def __copy__(self):
|
63
|
+
"""Create a new interactive parser with a separate state.
|
64
|
+
|
65
|
+
Calls to feed_token() won't affect the old instance, and vice-versa.
|
66
|
+
"""
|
67
|
+
return self.copy()
|
68
|
+
|
69
|
+
def copy(self, deepcopy_values=True):
|
70
|
+
return type(self)(
|
71
|
+
self.parser,
|
72
|
+
self.parser_state.copy(deepcopy_values=deepcopy_values),
|
73
|
+
copy(self.lexer_thread),
|
74
|
+
)
|
75
|
+
|
76
|
+
def __eq__(self, other):
|
77
|
+
if not isinstance(other, InteractiveParser):
|
78
|
+
return False
|
79
|
+
|
80
|
+
return self.parser_state == other.parser_state and self.lexer_thread == other.lexer_thread
|
81
|
+
|
82
|
+
def as_immutable(self):
|
83
|
+
"""Convert to an ``ImmutableInteractiveParser``."""
|
84
|
+
p = copy(self)
|
85
|
+
return ImmutableInteractiveParser(p.parser, p.parser_state, p.lexer_thread)
|
86
|
+
|
87
|
+
def pretty(self):
|
88
|
+
"""Print the output of ``choices()`` in a way that's easier to read."""
|
89
|
+
out = ["Parser choices:"]
|
90
|
+
for k, v in self.choices().items():
|
91
|
+
out.append('\t- %s -> %r' % (k, v))
|
92
|
+
out.append('stack size: %s' % len(self.parser_state.state_stack))
|
93
|
+
return '\n'.join(out)
|
94
|
+
|
95
|
+
def choices(self):
|
96
|
+
"""Returns a dictionary of token types, matched to their action in the parser.
|
97
|
+
|
98
|
+
Only returns token types that are accepted by the current state.
|
99
|
+
|
100
|
+
Updated by ``feed_token()``.
|
101
|
+
"""
|
102
|
+
return self.parser_state.parse_conf.parse_table.states[self.parser_state.position]
|
103
|
+
|
104
|
+
def accepts(self):
|
105
|
+
"""Returns the set of possible tokens that will advance the parser into a new valid state."""
|
106
|
+
accepts = set()
|
107
|
+
conf_no_callbacks = copy(self.parser_state.parse_conf)
|
108
|
+
# We don't want to call callbacks here since those might have arbitrary side effects
|
109
|
+
# and are unnecessarily slow.
|
110
|
+
conf_no_callbacks.callbacks = {}
|
111
|
+
for t in self.choices():
|
112
|
+
if t.isupper(): # is terminal?
|
113
|
+
new_cursor = self.copy(deepcopy_values=False)
|
114
|
+
new_cursor.parser_state.parse_conf = conf_no_callbacks
|
115
|
+
try:
|
116
|
+
new_cursor.feed_token(self.lexer_thread._Token(t, ''))
|
117
|
+
except UnexpectedToken:
|
118
|
+
pass
|
119
|
+
else:
|
120
|
+
accepts.add(t)
|
121
|
+
return accepts
|
122
|
+
|
123
|
+
def resume_parse(self):
|
124
|
+
"""Resume automated parsing from the current state.
|
125
|
+
"""
|
126
|
+
return self.parser.parse_from_state(self.parser_state, last_token=self.lexer_thread.state.last_token)
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
class ImmutableInteractiveParser(InteractiveParser):
|
131
|
+
"""Same as ``InteractiveParser``, but operations create a new instance instead
|
132
|
+
of changing it in-place.
|
133
|
+
"""
|
134
|
+
|
135
|
+
result = None
|
136
|
+
|
137
|
+
def __hash__(self):
|
138
|
+
return hash((self.parser_state, self.lexer_thread))
|
139
|
+
|
140
|
+
def feed_token(self, token):
|
141
|
+
c = copy(self)
|
142
|
+
c.result = InteractiveParser.feed_token(c, token)
|
143
|
+
return c
|
144
|
+
|
145
|
+
def exhaust_lexer(self):
|
146
|
+
"""Try to feed the rest of the lexer state into the parser.
|
147
|
+
|
148
|
+
Note that this returns a new ImmutableInteractiveParser and does not feed an '$END' Token"""
|
149
|
+
cursor = self.as_mutable()
|
150
|
+
cursor.exhaust_lexer()
|
151
|
+
return cursor.as_immutable()
|
152
|
+
|
153
|
+
def as_mutable(self):
|
154
|
+
"""Convert to an ``InteractiveParser``."""
|
155
|
+
p = copy(self)
|
156
|
+
return InteractiveParser(p.parser, p.parser_state, p.lexer_thread)
|
157
|
+
|
158
|
+
###}
|