ccxt 4.3.53__py2.py3-none-any.whl → 4.3.55__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/kucoin.py +3 -0
  3. ccxt/abstract/kucoinfutures.py +3 -0
  4. ccxt/ace.py +1 -1
  5. ccxt/alpaca.py +1 -1
  6. ccxt/ascendex.py +6 -4
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/ace.py +1 -1
  9. ccxt/async_support/alpaca.py +1 -1
  10. ccxt/async_support/ascendex.py +6 -4
  11. ccxt/async_support/base/exchange.py +1 -1
  12. ccxt/async_support/bigone.py +1 -1
  13. ccxt/async_support/binance.py +6 -6
  14. ccxt/async_support/bingx.py +4 -4
  15. ccxt/async_support/bit2c.py +1 -1
  16. ccxt/async_support/bitbank.py +1 -1
  17. ccxt/async_support/bitbns.py +1 -1
  18. ccxt/async_support/bitfinex.py +1 -1
  19. ccxt/async_support/bitfinex2.py +1 -1
  20. ccxt/async_support/bitflyer.py +1 -1
  21. ccxt/async_support/bitget.py +2 -2
  22. ccxt/async_support/bithumb.py +1 -1
  23. ccxt/async_support/bitmart.py +3 -3
  24. ccxt/async_support/bitmex.py +1 -1
  25. ccxt/async_support/bitopro.py +1 -1
  26. ccxt/async_support/bitrue.py +1 -1
  27. ccxt/async_support/bitso.py +1 -1
  28. ccxt/async_support/bitstamp.py +1 -1
  29. ccxt/async_support/bitteam.py +1 -1
  30. ccxt/async_support/bitvavo.py +2 -2
  31. ccxt/async_support/bl3p.py +1 -1
  32. ccxt/async_support/blockchaincom.py +28 -28
  33. ccxt/async_support/blofin.py +1 -1
  34. ccxt/async_support/btcalpha.py +4 -11
  35. ccxt/async_support/btcbox.py +1 -1
  36. ccxt/async_support/btcmarkets.py +1 -1
  37. ccxt/async_support/btcturk.py +1 -1
  38. ccxt/async_support/bybit.py +2 -2
  39. ccxt/async_support/cex.py +2 -2
  40. ccxt/async_support/coinbase.py +33 -33
  41. ccxt/async_support/coinbaseexchange.py +1 -1
  42. ccxt/async_support/coinbaseinternational.py +1 -1
  43. ccxt/async_support/coincheck.py +1 -1
  44. ccxt/async_support/coinex.py +2 -2
  45. ccxt/async_support/coinlist.py +2 -2
  46. ccxt/async_support/coinmate.py +1 -1
  47. ccxt/async_support/coinmetro.py +1 -1
  48. ccxt/async_support/coinone.py +1 -1
  49. ccxt/async_support/coinsph.py +1 -1
  50. ccxt/async_support/coinspot.py +1 -1
  51. ccxt/async_support/cryptocom.py +1 -1
  52. ccxt/async_support/currencycom.py +1 -1
  53. ccxt/async_support/delta.py +2 -2
  54. ccxt/async_support/deribit.py +4 -4
  55. ccxt/async_support/digifinex.py +2 -2
  56. ccxt/async_support/exmo.py +2 -2
  57. ccxt/async_support/gate.py +2 -2
  58. ccxt/async_support/gemini.py +1 -1
  59. ccxt/async_support/hitbtc.py +1 -1
  60. ccxt/async_support/hollaex.py +1 -1
  61. ccxt/async_support/htx.py +3 -3
  62. ccxt/async_support/huobijp.py +1 -1
  63. ccxt/async_support/hyperliquid.py +2 -2
  64. ccxt/async_support/idex.py +1 -1
  65. ccxt/async_support/independentreserve.py +1 -1
  66. ccxt/async_support/indodax.py +1 -1
  67. ccxt/async_support/kraken.py +2 -2
  68. ccxt/async_support/kucoin.py +127 -46
  69. ccxt/async_support/kucoinfutures.py +1 -1
  70. ccxt/async_support/kuna.py +1 -1
  71. ccxt/async_support/latoken.py +1 -1
  72. ccxt/async_support/lbank.py +1 -1
  73. ccxt/async_support/luno.py +1 -1
  74. ccxt/async_support/lykke.py +1 -1
  75. ccxt/async_support/mercado.py +1 -1
  76. ccxt/async_support/mexc.py +1 -1
  77. ccxt/async_support/ndax.py +1 -1
  78. ccxt/async_support/novadax.py +1 -1
  79. ccxt/async_support/oceanex.py +1 -1
  80. ccxt/async_support/okcoin.py +1 -1
  81. ccxt/async_support/okx.py +3 -3
  82. ccxt/async_support/onetrading.py +1 -1
  83. ccxt/async_support/oxfun.py +2 -2
  84. ccxt/async_support/p2b.py +1 -1
  85. ccxt/async_support/paymium.py +1 -1
  86. ccxt/async_support/phemex.py +30 -3
  87. ccxt/async_support/poloniex.py +6 -4
  88. ccxt/async_support/poloniexfutures.py +1 -1
  89. ccxt/async_support/probit.py +1 -1
  90. ccxt/async_support/timex.py +1 -1
  91. ccxt/async_support/tokocrypto.py +1 -1
  92. ccxt/async_support/tradeogre.py +1 -1
  93. ccxt/async_support/upbit.py +1 -1
  94. ccxt/async_support/vertex.py +2 -2
  95. ccxt/async_support/wavesexchange.py +1 -1
  96. ccxt/async_support/wazirx.py +1 -1
  97. ccxt/async_support/whitebit.py +2 -2
  98. ccxt/async_support/woo.py +31 -23
  99. ccxt/async_support/woofipro.py +3 -3
  100. ccxt/async_support/yobit.py +1 -1
  101. ccxt/async_support/zaif.py +1 -1
  102. ccxt/async_support/zonda.py +1 -1
  103. ccxt/base/exchange.py +1 -1
  104. ccxt/base/types.py +4 -1
  105. ccxt/bigone.py +1 -1
  106. ccxt/binance.py +6 -6
  107. ccxt/bingx.py +4 -4
  108. ccxt/bit2c.py +1 -1
  109. ccxt/bitbank.py +1 -1
  110. ccxt/bitbns.py +1 -1
  111. ccxt/bitfinex.py +1 -1
  112. ccxt/bitfinex2.py +1 -1
  113. ccxt/bitflyer.py +1 -1
  114. ccxt/bitget.py +2 -2
  115. ccxt/bithumb.py +1 -1
  116. ccxt/bitmart.py +3 -3
  117. ccxt/bitmex.py +1 -1
  118. ccxt/bitopro.py +1 -1
  119. ccxt/bitrue.py +1 -1
  120. ccxt/bitso.py +1 -1
  121. ccxt/bitstamp.py +1 -1
  122. ccxt/bitteam.py +1 -1
  123. ccxt/bitvavo.py +2 -2
  124. ccxt/bl3p.py +1 -1
  125. ccxt/blockchaincom.py +28 -28
  126. ccxt/blofin.py +1 -1
  127. ccxt/btcalpha.py +4 -11
  128. ccxt/btcbox.py +1 -1
  129. ccxt/btcmarkets.py +1 -1
  130. ccxt/btcturk.py +1 -1
  131. ccxt/bybit.py +2 -2
  132. ccxt/cex.py +2 -2
  133. ccxt/coinbase.py +33 -33
  134. ccxt/coinbaseexchange.py +1 -1
  135. ccxt/coinbaseinternational.py +1 -1
  136. ccxt/coincheck.py +1 -1
  137. ccxt/coinex.py +2 -2
  138. ccxt/coinlist.py +2 -2
  139. ccxt/coinmate.py +1 -1
  140. ccxt/coinmetro.py +1 -1
  141. ccxt/coinone.py +1 -1
  142. ccxt/coinsph.py +1 -1
  143. ccxt/coinspot.py +1 -1
  144. ccxt/cryptocom.py +1 -1
  145. ccxt/currencycom.py +1 -1
  146. ccxt/delta.py +2 -2
  147. ccxt/deribit.py +4 -4
  148. ccxt/digifinex.py +2 -2
  149. ccxt/exmo.py +2 -2
  150. ccxt/gate.py +2 -2
  151. ccxt/gemini.py +1 -1
  152. ccxt/hitbtc.py +1 -1
  153. ccxt/hollaex.py +1 -1
  154. ccxt/htx.py +3 -3
  155. ccxt/huobijp.py +1 -1
  156. ccxt/hyperliquid.py +2 -2
  157. ccxt/idex.py +1 -1
  158. ccxt/independentreserve.py +1 -1
  159. ccxt/indodax.py +1 -1
  160. ccxt/kraken.py +2 -2
  161. ccxt/kucoin.py +127 -46
  162. ccxt/kucoinfutures.py +1 -1
  163. ccxt/kuna.py +1 -1
  164. ccxt/latoken.py +1 -1
  165. ccxt/lbank.py +1 -1
  166. ccxt/luno.py +1 -1
  167. ccxt/lykke.py +1 -1
  168. ccxt/mercado.py +1 -1
  169. ccxt/mexc.py +1 -1
  170. ccxt/ndax.py +1 -1
  171. ccxt/novadax.py +1 -1
  172. ccxt/oceanex.py +1 -1
  173. ccxt/okcoin.py +1 -1
  174. ccxt/okx.py +3 -3
  175. ccxt/onetrading.py +1 -1
  176. ccxt/oxfun.py +2 -2
  177. ccxt/p2b.py +1 -1
  178. ccxt/paymium.py +1 -1
  179. ccxt/phemex.py +30 -3
  180. ccxt/poloniex.py +6 -4
  181. ccxt/poloniexfutures.py +1 -1
  182. ccxt/pro/__init__.py +1 -1
  183. ccxt/pro/binance.py +3 -3
  184. ccxt/pro/bitvavo.py +2 -2
  185. ccxt/pro/bybit.py +20 -14
  186. ccxt/pro/cex.py +3 -3
  187. ccxt/pro/coinbase.py +22 -1
  188. ccxt/pro/cryptocom.py +1 -1
  189. ccxt/pro/gate.py +2 -2
  190. ccxt/pro/hitbtc.py +1 -1
  191. ccxt/pro/kraken.py +2 -2
  192. ccxt/pro/kucoin.py +65 -28
  193. ccxt/pro/okx.py +2 -2
  194. ccxt/pro/oxfun.py +2 -2
  195. ccxt/pro/poloniex.py +1 -1
  196. ccxt/pro/vertex.py +2 -2
  197. ccxt/probit.py +1 -1
  198. ccxt/test/{test_async.py → tests_async.py} +27 -280
  199. ccxt/test/tests_helpers.py +284 -0
  200. ccxt/test/tests_init.py +35 -0
  201. ccxt/test/{test_sync.py → tests_sync.py} +27 -282
  202. ccxt/timex.py +1 -1
  203. ccxt/tokocrypto.py +1 -1
  204. ccxt/tradeogre.py +1 -1
  205. ccxt/upbit.py +1 -1
  206. ccxt/vertex.py +2 -2
  207. ccxt/wavesexchange.py +1 -1
  208. ccxt/wazirx.py +1 -1
  209. ccxt/whitebit.py +2 -2
  210. ccxt/woo.py +31 -23
  211. ccxt/woofipro.py +3 -3
  212. ccxt/yobit.py +1 -1
  213. ccxt/zaif.py +1 -1
  214. ccxt/zonda.py +1 -1
  215. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/METADATA +5 -5
  216. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/RECORD +219 -252
  217. ccxt/test/base/__init__.py +0 -29
  218. ccxt/test/base/test_account.py +0 -26
  219. ccxt/test/base/test_balance.py +0 -56
  220. ccxt/test/base/test_borrow_interest.py +0 -35
  221. ccxt/test/base/test_borrow_rate.py +0 -32
  222. ccxt/test/base/test_calculate_fee.py +0 -51
  223. ccxt/test/base/test_crypto.py +0 -127
  224. ccxt/test/base/test_currency.py +0 -76
  225. ccxt/test/base/test_datetime.py +0 -109
  226. ccxt/test/base/test_decimal_to_precision.py +0 -392
  227. ccxt/test/base/test_deep_extend.py +0 -68
  228. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  229. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  230. ccxt/test/base/test_funding_rate_history.py +0 -29
  231. ccxt/test/base/test_last_price.py +0 -31
  232. ccxt/test/base/test_ledger_entry.py +0 -45
  233. ccxt/test/base/test_ledger_item.py +0 -48
  234. ccxt/test/base/test_leverage_tier.py +0 -33
  235. ccxt/test/base/test_liquidation.py +0 -50
  236. ccxt/test/base/test_margin_mode.py +0 -24
  237. ccxt/test/base/test_margin_modification.py +0 -35
  238. ccxt/test/base/test_market.py +0 -193
  239. ccxt/test/base/test_number.py +0 -411
  240. ccxt/test/base/test_ohlcv.py +0 -33
  241. ccxt/test/base/test_open_interest.py +0 -32
  242. ccxt/test/base/test_order.py +0 -64
  243. ccxt/test/base/test_order_book.py +0 -69
  244. ccxt/test/base/test_position.py +0 -60
  245. ccxt/test/base/test_shared_methods.py +0 -353
  246. ccxt/test/base/test_status.py +0 -24
  247. ccxt/test/base/test_throttle.py +0 -126
  248. ccxt/test/base/test_ticker.py +0 -92
  249. ccxt/test/base/test_trade.py +0 -47
  250. ccxt/test/base/test_trading_fee.py +0 -26
  251. ccxt/test/base/test_transaction.py +0 -39
  252. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/LICENSE.txt +0 -0
  253. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/WHEEL +0 -0
  254. {ccxt-4.3.53.dist-info → ccxt-4.3.55.dist-info}/top_level.txt +0 -0
