ccxt 4.2.77__py2.py3-none-any.whl → 4.4.49__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +24 -0
- ccxt/abstract/kucoinfutures.py +34 -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 +3030 -1087
- 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 +3205 -937
- 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 +238 -49
- ccxt/async_support/bitget.py +1525 -573
- ccxt/async_support/bithumb.py +199 -65
- 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 +392 -148
- 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 +2231 -1193
- ccxt/async_support/cex.py +1409 -1329
- ccxt/async_support/coinbase.py +1454 -287
- 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 +223 -97
- 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 +404 -109
- ccxt/async_support/deribit.py +639 -323
- ccxt/async_support/digifinex.py +465 -233
- ccxt/async_support/ellipx.py +1887 -0
- ccxt/async_support/exmo.py +317 -128
- ccxt/async_support/gate.py +1472 -463
- ccxt/async_support/gemini.py +206 -84
- ccxt/async_support/hashkey.py +4164 -0
- ccxt/async_support/hitbtc.py +433 -178
- ccxt/async_support/hollaex.py +207 -83
- ccxt/async_support/htx.py +1095 -563
- ccxt/async_support/huobijp.py +178 -56
- ccxt/async_support/hyperliquid.py +1678 -292
- ccxt/async_support/idex.py +219 -95
- ccxt/async_support/independentreserve.py +300 -31
- ccxt/async_support/indodax.py +226 -62
- ccxt/async_support/kraken.py +871 -354
- ccxt/async_support/krakenfutures.py +324 -100
- ccxt/async_support/kucoin.py +917 -357
- ccxt/async_support/kucoinfutures.py +1004 -149
- ccxt/async_support/kuna.py +198 -107
- ccxt/async_support/latoken.py +199 -79
- ccxt/async_support/lbank.py +360 -113
- ccxt/async_support/luno.py +185 -62
- ccxt/async_support/lykke.py +168 -55
- ccxt/async_support/mercado.py +101 -29
- ccxt/async_support/mexc.py +995 -429
- ccxt/async_support/myokx.py +53 -0
- ccxt/async_support/ndax.py +234 -82
- ccxt/async_support/novadax.py +195 -75
- ccxt/async_support/oceanex.py +244 -59
- ccxt/async_support/okcoin.py +301 -165
- ccxt/async_support/okx.py +1776 -454
- ccxt/async_support/onetrading.py +198 -414
- ccxt/async_support/oxfun.py +2898 -0
- ccxt/async_support/p2b.py +142 -52
- ccxt/async_support/paradex.py +2085 -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 +1137 -296
- 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 +1722 -480
- 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 +3030 -1087
- ccxt/binancecoinm.py +2 -1
- ccxt/binanceus.py +12 -1
- ccxt/binanceusdm.py +3 -1
- ccxt/bingx.py +3205 -937
- 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 +238 -49
- ccxt/bitget.py +1525 -573
- ccxt/bithumb.py +198 -65
- 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 +392 -148
- ccxt/btcalpha.py +161 -55
- ccxt/btcbox.py +250 -34
- ccxt/btcmarkets.py +232 -85
- ccxt/btcturk.py +159 -60
- ccxt/bybit.py +2231 -1193
- ccxt/cex.py +1408 -1329
- ccxt/coinbase.py +1454 -287
- 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 +223 -97
- ccxt/coinspot.py +137 -62
- ccxt/cryptocom.py +515 -185
- ccxt/currencycom.py +203 -85
- ccxt/defx.py +2065 -0
- ccxt/delta.py +404 -109
- ccxt/deribit.py +639 -323
- ccxt/digifinex.py +465 -233
- ccxt/ellipx.py +1887 -0
- ccxt/exmo.py +317 -128
- ccxt/gate.py +1472 -463
- ccxt/gemini.py +206 -84
- ccxt/hashkey.py +4164 -0
- ccxt/hitbtc.py +433 -178
- ccxt/hollaex.py +207 -83
- ccxt/htx.py +1095 -563
- ccxt/huobijp.py +178 -56
- ccxt/hyperliquid.py +1677 -292
- ccxt/idex.py +219 -95
- ccxt/independentreserve.py +299 -31
- ccxt/indodax.py +226 -62
- ccxt/kraken.py +871 -354
- ccxt/krakenfutures.py +324 -100
- ccxt/kucoin.py +917 -357
- ccxt/kucoinfutures.py +1004 -149
- ccxt/kuna.py +198 -107
- ccxt/latoken.py +199 -79
- ccxt/lbank.py +360 -113
- ccxt/luno.py +185 -62
- ccxt/lykke.py +168 -55
- ccxt/mercado.py +101 -29
- ccxt/mexc.py +994 -429
- ccxt/myokx.py +53 -0
- ccxt/ndax.py +234 -82
- ccxt/novadax.py +195 -75
- ccxt/oceanex.py +244 -59
- ccxt/okcoin.py +301 -165
- ccxt/okx.py +1776 -454
- ccxt/onetrading.py +198 -414
- ccxt/oxfun.py +2897 -0
- ccxt/p2b.py +142 -52
- ccxt/paradex.py +2085 -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 +62 -14
- 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 +143 -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 +203 -81
- 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 +965 -665
- 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 +167 -31
- ccxt/pro/exmo.py +252 -20
- 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 +92 -33
- ccxt/pro/poloniex.py +128 -49
- ccxt/pro/poloniexfutures.py +53 -32
- ccxt/pro/probit.py +92 -85
- 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 +437 -65
- 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} +456 -391
- ccxt/test/tests_helpers.py +285 -0
- ccxt/test/tests_init.py +39 -0
- ccxt/test/{test_sync.py → tests_sync.py} +456 -393
- 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 +1137 -296
- 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.49.dist-info/LICENSE.txt +21 -0
- ccxt-4.4.49.dist-info/METADATA +646 -0
- ccxt-4.4.49.dist-info/RECORD +669 -0
- {ccxt-4.2.77.dist-info → ccxt-4.4.49.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.77.dist-info/METADATA +0 -626
- ccxt-4.2.77.dist-info/RECORD +0 -534
- {ccxt-4.2.77.dist-info → ccxt-4.4.49.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
"""This module implements a LALR(1) Parser
|
2
|
+
"""
|
3
|
+
# Author: Erez Shinan (2017)
|
4
|
+
# Email : erezshin@gmail.com
|
5
|
+
from typing import Dict, Any, Optional
|
6
|
+
from ..lexer import Token, LexerThread
|
7
|
+
from ..utils import Serialize
|
8
|
+
from ..common import ParserConf, ParserCallbacks
|
9
|
+
|
10
|
+
from .lalr_analysis import LALR_Analyzer, IntParseTable, ParseTableBase
|
11
|
+
from .lalr_interactive_parser import InteractiveParser
|
12
|
+
from ..exceptions import UnexpectedCharacters, UnexpectedInput, UnexpectedToken
|
13
|
+
from .lalr_parser_state import ParserState, ParseConf
|
14
|
+
|
15
|
+
###{standalone
|
16
|
+
|
17
|
+
class LALR_Parser(Serialize):
|
18
|
+
def __init__(self, parser_conf: ParserConf, debug: bool=False, strict: bool=False):
|
19
|
+
analysis = LALR_Analyzer(parser_conf, debug=debug, strict=strict)
|
20
|
+
analysis.compute_lalr()
|
21
|
+
callbacks = parser_conf.callbacks
|
22
|
+
|
23
|
+
self._parse_table = analysis.parse_table
|
24
|
+
self.parser_conf = parser_conf
|
25
|
+
self.parser = _Parser(analysis.parse_table, callbacks, debug)
|
26
|
+
|
27
|
+
@classmethod
|
28
|
+
def deserialize(cls, data, memo, callbacks, debug=False):
|
29
|
+
inst = cls.__new__(cls)
|
30
|
+
inst._parse_table = IntParseTable.deserialize(data, memo)
|
31
|
+
inst.parser = _Parser(inst._parse_table, callbacks, debug)
|
32
|
+
return inst
|
33
|
+
|
34
|
+
def serialize(self, memo: Any = None) -> Dict[str, Any]:
|
35
|
+
return self._parse_table.serialize(memo)
|
36
|
+
|
37
|
+
def parse_interactive(self, lexer: LexerThread, start: str):
|
38
|
+
return self.parser.parse(lexer, start, start_interactive=True)
|
39
|
+
|
40
|
+
def parse(self, lexer, start, on_error=None):
|
41
|
+
try:
|
42
|
+
return self.parser.parse(lexer, start)
|
43
|
+
except UnexpectedInput as e:
|
44
|
+
if on_error is None:
|
45
|
+
raise
|
46
|
+
|
47
|
+
while True:
|
48
|
+
if isinstance(e, UnexpectedCharacters):
|
49
|
+
s = e.interactive_parser.lexer_thread.state
|
50
|
+
p = s.line_ctr.char_pos
|
51
|
+
|
52
|
+
if not on_error(e):
|
53
|
+
raise e
|
54
|
+
|
55
|
+
if isinstance(e, UnexpectedCharacters):
|
56
|
+
# If user didn't change the character position, then we should
|
57
|
+
if p == s.line_ctr.char_pos:
|
58
|
+
s.line_ctr.feed(s.text[p:p+1])
|
59
|
+
|
60
|
+
try:
|
61
|
+
return e.interactive_parser.resume_parse()
|
62
|
+
except UnexpectedToken as e2:
|
63
|
+
if (isinstance(e, UnexpectedToken)
|
64
|
+
and e.token.type == e2.token.type == '$END'
|
65
|
+
and e.interactive_parser == e2.interactive_parser):
|
66
|
+
# Prevent infinite loop
|
67
|
+
raise e2
|
68
|
+
e = e2
|
69
|
+
except UnexpectedCharacters as e2:
|
70
|
+
e = e2
|
71
|
+
|
72
|
+
|
73
|
+
class _Parser:
|
74
|
+
parse_table: ParseTableBase
|
75
|
+
callbacks: ParserCallbacks
|
76
|
+
debug: bool
|
77
|
+
|
78
|
+
def __init__(self, parse_table: ParseTableBase, callbacks: ParserCallbacks, debug: bool=False):
|
79
|
+
self.parse_table = parse_table
|
80
|
+
self.callbacks = callbacks
|
81
|
+
self.debug = debug
|
82
|
+
|
83
|
+
def parse(self, lexer: LexerThread, start: str, value_stack=None, state_stack=None, start_interactive=False):
|
84
|
+
parse_conf = ParseConf(self.parse_table, self.callbacks, start)
|
85
|
+
parser_state = ParserState(parse_conf, lexer, state_stack, value_stack)
|
86
|
+
if start_interactive:
|
87
|
+
return InteractiveParser(self, parser_state, parser_state.lexer)
|
88
|
+
return self.parse_from_state(parser_state)
|
89
|
+
|
90
|
+
|
91
|
+
def parse_from_state(self, state: ParserState, last_token: Optional[Token]=None):
|
92
|
+
"""Run the main LALR parser loop
|
93
|
+
|
94
|
+
Parameters:
|
95
|
+
state - the initial state. Changed in-place.
|
96
|
+
last_token - Used only for line information in case of an empty lexer.
|
97
|
+
"""
|
98
|
+
try:
|
99
|
+
token = last_token
|
100
|
+
for token in state.lexer.lex(state):
|
101
|
+
assert token is not None
|
102
|
+
state.feed_token(token)
|
103
|
+
|
104
|
+
end_token = Token.new_borrow_pos('$END', '', token) if token else Token('$END', '', 0, 1, 1)
|
105
|
+
return state.feed_token(end_token, True)
|
106
|
+
except UnexpectedInput as e:
|
107
|
+
try:
|
108
|
+
e.interactive_parser = InteractiveParser(self, state, state.lexer)
|
109
|
+
except NameError:
|
110
|
+
pass
|
111
|
+
raise e
|
112
|
+
except Exception as e:
|
113
|
+
if self.debug:
|
114
|
+
print("")
|
115
|
+
print("STATE STACK DUMP")
|
116
|
+
print("----------------")
|
117
|
+
for i, s in enumerate(state.state_stack):
|
118
|
+
print('%d)' % i , s)
|
119
|
+
print("")
|
120
|
+
|
121
|
+
raise
|
122
|
+
###}
|
@@ -0,0 +1,110 @@
|
|
1
|
+
from copy import deepcopy, copy
|
2
|
+
from typing import Dict, Any, Generic, List
|
3
|
+
from ..lexer import Token, LexerThread
|
4
|
+
from ..common import ParserCallbacks
|
5
|
+
|
6
|
+
from .lalr_analysis import Shift, ParseTableBase, StateT
|
7
|
+
from ..exceptions import UnexpectedToken
|
8
|
+
|
9
|
+
###{standalone
|
10
|
+
|
11
|
+
class ParseConf(Generic[StateT]):
|
12
|
+
__slots__ = 'parse_table', 'callbacks', 'start', 'start_state', 'end_state', 'states'
|
13
|
+
|
14
|
+
parse_table: ParseTableBase[StateT]
|
15
|
+
callbacks: ParserCallbacks
|
16
|
+
start: str
|
17
|
+
|
18
|
+
start_state: StateT
|
19
|
+
end_state: StateT
|
20
|
+
states: Dict[StateT, Dict[str, tuple]]
|
21
|
+
|
22
|
+
def __init__(self, parse_table: ParseTableBase[StateT], callbacks: ParserCallbacks, start: str):
|
23
|
+
self.parse_table = parse_table
|
24
|
+
|
25
|
+
self.start_state = self.parse_table.start_states[start]
|
26
|
+
self.end_state = self.parse_table.end_states[start]
|
27
|
+
self.states = self.parse_table.states
|
28
|
+
|
29
|
+
self.callbacks = callbacks
|
30
|
+
self.start = start
|
31
|
+
|
32
|
+
class ParserState(Generic[StateT]):
|
33
|
+
__slots__ = 'parse_conf', 'lexer', 'state_stack', 'value_stack'
|
34
|
+
|
35
|
+
parse_conf: ParseConf[StateT]
|
36
|
+
lexer: LexerThread
|
37
|
+
state_stack: List[StateT]
|
38
|
+
value_stack: list
|
39
|
+
|
40
|
+
def __init__(self, parse_conf: ParseConf[StateT], lexer: LexerThread, state_stack=None, value_stack=None):
|
41
|
+
self.parse_conf = parse_conf
|
42
|
+
self.lexer = lexer
|
43
|
+
self.state_stack = state_stack or [self.parse_conf.start_state]
|
44
|
+
self.value_stack = value_stack or []
|
45
|
+
|
46
|
+
@property
|
47
|
+
def position(self) -> StateT:
|
48
|
+
return self.state_stack[-1]
|
49
|
+
|
50
|
+
# Necessary for match_examples() to work
|
51
|
+
def __eq__(self, other) -> bool:
|
52
|
+
if not isinstance(other, ParserState):
|
53
|
+
return NotImplemented
|
54
|
+
return len(self.state_stack) == len(other.state_stack) and self.position == other.position
|
55
|
+
|
56
|
+
def __copy__(self):
|
57
|
+
return self.copy()
|
58
|
+
|
59
|
+
def copy(self, deepcopy_values=True) -> 'ParserState[StateT]':
|
60
|
+
return type(self)(
|
61
|
+
self.parse_conf,
|
62
|
+
self.lexer, # XXX copy
|
63
|
+
copy(self.state_stack),
|
64
|
+
deepcopy(self.value_stack) if deepcopy_values else copy(self.value_stack),
|
65
|
+
)
|
66
|
+
|
67
|
+
def feed_token(self, token: Token, is_end=False) -> Any:
|
68
|
+
state_stack = self.state_stack
|
69
|
+
value_stack = self.value_stack
|
70
|
+
states = self.parse_conf.states
|
71
|
+
end_state = self.parse_conf.end_state
|
72
|
+
callbacks = self.parse_conf.callbacks
|
73
|
+
|
74
|
+
while True:
|
75
|
+
state = state_stack[-1]
|
76
|
+
try:
|
77
|
+
action, arg = states[state][token.type]
|
78
|
+
except KeyError:
|
79
|
+
expected = {s for s in states[state].keys() if s.isupper()}
|
80
|
+
raise UnexpectedToken(token, expected, state=self, interactive_parser=None)
|
81
|
+
|
82
|
+
assert arg != end_state
|
83
|
+
|
84
|
+
if action is Shift:
|
85
|
+
# shift once and return
|
86
|
+
assert not is_end
|
87
|
+
state_stack.append(arg)
|
88
|
+
value_stack.append(token if token.type not in callbacks else callbacks[token.type](token))
|
89
|
+
return
|
90
|
+
else:
|
91
|
+
# reduce+shift as many times as necessary
|
92
|
+
rule = arg
|
93
|
+
size = len(rule.expansion)
|
94
|
+
if size:
|
95
|
+
s = value_stack[-size:]
|
96
|
+
del state_stack[-size:]
|
97
|
+
del value_stack[-size:]
|
98
|
+
else:
|
99
|
+
s = []
|
100
|
+
|
101
|
+
value = callbacks[rule](s) if callbacks else s
|
102
|
+
|
103
|
+
_action, new_state = states[state_stack[-1]][rule.origin.name]
|
104
|
+
assert _action is Shift
|
105
|
+
state_stack.append(new_state)
|
106
|
+
value_stack.append(value)
|
107
|
+
|
108
|
+
if is_end and state_stack[-1] == end_state:
|
109
|
+
return value_stack[-1]
|
110
|
+
###}
|
@@ -0,0 +1,165 @@
|
|
1
|
+
"""This module implements an Earley parser with a dynamic lexer
|
2
|
+
|
3
|
+
The core Earley algorithm used here is based on Elizabeth Scott's implementation, here:
|
4
|
+
https://www.sciencedirect.com/science/article/pii/S1571066108001497
|
5
|
+
|
6
|
+
That is probably the best reference for understanding the algorithm here.
|
7
|
+
|
8
|
+
The Earley parser outputs an SPPF-tree as per that document. The SPPF tree format
|
9
|
+
is better documented here:
|
10
|
+
http://www.bramvandersanden.com/post/2014/06/shared-packed-parse-forest/
|
11
|
+
|
12
|
+
Instead of running a lexer beforehand, or using a costy char-by-char method, this parser
|
13
|
+
uses regular expressions by necessity, achieving high-performance while maintaining all of
|
14
|
+
Earley's power in parsing any CFG.
|
15
|
+
"""
|
16
|
+
|
17
|
+
from typing import TYPE_CHECKING, Callable, Optional, List, Any
|
18
|
+
from collections import defaultdict
|
19
|
+
|
20
|
+
from ..tree import Tree
|
21
|
+
from ..exceptions import UnexpectedCharacters
|
22
|
+
from ..lexer import Token
|
23
|
+
from ..grammar import Terminal
|
24
|
+
from .earley import Parser as BaseParser
|
25
|
+
from .earley_forest import TokenNode
|
26
|
+
|
27
|
+
if TYPE_CHECKING:
|
28
|
+
from ..common import LexerConf, ParserConf
|
29
|
+
|
30
|
+
class Parser(BaseParser):
|
31
|
+
def __init__(self, lexer_conf: 'LexerConf', parser_conf: 'ParserConf', term_matcher: Callable,
|
32
|
+
resolve_ambiguity: bool=True, complete_lex: bool=False, debug: bool=False,
|
33
|
+
tree_class: Optional[Callable[[str, List], Any]]=Tree, ordered_sets: bool=True):
|
34
|
+
BaseParser.__init__(self, lexer_conf, parser_conf, term_matcher, resolve_ambiguity,
|
35
|
+
debug, tree_class, ordered_sets)
|
36
|
+
self.ignore = [Terminal(t) for t in lexer_conf.ignore]
|
37
|
+
self.complete_lex = complete_lex
|
38
|
+
|
39
|
+
def _parse(self, stream, columns, to_scan, start_symbol=None):
|
40
|
+
|
41
|
+
def scan(i, to_scan):
|
42
|
+
"""The core Earley Scanner.
|
43
|
+
|
44
|
+
This is a custom implementation of the scanner that uses the
|
45
|
+
Lark lexer to match tokens. The scan list is built by the
|
46
|
+
Earley predictor, based on the previously completed tokens.
|
47
|
+
This ensures that at each phase of the parse we have a custom
|
48
|
+
lexer context, allowing for more complex ambiguities."""
|
49
|
+
|
50
|
+
node_cache = {}
|
51
|
+
|
52
|
+
# 1) Loop the expectations and ask the lexer to match.
|
53
|
+
# Since regexp is forward looking on the input stream, and we only
|
54
|
+
# want to process tokens when we hit the point in the stream at which
|
55
|
+
# they complete, we push all tokens into a buffer (delayed_matches), to
|
56
|
+
# be held possibly for a later parse step when we reach the point in the
|
57
|
+
# input stream at which they complete.
|
58
|
+
for item in self.Set(to_scan):
|
59
|
+
m = match(item.expect, stream, i)
|
60
|
+
if m:
|
61
|
+
t = Token(item.expect.name, m.group(0), i, text_line, text_column)
|
62
|
+
delayed_matches[m.end()].append( (item, i, t) )
|
63
|
+
|
64
|
+
if self.complete_lex:
|
65
|
+
s = m.group(0)
|
66
|
+
for j in range(1, len(s)):
|
67
|
+
m = match(item.expect, s[:-j])
|
68
|
+
if m:
|
69
|
+
t = Token(item.expect.name, m.group(0), i, text_line, text_column)
|
70
|
+
delayed_matches[i+m.end()].append( (item, i, t) )
|
71
|
+
|
72
|
+
# XXX The following 3 lines were commented out for causing a bug. See issue #768
|
73
|
+
# # Remove any items that successfully matched in this pass from the to_scan buffer.
|
74
|
+
# # This ensures we don't carry over tokens that already matched, if we're ignoring below.
|
75
|
+
# to_scan.remove(item)
|
76
|
+
|
77
|
+
# 3) Process any ignores. This is typically used for e.g. whitespace.
|
78
|
+
# We carry over any unmatched items from the to_scan buffer to be matched again after
|
79
|
+
# the ignore. This should allow us to use ignored symbols in non-terminals to implement
|
80
|
+
# e.g. mandatory spacing.
|
81
|
+
for x in self.ignore:
|
82
|
+
m = match(x, stream, i)
|
83
|
+
if m:
|
84
|
+
# Carry over any items still in the scan buffer, to past the end of the ignored items.
|
85
|
+
delayed_matches[m.end()].extend([(item, i, None) for item in to_scan ])
|
86
|
+
|
87
|
+
# If we're ignoring up to the end of the file, # carry over the start symbol if it already completed.
|
88
|
+
delayed_matches[m.end()].extend([(item, i, None) for item in columns[i] if item.is_complete and item.s == start_symbol])
|
89
|
+
|
90
|
+
next_to_scan = self.Set()
|
91
|
+
next_set = self.Set()
|
92
|
+
columns.append(next_set)
|
93
|
+
transitives.append({})
|
94
|
+
|
95
|
+
## 4) Process Tokens from delayed_matches.
|
96
|
+
# This is the core of the Earley scanner. Create an SPPF node for each Token,
|
97
|
+
# and create the symbol node in the SPPF tree. Advance the item that completed,
|
98
|
+
# and add the resulting new item to either the Earley set (for processing by the
|
99
|
+
# completer/predictor) or the to_scan buffer for the next parse step.
|
100
|
+
for item, start, token in delayed_matches[i+1]:
|
101
|
+
if token is not None:
|
102
|
+
token.end_line = text_line
|
103
|
+
token.end_column = text_column + 1
|
104
|
+
token.end_pos = i + 1
|
105
|
+
|
106
|
+
new_item = item.advance()
|
107
|
+
label = (new_item.s, new_item.start, i + 1)
|
108
|
+
token_node = TokenNode(token, terminals[token.type])
|
109
|
+
new_item.node = node_cache[label] if label in node_cache else node_cache.setdefault(label, self.SymbolNode(*label))
|
110
|
+
new_item.node.add_family(new_item.s, item.rule, new_item.start, item.node, token_node)
|
111
|
+
else:
|
112
|
+
new_item = item
|
113
|
+
|
114
|
+
if new_item.expect in self.TERMINALS:
|
115
|
+
# add (B ::= Aai+1.B, h, y) to Q'
|
116
|
+
next_to_scan.add(new_item)
|
117
|
+
else:
|
118
|
+
# add (B ::= Aa+1.B, h, y) to Ei+1
|
119
|
+
next_set.add(new_item)
|
120
|
+
|
121
|
+
del delayed_matches[i+1] # No longer needed, so unburden memory
|
122
|
+
|
123
|
+
if not next_set and not delayed_matches and not next_to_scan:
|
124
|
+
considered_rules = list(sorted(to_scan, key=lambda key: key.rule.origin.name))
|
125
|
+
raise UnexpectedCharacters(stream, i, text_line, text_column, {item.expect.name for item in to_scan},
|
126
|
+
set(to_scan), state=frozenset(i.s for i in to_scan),
|
127
|
+
considered_rules=considered_rules
|
128
|
+
)
|
129
|
+
|
130
|
+
return next_to_scan
|
131
|
+
|
132
|
+
|
133
|
+
delayed_matches = defaultdict(list)
|
134
|
+
match = self.term_matcher
|
135
|
+
terminals = self.lexer_conf.terminals_by_name
|
136
|
+
|
137
|
+
# Cache for nodes & tokens created in a particular parse step.
|
138
|
+
transitives = [{}]
|
139
|
+
|
140
|
+
text_line = 1
|
141
|
+
text_column = 1
|
142
|
+
|
143
|
+
## The main Earley loop.
|
144
|
+
# Run the Prediction/Completion cycle for any Items in the current Earley set.
|
145
|
+
# Completions will be added to the SPPF tree, and predictions will be recursively
|
146
|
+
# processed down to terminals/empty nodes to be added to the scanner for the next
|
147
|
+
# step.
|
148
|
+
i = 0
|
149
|
+
for token in stream:
|
150
|
+
self.predict_and_complete(i, to_scan, columns, transitives)
|
151
|
+
|
152
|
+
to_scan = scan(i, to_scan)
|
153
|
+
|
154
|
+
if token == '\n':
|
155
|
+
text_line += 1
|
156
|
+
text_column = 1
|
157
|
+
else:
|
158
|
+
text_column += 1
|
159
|
+
i += 1
|
160
|
+
|
161
|
+
self.predict_and_complete(i, to_scan, columns, transitives)
|
162
|
+
|
163
|
+
## Column is now the final column in the parse.
|
164
|
+
assert i == len(columns)-1
|
165
|
+
return to_scan
|
File without changes
|
@@ -0,0 +1,107 @@
|
|
1
|
+
"""This is an experimental tool for reconstructing text from a shaped tree, based on a Lark grammar.
|
2
|
+
"""
|
3
|
+
|
4
|
+
from typing import Dict, Callable, Iterable, Optional
|
5
|
+
|
6
|
+
from .lark import Lark
|
7
|
+
from .tree import Tree, ParseTree
|
8
|
+
from .visitors import Transformer_InPlace
|
9
|
+
from .lexer import Token, PatternStr, TerminalDef
|
10
|
+
from .grammar import Terminal, NonTerminal, Symbol
|
11
|
+
|
12
|
+
from .tree_matcher import TreeMatcher, is_discarded_terminal
|
13
|
+
from .utils import is_id_continue
|
14
|
+
|
15
|
+
def is_iter_empty(i):
|
16
|
+
try:
|
17
|
+
_ = next(i)
|
18
|
+
return False
|
19
|
+
except StopIteration:
|
20
|
+
return True
|
21
|
+
|
22
|
+
|
23
|
+
class WriteTokensTransformer(Transformer_InPlace):
|
24
|
+
"Inserts discarded tokens into their correct place, according to the rules of grammar"
|
25
|
+
|
26
|
+
tokens: Dict[str, TerminalDef]
|
27
|
+
term_subs: Dict[str, Callable[[Symbol], str]]
|
28
|
+
|
29
|
+
def __init__(self, tokens: Dict[str, TerminalDef], term_subs: Dict[str, Callable[[Symbol], str]]) -> None:
|
30
|
+
self.tokens = tokens
|
31
|
+
self.term_subs = term_subs
|
32
|
+
|
33
|
+
def __default__(self, data, children, meta):
|
34
|
+
if not getattr(meta, 'match_tree', False):
|
35
|
+
return Tree(data, children)
|
36
|
+
|
37
|
+
iter_args = iter(children)
|
38
|
+
to_write = []
|
39
|
+
for sym in meta.orig_expansion:
|
40
|
+
if is_discarded_terminal(sym):
|
41
|
+
try:
|
42
|
+
v = self.term_subs[sym.name](sym)
|
43
|
+
except KeyError:
|
44
|
+
t = self.tokens[sym.name]
|
45
|
+
if not isinstance(t.pattern, PatternStr):
|
46
|
+
raise NotImplementedError("Reconstructing regexps not supported yet: %s" % t)
|
47
|
+
|
48
|
+
v = t.pattern.value
|
49
|
+
to_write.append(v)
|
50
|
+
else:
|
51
|
+
x = next(iter_args)
|
52
|
+
if isinstance(x, list):
|
53
|
+
to_write += x
|
54
|
+
else:
|
55
|
+
if isinstance(x, Token):
|
56
|
+
assert Terminal(x.type) == sym, x
|
57
|
+
else:
|
58
|
+
assert NonTerminal(x.data) == sym, (sym, x)
|
59
|
+
to_write.append(x)
|
60
|
+
|
61
|
+
assert is_iter_empty(iter_args)
|
62
|
+
return to_write
|
63
|
+
|
64
|
+
|
65
|
+
class Reconstructor(TreeMatcher):
|
66
|
+
"""
|
67
|
+
A Reconstructor that will, given a full parse Tree, generate source code.
|
68
|
+
|
69
|
+
Note:
|
70
|
+
The reconstructor cannot generate values from regexps. If you need to produce discarded
|
71
|
+
regexes, such as newlines, use `term_subs` and provide default values for them.
|
72
|
+
|
73
|
+
Parameters:
|
74
|
+
parser: a Lark instance
|
75
|
+
term_subs: a dictionary of [Terminal name as str] to [output text as str]
|
76
|
+
"""
|
77
|
+
|
78
|
+
write_tokens: WriteTokensTransformer
|
79
|
+
|
80
|
+
def __init__(self, parser: Lark, term_subs: Optional[Dict[str, Callable[[Symbol], str]]]=None) -> None:
|
81
|
+
TreeMatcher.__init__(self, parser)
|
82
|
+
|
83
|
+
self.write_tokens = WriteTokensTransformer({t.name:t for t in self.tokens}, term_subs or {})
|
84
|
+
|
85
|
+
def _reconstruct(self, tree):
|
86
|
+
unreduced_tree = self.match_tree(tree, tree.data)
|
87
|
+
|
88
|
+
res = self.write_tokens.transform(unreduced_tree)
|
89
|
+
for item in res:
|
90
|
+
if isinstance(item, Tree):
|
91
|
+
# TODO use orig_expansion.rulename to support templates
|
92
|
+
yield from self._reconstruct(item)
|
93
|
+
else:
|
94
|
+
yield item
|
95
|
+
|
96
|
+
def reconstruct(self, tree: ParseTree, postproc: Optional[Callable[[Iterable[str]], Iterable[str]]]=None, insert_spaces: bool=True) -> str:
|
97
|
+
x = self._reconstruct(tree)
|
98
|
+
if postproc:
|
99
|
+
x = postproc(x)
|
100
|
+
y = []
|
101
|
+
prev_item = ''
|
102
|
+
for item in x:
|
103
|
+
if insert_spaces and prev_item and item and is_id_continue(prev_item[-1]) and is_id_continue(item[0]):
|
104
|
+
y.append(' ')
|
105
|
+
y.append(item)
|
106
|
+
prev_item = item
|
107
|
+
return ''.join(y)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import sys
|
2
|
+
from argparse import ArgumentParser, FileType
|
3
|
+
from textwrap import indent
|
4
|
+
from logging import DEBUG, INFO, WARN, ERROR
|
5
|
+
from typing import Optional
|
6
|
+
import warnings
|
7
|
+
|
8
|
+
from lark import Lark, logger
|
9
|
+
try:
|
10
|
+
from interegular import logger as interegular_logger
|
11
|
+
has_interegular = True
|
12
|
+
except ImportError:
|
13
|
+
has_interegular = False
|
14
|
+
|
15
|
+
lalr_argparser = ArgumentParser(add_help=False, epilog='Look at the Lark documentation for more info on the options')
|
16
|
+
|
17
|
+
flags = [
|
18
|
+
('d', 'debug'),
|
19
|
+
'keep_all_tokens',
|
20
|
+
'regex',
|
21
|
+
'propagate_positions',
|
22
|
+
'maybe_placeholders',
|
23
|
+
'use_bytes'
|
24
|
+
]
|
25
|
+
|
26
|
+
options = ['start', 'lexer']
|
27
|
+
|
28
|
+
lalr_argparser.add_argument('-v', '--verbose', action='count', default=0, help="Increase Logger output level, up to three times")
|
29
|
+
lalr_argparser.add_argument('-s', '--start', action='append', default=[])
|
30
|
+
lalr_argparser.add_argument('-l', '--lexer', default='contextual', choices=('basic', 'contextual'))
|
31
|
+
lalr_argparser.add_argument('-o', '--out', type=FileType('w', encoding='utf-8'), default=sys.stdout, help='the output file (default=stdout)')
|
32
|
+
lalr_argparser.add_argument('grammar_file', type=FileType('r', encoding='utf-8'), help='A valid .lark file')
|
33
|
+
|
34
|
+
for flag in flags:
|
35
|
+
if isinstance(flag, tuple):
|
36
|
+
options.append(flag[1])
|
37
|
+
lalr_argparser.add_argument('-' + flag[0], '--' + flag[1], action='store_true')
|
38
|
+
elif isinstance(flag, str):
|
39
|
+
options.append(flag)
|
40
|
+
lalr_argparser.add_argument('--' + flag, action='store_true')
|
41
|
+
else:
|
42
|
+
raise NotImplementedError("flags must only contain strings or tuples of strings")
|
43
|
+
|
44
|
+
|
45
|
+
def build_lalr(namespace):
|
46
|
+
logger.setLevel((ERROR, WARN, INFO, DEBUG)[min(namespace.verbose, 3)])
|
47
|
+
if has_interegular:
|
48
|
+
interegular_logger.setLevel(logger.getEffectiveLevel())
|
49
|
+
if len(namespace.start) == 0:
|
50
|
+
namespace.start.append('start')
|
51
|
+
kwargs = {n: getattr(namespace, n) for n in options}
|
52
|
+
return Lark(namespace.grammar_file, parser='lalr', **kwargs), namespace.out
|
53
|
+
|
54
|
+
|
55
|
+
def showwarning_as_comment(message, category, filename, lineno, file=None, line=None):
|
56
|
+
# Based on warnings._showwarnmsg_impl
|
57
|
+
text = warnings.formatwarning(message, category, filename, lineno, line)
|
58
|
+
text = indent(text, '# ')
|
59
|
+
if file is None:
|
60
|
+
file = sys.stderr
|
61
|
+
if file is None:
|
62
|
+
return
|
63
|
+
try:
|
64
|
+
file.write(text)
|
65
|
+
except OSError:
|
66
|
+
pass
|
67
|
+
|
68
|
+
|
69
|
+
def make_warnings_comments():
|
70
|
+
warnings.showwarning = showwarning_as_comment
|