# -*- coding: utf-8 -*- import argparse import json # import logging import os import sys from traceback import format_tb, format_exception import importlib # noqa: E402 import re # ------------------------------------------------------------------------------ # logging.basicConfig(level=logging.INFO) # ------------------------------------------------------------------------------ DIR_NAME = os.path.dirname(os.path.abspath(__file__)) root = os.path.dirname(os.path.dirname(DIR_NAME)) sys.path.append(root) import ccxt.async_support as ccxt # noqa: E402 import ccxt as ccxt_sync # noqa: E402 import ccxt.pro as ccxtpro # noqa: E402 # ------------------------------------------------------------------------------ # from typing import Optional # from typing import List from ccxt.base.errors import NotSupported # noqa: F401 from ccxt.base.errors import InvalidProxySettings # noqa: F401 from ccxt.base.errors import OperationFailed # noqa: F401 # from ccxt.base.errors import ExchangeError from ccxt.base.errors import ExchangeNotAvailable # noqa: F401 from ccxt.base.errors import OnMaintenance # noqa: F401 from ccxt.base.errors import AuthenticationError # noqa: F401 # ------------------------------------------------------------------------------ class Argv(object): id_tests = False static_tests = False ws_tests = False request_tests = False response_tests = False sandbox = False privateOnly = False private = False ws = False verbose = False nonce = None exchange = None symbol = None info = False sync = False baseTests = False exchangeTests = False pass argv = Argv() parser = argparse.ArgumentParser() parser.add_argument('--sandbox', action='store_true', help='enable sandbox mode') parser.add_argument('--privateOnly', action='store_true', help='run private tests only') parser.add_argument('--private', action='store_true', help='run private tests') parser.add_argument('--verbose', action='store_true', help='enable verbose output') parser.add_argument('--ws', action='store_true', help='websockets version') parser.add_argument('--info', action='store_true', help='enable info output') parser.add_argument('--static', action='store_true', help='run static tests') parser.add_argument('--useProxy', action='store_true', help='run static tests') parser.add_argument('--idTests', action='store_true', help='run brokerId tests') parser.add_argument('--responseTests', action='store_true', help='run response tests') parser.add_argument('--response', action='store_true', help='run response tests') parser.add_argument('--requestTests', action='store_true', help='run request tests') parser.add_argument('--request', action='store_true', help='run request tests') parser.add_argument('--sync', action='store_true', help='is sync') parser.add_argument('--baseTests', action='store_true', help='is base tests') parser.add_argument('--exchangeTests', action='store_true', help='is exchange tests') parser.add_argument('exchange', type=str, help='exchange id in lowercase', nargs='?') parser.add_argument('symbol', type=str, help='symbol in uppercase', nargs='?') parser.parse_args(namespace=argv) # ------------------------------------------------------------------------------ path = os.path.dirname(ccxt.__file__) if 'site-packages' in os.path.dirname(ccxt.__file__): 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") # ------------------------------------------------------------------------------ Error = Exception # # print an error string # def dump_error(*args): # string = ' '.join([str(arg) for arg in args]) # print(string) # sys.stderr.write(string + "\n") # sys.stderr.flush() def handle_all_unhandled_exceptions(type, value, traceback): dump('[TEST_FAILURE]', (type), (value), '\n\n' + ('\n'.join(format_tb(traceback)))) exit(1) # unrecoverable crash sys.excepthook = handle_all_unhandled_exceptions # ------------------------------------------------------------------------------ # non-transpiled part, but shared names among langs EXT = 'py' LANG = 'PY' IS_SYNCHRONOUS = argv.sync # 'async' not in os.path.basename(__file__) PROXY_TEST_FILE_NAME = 'proxies' ROOT_DIR = DIR_NAME + '/../../../' ENV_VARS = os.environ NEW_LINE = '\n' LOG_CHARS_LENGTH = 10000 def get_cli_arg_value(arg): arg_exists = getattr(argv, arg) if hasattr(argv, arg) else False with_hyphen = '--' + arg arg_exists_with_hyphen = getattr(argv, with_hyphen) if hasattr(argv, with_hyphen) else False without_hyphen = arg.replace('--', '') arg_exists_wo_hyphen = getattr(argv, without_hyphen) if hasattr(argv, without_hyphen) else False return arg_exists or arg_exists_with_hyphen or arg_exists_wo_hyphen isWsTests = get_cli_arg_value('--ws') def dump(*args): print(' '.join([str(arg) for arg in args])) def convert_ascii(str): return str # stub def json_parse(elem): return json.loads(elem) def json_stringify(elem): return json.dumps(elem) def convert_to_snake_case(content): res = re.sub(r'(? LOG_CHARS_LENGTH: # Accessing out of range element causes error message = message[0:LOG_CHARS_LENGTH] return message # stub for c# def get_root_exception(exc): return exc def exit_script(code=0): exit(code) def get_exchange_prop(exchange, prop, defaultValue=None): if hasattr(exchange, prop): res = getattr(exchange, prop) if res is not None and res != '': return res return defaultValue def set_exchange_prop(exchange, prop, value): setattr(exchange, prop, value) # set snake case too setattr(exchange, convert_to_snake_case(prop), value) def init_exchange(exchangeId, args, is_ws=False): if IS_SYNCHRONOUS: return getattr(ccxt_sync, exchangeId)(args) if (is_ws): return getattr(ccxtpro, exchangeId)(args) return getattr(ccxt, exchangeId)(args) def get_test_files_sync(properties, ws=False): tests = {} finalPropList = properties + [PROXY_TEST_FILE_NAME, 'features'] for i in range(0, len(finalPropList)): methodName = finalPropList[i] name_snake_case = convert_to_snake_case(methodName) prefix = 'async' if not IS_SYNCHRONOUS else 'sync' dir_to_test = DIR_NAME + '/exchange/' + prefix + '/' module_string = 'ccxt.test.exchange.' + prefix + '.test_' + name_snake_case if (ws): prefix = 'pro' dir_to_test = DIR_NAME + '/../' + prefix + '/test/Exchange/' module_string = 'ccxt.pro.test.Exchange.test_' + name_snake_case filePathWithExt = dir_to_test + 'test_' + name_snake_case + '.py' if (io_file_exists (filePathWithExt)): imp = importlib.import_module(module_string) tests[methodName] = imp # getattr(imp, finalName) return tests async def get_test_files(properties, ws=False): return get_test_files_sync(properties, ws) async def close(exchange): if (not IS_SYNCHRONOUS and hasattr(exchange, 'close')): await exchange.close() def is_null_value(value): return value is None def set_fetch_response(exchange: ccxt.Exchange, data): if (IS_SYNCHRONOUS): def fetch(url, method='GET', headers=None, body=None): return data exchange.fetch = fetch return exchange async def fetch(url, method='GET', headers=None, body=None): return data exchange.fetch = fetch return exchange def get_lang(): return LANG def get_ext(): return EXT def get_root_dir(): return ROOT_DIR def get_env_vars(): return ENV_VARS def is_sync(): return IS_SYNCHRONOUS argvExchange = argv.exchange argvSymbol = argv.symbol if argv.symbol and '/' in argv.symbol else None # in python, we check it through "symbol" arg (as opposed to JS/PHP) because argvs were already built above argvMethod = argv.symbol if argv.symbol and '()' in argv.symbol else None