@@ -1,269 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- import argparse
4
- import json
5
- # import logging
6
- import os
7
- import sys
8
- from traceback import format_tb, format_exception
9
-
10
- import importlib # noqa: E402
11
- import re
12
-
13
- # ------------------------------------------------------------------------------
14
- # logging.basicConfig(level=logging.INFO)
15
- # ------------------------------------------------------------------------------
16
- DIR_NAME = os.path.dirname(os.path.abspath(__file__))
17
- root = os.path.dirname(os.path.dirname(DIR_NAME))
18
- sys.path.append(root)
19
-
20
- import ccxt.async_support as ccxt # noqa: E402
21
- import ccxt.pro as ccxtpro # noqa: E402
22
-
23
- # ------------------------------------------------------------------------------
24
3
  import asyncio
25
- # from typing import Optional
26
- # from typing import List
27
- from ccxt.base.errors import NotSupported
28
- from ccxt.base.errors import ProxyError
29
- from ccxt.base.errors import OperationFailed
30
- # from ccxt.base.errors import ExchangeError
31
- from ccxt.base.errors import ExchangeNotAvailable
32
- from ccxt.base.errors import OnMaintenance
33
- from ccxt.base.errors import AuthenticationError
34
-
35
- # ------------------------------------------------------------------------------
36
-
37
- class Argv(object):
38
- id_tests = False
39
- static_tests = False
40
- ws_tests = False
41
- request_tests = False
42
- response_tests = False
43
- token_bucket = False
44
- sandbox = False
45
- privateOnly = False
46
- private = False
47
- ws = False
48
- verbose = False
49
- nonce = None
50
- exchange = None
51
- symbol = None
52
- info = False
53
- pass
54
-
55
-
56
- argv = Argv()
57
- parser = argparse.ArgumentParser()
58
- parser.add_argument('--token_bucket', action='store_true', help='enable token bucket experimental test')
59
- parser.add_argument('--sandbox', action='store_true', help='enable sandbox mode')
60
- parser.add_argument('--privateOnly', action='store_true', help='run private tests only')
61
- parser.add_argument('--private', action='store_true', help='run private tests')
62
- parser.add_argument('--verbose', action='store_true', help='enable verbose output')
63
- parser.add_argument('--ws', action='store_true', help='websockets version')
64
- parser.add_argument('--info', action='store_true', help='enable info output')
65
- parser.add_argument('--static', action='store_true', help='run static tests')
66
- parser.add_argument('--useProxy', action='store_true', help='run static tests')
67
- parser.add_argument('--idTests', action='store_true', help='run brokerId tests')
68
- parser.add_argument('--responseTests', action='store_true', help='run response tests')
69
- parser.add_argument('--requestTests', action='store_true', help='run response tests')
70
- parser.add_argument('--nonce', type=int, help='integer')
71
- parser.add_argument('exchange', type=str, help='exchange id in lowercase', nargs='?')
72
- parser.add_argument('symbol', type=str, help='symbol in uppercase', nargs='?')
73
- parser.parse_args(namespace=argv)
74
-
75
- # ------------------------------------------------------------------------------
76
-
77
- path = os.path.dirname(ccxt.__file__)
78
- if 'site-packages' in os.path.dirname(ccxt.__file__):
79
- raise Exception("You are running test_async.py/test.py against a globally-installed version of the library! It was previously installed into your site-packages folder by pip or pip3. To ensure testing against the local folder uninstall it first with pip uninstall ccxt or pip3 uninstall ccxt")
80
-
81
- # ------------------------------------------------------------------------------
82
-
83
- Error = Exception
84
-
85
- # # print an error string
86
- # def dump_error(*args):
87
- # string = ' '.join([str(arg) for arg in args])
88
- # print(string)
89
- # sys.stderr.write(string + "\n")
90
- # sys.stderr.flush()
91
-
92
-
93
- def handle_all_unhandled_exceptions(type, value, traceback):
94
- dump((type), (value), '\n<UNHANDLED EXCEPTION>\n' + ('\n'.join(format_tb(traceback))))
95
- exit(1) # unrecoverable crash
96
-
97
-
98
- sys.excepthook = handle_all_unhandled_exceptions
99
- # ------------------------------------------------------------------------------
100
-
101
- # non-transpiled part, but shared names among langs
102
-
103
- is_synchronous = 'async' not in os.path.basename(__file__)
104
-
105
- rootDir = DIR_NAME + '/../../../'
106
- rootDirForSkips = DIR_NAME + '/../../../'
107
- envVars = os.environ
108
- LOG_CHARS_LENGTH = 10000
109
- ext = 'py'
110
- proxyTestFileName = 'proxies'
111
-
112
-
113
- def get_cli_arg_value(arg):
114
- arg_exists = getattr(argv, arg) if hasattr(argv, arg) else False
115
- with_hyphen = '--' + arg
116
- arg_exists_with_hyphen = getattr(argv, with_hyphen) if hasattr(argv, with_hyphen) else False
117
- without_hyphen = arg.replace('--', '')
118
- arg_exists_wo_hyphen = getattr(argv, without_hyphen) if hasattr(argv, without_hyphen) else False
119
- return arg_exists or arg_exists_with_hyphen or arg_exists_wo_hyphen
120
-
121
- isWsTests = get_cli_arg_value('--ws')
122
-
123
-
124
- class baseMainTestClass():
125
- lang = 'PY'
126
- is_synchronous = is_synchronous
127
- request_tests_failed = False
128
- response_tests_failed = False
129
- response_tests = False
130
- ws_tests = False
131
- load_keys = False
132
- skipped_settings_for_exchange = {}
133
- skipped_methods = {}
134
- check_public_tests = {}
135
- test_files = {}
136
- public_tests = {}
137
- new_line = '\n'
138
- root_dir = rootDir
139
- env_vars = envVars
140
- ext = ext
141
- root_dir_for_skips = rootDirForSkips
142
- only_specific_tests = []
143
- proxy_test_file_name = proxyTestFileName
144
- pass
145
4
 
146
5
 
147
- def dump(*args):
148
- print(' '.join([str(arg) for arg in args]))
6
+ from tests_helpers import get_cli_arg_value, dump, exit_script, get_test_files, init_exchange, set_exchange_prop, call_method, exception_message, io_file_exists, io_file_read, baseMainTestClass, AuthenticationError, NotSupported, OperationFailed, OnMaintenance, ExchangeNotAvailable, ProxyError, get_exchange_prop, close, json_parse, json_stringify, is_null_value, io_dir_read, convert_ascii, call_exchange_method_dynamically, set_fetch_response, call_exchange_method_dynamically_sync # noqa: F401
149
7
 
150
-
151
- def convert_ascii(str):
152
- return str # stub
153
-
154
- def json_parse(elem):
155
- return json.loads(elem)
156
-
157
-
158
- def json_stringify(elem):
159
- return json.dumps(elem)
160
-
161
-
162
- def convert_to_snake_case(content):
163
- res = re.sub(r'(?<!^)(?=[A-Z])', '_', content).lower()
164
- return res.replace('o_h_l_c_v', 'ohlcv')
165
-
166
-
167
- def get_test_name(methodName):
168
- # stub
169
- return methodName
170
-
171
-
172
- def io_file_exists(path):
173
- return os.path.isfile(path)
174
-
175
-
176
- def io_file_read(path, decode=True):
177
- fs = open(path, "r", encoding="utf-8")
178
- content = fs.read()
179
- if decode:
180
- return json.loads(content)
181
- else:
182
- return content
183
-
184
-
185
- def io_dir_read(path):
186
- return os.listdir(path)
187
-
188
-
189
- async def call_method(test_files, methodName, exchange, skippedProperties, args):
190
- methodNameToCall = 'test_' + convert_to_snake_case(methodName)
191
- return await getattr(test_files[methodName], methodNameToCall)(exchange, skippedProperties, *args)
192
-
193
-
194
- async def call_exchange_method_dynamically(exchange, methodName, args):
195
- return await getattr(exchange, methodName)(*args)
196
-
197
- async def call_overriden_method(exchange, methodName, args):
198
- # needed for php
199
- return await call_exchange_method_dynamically(exchange, methodName, args)
200
-
201
- def exception_message(exc):
202
- message = '[' + type(exc).__name__ + '] ' + "".join(format_exception(type(exc), exc, exc.__traceback__, limit=6))
203
- if len(message) > LOG_CHARS_LENGTH:
204
- # Accessing out of range element causes error
205
- message = message[0:LOG_CHARS_LENGTH]
206
- return message
207
-
208
-
209
- def exit_script(code=0):
210
- exit(code)
211
-
212
-
213
- def get_exchange_prop(exchange, prop, defaultValue=None):
214
- if hasattr(exchange, prop):
215
- res = getattr(exchange, prop)
216
- if res is not None and res != '':
217
- return res
218
- return defaultValue
219
-
220
-
221
- def set_exchange_prop(exchange, prop, value):
222
- setattr(exchange, prop, value)
223
- # set snake case too
224
- setattr(exchange, convert_to_snake_case(prop), value)
225
-
226
-
227
- def init_exchange(exchangeId, args, is_ws=False):
228
- if (is_ws):
229
- return getattr(ccxtpro, exchangeId)(args)
230
- return getattr(ccxt, exchangeId)(args)
231
-
232
-
233
- async def get_test_files(properties, ws=False):
234
- tests = {}
235
- finalPropList = properties + [proxyTestFileName]
236
- for i in range(0, len(finalPropList)):
237
- methodName = finalPropList[i]
238
- name_snake_case = convert_to_snake_case(methodName)
239
- prefix = 'async' if not is_synchronous else 'sync'
240
- dir_to_test = DIR_NAME + '/' + prefix + '/'
241
- module_string = 'ccxt.test.' + prefix + '.test_' + name_snake_case
242
- if (ws):
243
- prefix = 'pro'
244
- dir_to_test = DIR_NAME + '/../' + prefix + '/test/Exchange/'
245
- module_string = 'ccxt.pro.test.Exchange.test_' + name_snake_case
246
- filePathWithExt = dir_to_test + 'test_' + name_snake_case + '.py'
247
- if (io_file_exists (filePathWithExt)):
248
- imp = importlib.import_module(module_string)
249
- tests[methodName] = imp # getattr(imp, finalName)
250
- return tests
251
-
252
- async def close(exchange):
253
- if (not is_synchronous and hasattr(exchange, 'close')):
254
- await exchange.close()
255
-
256
- def is_null_value(value):
257
- return value is None
258
-
259
- def set_fetch_response(exchange: ccxt.Exchange, data):
260
- async def fetch(url, method='GET', headers=None, body=None):
261
- return data
262
- exchange.fetch = fetch
263
- return exchange
264
-
265
- # *********************************
266
- # ***** AUTO-TRANSPILER-START *****
267
8
  class testMainClass(baseMainTestClass):
268
9
  def parse_cli_args(self):
269
10
  self.response_tests = get_cli_arg_value('--responseTests')
@@ -452,7 +193,9 @@ class testMainClass(baseMainTestClass):
452
193
  args_stringified = '(' + exchange.json(args) + ')' # args.join() breaks when we provide a list of symbols or multidimensional array; "args.toString()" breaks bcz of "array to string conversion"
453
194
  dump(self.add_padding('[INFO] TESTING', 25), self.exchange_hint(exchange), method_name, args_stringified)
454
195
  await call_method(self.test_files, method_name, exchange, skipped_properties_for_method, args)
455
- # if it was passed successfully, add to the list of successfull tests
196
+ if self.info:
197
+ dump(self.add_padding('[INFO] TESTING DONE', 25), self.exchange_hint(exchange), method_name)
198
+ # add to the list of successed tests
456
199
  if is_public:
457
200
  self.checked_public_tests[method_name] = True
458
201
  return
@@ -507,7 +250,7 @@ class testMainClass(baseMainTestClass):
507
250
  # formatted message "[TEST_FAILURE] ..." and that output is then regex-matched by
508
251
  # run-tests.js, so the exceptions are still printed out to console from there.
509
252
  max_retries = 3
510
- args_stringified = exchange.json(args) # args.join() breaks when we provide a list of symbols | "args.toString()" breaks bcz of "array to string conversion"
253
+ args_stringified = exchange.json(args) # args.join() breaks when we provide a list of symbols or multidimensional array; "args.toString()" breaks bcz of "array to string conversion"
511
254
  for i in range(0, max_retries):
512
255
  try:
513
256
  await self.test_method(method_name, exchange, args, is_public)
@@ -836,12 +579,16 @@ class testMainClass(baseMainTestClass):
836
579
  for j in range(0, max_retries):
837
580
  try:
838
581
  await self.test_method(proxy_test_name, exchange, [], True)
839
- break # if successfull, then break
582
+ return # if successfull, then end the test
840
583
  except Exception as e:
841
584
  exception = e
585
+ await exchange.sleep(j * 1000)
842
586
  # if exception was set, then throw it
843
- if exception:
587
+ if exception is not None:
844
588
  error_message = '[TEST_FAILURE] Failed ' + proxy_test_name + ' : ' + exception_message(exception)
589
+ # temporary comment the below, because c# transpilation failure
590
+ # throw new ExchangeError (errorMessage.toString ());
591
+ dump('[TEST_WARNING]' + str(error_message))
845
592
 
846
593
  async def start_test(self, exchange, symbol):
847
594
  # we do not need to test aliases
@@ -1075,7 +822,10 @@ class testMainClass(baseMainTestClass):
1075
822
  output = None
1076
823
  request_url = None
1077
824
  try:
1078
- await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
825
+ if not self.is_synchronous:
826
+ await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
827
+ else:
828
+ call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
1079
829
  except Exception as e:
1080
830
  if not (isinstance(e, ProxyError)):
1081
831
  raise e
@@ -1093,8 +843,12 @@ class testMainClass(baseMainTestClass):
1093
843
  expected_result = exchange.safe_value(data, 'parsedResponse')
1094
844
  mocked_exchange = set_fetch_response(exchange, data['httpResponse'])
1095
845
  try:
1096
- unified_result = await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
1097
- self.assert_static_response_output(mocked_exchange, skip_keys, unified_result, expected_result)
846
+ if not self.is_synchronous:
847
+ unified_result = await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
848
+ self.assert_static_response_output(mocked_exchange, skip_keys, unified_result, expected_result)
849
+ else:
850
+ unified_result_sync = call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
851
+ self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
1098
852
  except Exception as e:
1099
853
  self.request_tests_failed = True
1100
854
  error_message = '[' + self.lang + '][STATIC_RESPONSE_TEST_FAILURE]' + '[' + self.exchange_hint(exchange) + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
@@ -1179,7 +933,8 @@ class testMainClass(baseMainTestClass):
1179
933
  # reset options
1180
934
  # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
1181
935
  exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
1182
- await close(exchange)
936
+ if not self.is_synchronous:
937
+ await close(exchange)
1183
938
  return True # in c# methods that will be used with promiseAll need to return something
1184
939
 
1185
940
  async def test_exchange_response_statically(self, exchange_name, exchange_data, test_name=None):
@@ -1228,7 +983,8 @@ class testMainClass(baseMainTestClass):
1228
983
  # reset options
1229
984
  # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
1230
985
  exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
1231
- await close(exchange)
986
+ if not self.is_synchronous:
987
+ await close(exchange)
1232
988
  return True # in c# methods that will be used with promiseAll need to return something
1233
989
 
1234
990
  def get_number_of_tests_from_exchange(self, exchange, exchange_data, test_name=None):
@@ -1273,7 +1029,8 @@ class testMainClass(baseMainTestClass):
1273
1029
  if self.request_tests_failed or self.response_tests_failed:
1274
1030
  exit_script(1)
1275
1031
  else:
1276
- success_message = '[' + self.lang + '][TEST_SUCCESS] ' + str(sum) + ' static ' + type + ' tests passed.'
1032
+ prefix = '[SYNC]' if (self.is_synchronous) else ''
1033
+ success_message = '[' + self.lang + ']' + prefix + '[TEST_SUCCESS] ' + str(sum) + ' static ' + type + ' tests passed.'
1277
1034
  dump('[INFO]' + success_message)
1278
1035
 
1279
1036
  async def run_static_response_tests(self, exchange_name=None, test=None):
@@ -1671,13 +1428,3 @@ class testMainClass(baseMainTestClass):
1671
1428
  assert broker_id == id, 'vertex - id: ' + str(id) + ' different from broker_id: ' + str(broker_id)
1672
1429
  await close(exchange)
1673
1430
  return True
1674
-
1675
- # ***** AUTO-TRANSPILER-END *****
1676
- # *******************************
1677
-
1678
-
1679
- if __name__ == '__main__':
1680
- argvSymbol = argv.symbol if argv.symbol and '/' in argv.symbol else None
1681
- # in python, we check it through "symbol" arg (as opposed to JS/PHP) because argvs were already built above
1682
- argvMethod = argv.symbol if argv.symbol and '()' in argv.symbol else None
1683
- asyncio.run(testMainClass().init(argv.exchange, argvSymbol, argvMethod))
@@ -0,0 +1,284 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import argparse
4
+ import json
5
+ # import logging
6
+ import os
7
+ import sys
8
+ from traceback import format_tb, format_exception
9
+
10
+ import importlib # noqa: E402
11
+ import re
12
+
13
+ # ------------------------------------------------------------------------------
14
+ # logging.basicConfig(level=logging.INFO)
15
+ # ------------------------------------------------------------------------------
16
+ DIR_NAME = os.path.dirname(os.path.abspath(__file__))
17
+ root = os.path.dirname(os.path.dirname(DIR_NAME))
18
+ sys.path.append(root)
19
+
20
+ import ccxt.async_support as ccxt # noqa: E402
21
+ import ccxt as ccxt_sync # noqa: E402
22
+ import ccxt.pro as ccxtpro # noqa: E402
23
+
24
+ # ------------------------------------------------------------------------------
25
+ # from typing import Optional
26
+ # from typing import List
27
+ from ccxt.base.errors import NotSupported # noqa: F401
28
+ from ccxt.base.errors import ProxyError # noqa: F401
29
+ from ccxt.base.errors import OperationFailed # noqa: F401
30
+ # from ccxt.base.errors import ExchangeError
31
+ from ccxt.base.errors import ExchangeNotAvailable # noqa: F401
32
+ from ccxt.base.errors import OnMaintenance # noqa: F401
33
+ from ccxt.base.errors import AuthenticationError # noqa: F401
34
+
35
+ # ------------------------------------------------------------------------------
36
+
37
+ class Argv(object):
38
+ id_tests = False
39
+ static_tests = False
40
+ ws_tests = False
41
+ request_tests = False
42
+ response_tests = False
43
+ token_bucket = False
44
+ sandbox = False
45
+ privateOnly = False
46
+ private = False
47
+ ws = False
48
+ verbose = False
49
+ nonce = None
50
+ exchange = None
51
+ symbol = None
52
+ info = False
53
+ sync = False
54
+ baseTests = False
55
+ exchangeTests = False
56
+ pass
57
+
58
+
59
+ argv = Argv()
60
+ parser = argparse.ArgumentParser()
61
+ parser.add_argument('--token_bucket', action='store_true', help='enable token bucket experimental test')
62
+ parser.add_argument('--sandbox', action='store_true', help='enable sandbox mode')
63
+ parser.add_argument('--privateOnly', action='store_true', help='run private tests only')
64
+ parser.add_argument('--private', action='store_true', help='run private tests')
65
+ parser.add_argument('--verbose', action='store_true', help='enable verbose output')
66
+ parser.add_argument('--ws', action='store_true', help='websockets version')
67
+ parser.add_argument('--info', action='store_true', help='enable info output')
68
+ parser.add_argument('--static', action='store_true', help='run static tests')
69
+ parser.add_argument('--useProxy', action='store_true', help='run static tests')
70
+ parser.add_argument('--idTests', action='store_true', help='run brokerId tests')
71
+ parser.add_argument('--responseTests', action='store_true', help='run response tests')
72
+ parser.add_argument('--requestTests', action='store_true', help='run response tests')
73
+ parser.add_argument('--sync', action='store_true', help='is sync')
74
+ parser.add_argument('--baseTests', action='store_true', help='is base tests')
75
+ parser.add_argument('--exchangeTests', action='store_true', help='is exchange tests')
76
+ parser.add_argument('--nonce', type=int, help='integer')
77
+ parser.add_argument('exchange', type=str, help='exchange id in lowercase', nargs='?')
78
+ parser.add_argument('symbol', type=str, help='symbol in uppercase', nargs='?')
79
+ parser.parse_args(namespace=argv)
80
+
81
+ # ------------------------------------------------------------------------------
82
+
83
+ path = os.path.dirname(ccxt.__file__)
84
+ if 'site-packages' in os.path.dirname(ccxt.__file__):
85
+ raise Exception("You are running tests_async.py/test.py against a globally-installed version of the library! It was previously installed into your site-packages folder by pip or pip3. To ensure testing against the local folder uninstall it first with pip uninstall ccxt or pip3 uninstall ccxt")
86
+
87
+ # ------------------------------------------------------------------------------
88
+
89
+ Error = Exception
90
+
91
+ # # print an error string
92
+ # def dump_error(*args):
93
+ # string = ' '.join([str(arg) for arg in args])
94
+ # print(string)
95
+ # sys.stderr.write(string + "\n")
96
+ # sys.stderr.flush()
97
+
98
+
99
+ def handle_all_unhandled_exceptions(type, value, traceback):
100
+ dump((type), (value), '\n<UNHANDLED EXCEPTION>\n' + ('\n'.join(format_tb(traceback))))
101
+ exit(1) # unrecoverable crash
102
+
103
+
104
+ sys.excepthook = handle_all_unhandled_exceptions
105
+ # ------------------------------------------------------------------------------
106
+
107
+ # non-transpiled part, but shared names among langs
108
+
109
+ is_synchronous = argv.sync # 'async' not in os.path.basename(__file__)
110
+
111
+ rootDir = DIR_NAME + '/../../../'
112
+ rootDirForSkips = DIR_NAME + '/../../../'
113
+ envVars = os.environ
114
+ LOG_CHARS_LENGTH = 10000
115
+ ext = 'py'
116
+ proxyTestFileName = 'proxies'
117
+
118
+
119
+ def get_cli_arg_value(arg):
120
+ arg_exists = getattr(argv, arg) if hasattr(argv, arg) else False
121
+ with_hyphen = '--' + arg
122
+ arg_exists_with_hyphen = getattr(argv, with_hyphen) if hasattr(argv, with_hyphen) else False
123
+ without_hyphen = arg.replace('--', '')
124
+ arg_exists_wo_hyphen = getattr(argv, without_hyphen) if hasattr(argv, without_hyphen) else False
125
+ return arg_exists or arg_exists_with_hyphen or arg_exists_wo_hyphen
126
+
127
+ isWsTests = get_cli_arg_value('--ws')
128
+
129
+
130
+ class baseMainTestClass():
131
+ lang = 'PY'
132
+ is_synchronous = is_synchronous
133
+ request_tests_failed = False
134
+ response_tests_failed = False
135
+ response_tests = False
136
+ ws_tests = False
137
+ load_keys = False
138
+ skipped_settings_for_exchange = {}
139
+ skipped_methods = {}
140
+ check_public_tests = {}
141
+ test_files = {}
142
+ public_tests = {}
143
+ new_line = '\n'
144
+ root_dir = rootDir
145
+ env_vars = envVars
146
+ ext = ext
147
+ root_dir_for_skips = rootDirForSkips
148
+ only_specific_tests = []
149
+ proxy_test_file_name = proxyTestFileName
150
+ pass
151
+
152
+
153
+ def dump(*args):
154
+ print(' '.join([str(arg) for arg in args]))
155
+
156
+
157
+ def convert_ascii(str):
158
+ return str # stub
159
+
160
+ def json_parse(elem):
161
+ return json.loads(elem)
162
+
163
+
164
+ def json_stringify(elem):
165
+ return json.dumps(elem)
166
+
167
+
168
+ def convert_to_snake_case(content):
169
+ res = re.sub(r'(?<!^)(?=[A-Z])', '_', content).lower()
170
+ return res.replace('o_h_l_c_v', 'ohlcv')
171
+
172
+
173
+ def get_test_name(methodName):
174
+ # stub
175
+ return methodName
176
+
177
+
178
+ def io_file_exists(path):
179
+ return os.path.isfile(path)
180
+
181
+
182
+ def io_file_read(path, decode=True):
183
+ fs = open(path, "r", encoding="utf-8")
184
+ content = fs.read()
185
+ if decode:
186
+ return json.loads(content)
187
+ else:
188
+ return content
189
+
190
+
191
+ def io_dir_read(path):
192
+ return os.listdir(path)
193
+
194
+
195
+ async def call_method(test_files, methodName, exchange, skippedProperties, args):
196
+ methodNameToCall = 'test_' + convert_to_snake_case(methodName)
197
+ return await getattr(test_files[methodName], methodNameToCall)(exchange, skippedProperties, *args)
198
+
199
+
200
+ async def call_exchange_method_dynamically(exchange, methodName, args):
201
+ return await getattr(exchange, methodName)(*args)
202
+
203
+ def call_exchange_method_dynamically_sync(exchange, methodName, args):
204
+ return getattr(exchange, methodName)(*args)
205
+
206
+ async def call_overriden_method(exchange, methodName, args):
207
+ # needed for php
208
+ return await call_exchange_method_dynamically(exchange, methodName, args)
209
+
210
+ def exception_message(exc):
211
+ message = '[' + type(exc).__name__ + '] ' + "".join(format_exception(type(exc), exc, exc.__traceback__, limit=6))
212
+ if len(message) > LOG_CHARS_LENGTH:
213
+ # Accessing out of range element causes error
214
+ message = message[0:LOG_CHARS_LENGTH]
215
+ return message
216
+
217
+
218
+ def exit_script(code=0):
219
+ exit(code)
220
+
221
+
222
+ def get_exchange_prop(exchange, prop, defaultValue=None):
223
+ if hasattr(exchange, prop):
224
+ res = getattr(exchange, prop)
225
+ if res is not None and res != '':
226
+ return res
227
+ return defaultValue
228
+
229
+
230
+ def set_exchange_prop(exchange, prop, value):
231
+ setattr(exchange, prop, value)
232
+ # set snake case too
233
+ setattr(exchange, convert_to_snake_case(prop), value)
234
+
235
+
236
+ def init_exchange(exchangeId, args, is_ws=False):
237
+ if is_synchronous:
238
+ return getattr(ccxt_sync, exchangeId)(args)
239
+ if (is_ws):
240
+ return getattr(ccxtpro, exchangeId)(args)
241
+ return getattr(ccxt, exchangeId)(args)
242
+
243
+
244
+ async def get_test_files(properties, ws=False):
245
+ tests = {}
246
+ finalPropList = properties + [proxyTestFileName]
247
+ for i in range(0, len(finalPropList)):
248
+ methodName = finalPropList[i]
249
+ name_snake_case = convert_to_snake_case(methodName)
250
+ prefix = 'async' if not is_synchronous else 'sync'
251
+ dir_to_test = DIR_NAME + '/exchange/' + prefix + '/'
252
+ module_string = 'ccxt.test.exchange.' + prefix + '.test_' + name_snake_case
253
+ if (ws):
254
+ prefix = 'pro'
255
+ dir_to_test = DIR_NAME + '/../' + prefix + '/test/Exchange/'
256
+ module_string = 'ccxt.pro.test.Exchange.test_' + name_snake_case
257
+ filePathWithExt = dir_to_test + 'test_' + name_snake_case + '.py'
258
+ if (io_file_exists (filePathWithExt)):
259
+ imp = importlib.import_module(module_string)
260
+ tests[methodName] = imp # getattr(imp, finalName)
261
+ return tests
262
+
263
+ async def close(exchange):
264
+ if (not is_synchronous and hasattr(exchange, 'close')):
265
+ await exchange.close()
266
+
267
+ def is_null_value(value):
268
+ return value is None
269
+
270
+ def set_fetch_response(exchange: ccxt.Exchange, data):
271
+ if (is_synchronous):
272
+ def fetch(url, method='GET', headers=None, body=None):
273
+ return data
274
+ exchange.fetch = fetch
275
+ return exchange
276
+ async def fetch(url, method='GET', headers=None, body=None):
277
+ return data
278
+ exchange.fetch = fetch
279
+ return exchange
280
+
281
+
282
+ argvSymbol = argv.symbol if argv.symbol and '/' in argv.symbol else None
283
+ # in python, we check it through "symbol" arg (as opposed to JS/PHP) because argvs were already built above
284
+ argvMethod = argv.symbol if argv.symbol and '()' in argv.symbol else None
@@ -0,0 +1,35 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from tests_helpers import get_cli_arg_value, is_synchronous, argv, argvSymbol, argvMethod
4
+
5
+ try:
6
+ import asyncio
7
+ except ImportError:
8
+ asyncio = None
9
+
10
+ from base.tests_init import base_tests_init # noqa: F401
11
+ from ccxt.pro.test.base.tests_init import test_base_init_ws # noqa: F401
12
+
13
+
14
+ # ########### args ###########
15
+ isWs = get_cli_arg_value('--ws')
16
+ isBaseTests = get_cli_arg_value('--baseTests')
17
+ run_all = get_cli_arg_value('--all')
18
+
19
+ # ###### base tests #######
20
+ if (isBaseTests):
21
+ if (isWs):
22
+ test_base_init_ws()
23
+ else:
24
+ base_tests_init()
25
+ print('base tests passed!')
26
+ if not run_all:
27
+ exit(0)
28
+
29
+ # ###### exchange tests #######
30
+ if (is_synchronous):
31
+ from tests_sync import testMainClass as testMainClassSync
32
+ testMainClassSync().init(argv.exchange, argvSymbol, argvMethod)
33
+ else:
34
+ from tests_async import testMainClass as testMainClassAsync
35
+ asyncio.run(testMainClassAsync().init(argv.exchange, argvSymbol, argvMethod))