Issues (15)

transpile.js (3 issues)

1
"use strict";
2
3
const fs   = require ('fs')
4
const log  = require ('ololog')
5
const ansi = require ('ansicolor').nice
0 ignored issues
show
The constant ansi seems to be never used. Consider removing it.
Loading history...
6
7
//-----------------------------------------------------------------------------
8
9
function regexAll (text, array) {
10
    for (let i in array) {
11
        let regex = array[i][0]
12
        regex = typeof regex == 'string' ? new RegExp (regex, 'g') : new RegExp (regex)
13
        text = text.replace (regex, array[i][1])
14
    }
15
    return text
16
}
17
18
//-----------------------------------------------------------------------------
19
20
let ccxtjs = fs.readFileSync ('ccxt.js', 'utf8')
21
let contents = ccxtjs.match (/\/\/====(?:[\s\S]+?)\/\/====/) [0]
22
let exchanges
23
let regex = /^var ([\S]+) =\s*(?:extend\s*\(([^\,]+)\,\s*)?{([\s\S]+?)^}/gm // exchange class
24
25
let python      = []
26
let pythonAsync = []
27
let php         = []
28
29
//-----------------------------------------------------------------------------
30
31
while (exchanges = regex.exec (contents)) {
32
33
    let id = exchanges[1]
34
35
    let parent = exchanges[2]
36
37
    let all = exchanges[3].trim ().split (/\,\s*\n\s*\n/)
38
    let params = '    ' + all[0]
39
    let methods = all.slice (1)
40
41
    let py = []
42
    let pyAsync = []
43
    let ph = []
44
45
    params = params.split ("\n")
46
47
    let pyParams = params
48
        .join ("\n        ")
49
        .replace (/ true/g, ' True')
50
        .replace (/ false/g, ' False')
51
        .replace (/ undefined/g, ' None')
52
        .replace (/ \/\//g, ' #')
53
        .replace (/\{ /g, '{')              // PEP8 E201
54
        .replace (/\[ /g, '[')              // PEP8 E201
55
        .replace (/([^\s]+) \]/g, '$1]')    // PEP8 E202
56
        .replace (/([^\s]+) \}\,/g, '$1},') // PEP8 E202
57
58
    function pyAddClass (py) {
0 ignored issues
show
The function pyAddClass is declared conditionally. This is not supported by all runtimes. Consider moving it to root scope or using var pyAddClass = function() { /* ... */ }; instead.
Loading history...
59
        py.push ('')
60
        py.push ('class ' + id + ' (' + (parent ? parent : 'Exchange') + '):')
61
        py.push ('')
62
        py.push ('    def __init__(self, config={}):')
63
        py.push ('        params = {')
64
        py.push ('        ' + pyParams + ((all.length > 1) ? ',' : ''))
65
        py.push ('        }')
66
        py.push ('        params.update(config)')
67
        py.push ('        super(' + id + ', self).__init__(params)')
68
    }
69
70
    pyAddClass (py);
71
    pyAddClass (pyAsync);
72
73
    let phParams = params
74
        .join ("\n        ")
75
        .replace (/ undefined/g, ' null')
76
        .replace (/': /g, "' => ")
77
        .replace (/ {/g, ' array (')
78
        .replace (/ \[/g, ' array (')
79
        .replace (/\}([\,\n]|$)/g, ')$1')
80
        .replace (/\]/g, ')')
81
82
    ph.push ('')
83
    ph.push ('class ' + id + ' extends ' + (parent ? parent : 'Exchange') + ' {')
84
    ph.push ('')
85
    ph.push ('    public function __construct ($options = array ()) {')
86
    ph.push ('        parent::__construct (array_merge(array (')
87
    ph.push ('        ' +  phParams + ((all.length > 1) ? ',' : ''))
88
    ph.push ('        ), $options));')
89
    ph.push ('    }')
90
91
    for (let i = 0; i < methods.length; i++) {
92
        let part = methods[i].trim ()
93
        let lines = part.split ("\n")
94
        let header = lines[0].trim ()
95
        let regex2 = /(async |)([\S]+)\s\(([^)]*)\)\s*{/g // exchange method
96
        let matches = regex2.exec (header)
97
        let keyword = matches[1]
98
        let method = matches[2]
99
        let args = matches[3].trim ()
100
101
        method = method.replace ('fetchBalance',       'fetch_balance')
102
                        // .replace ('fetchCategories', 'fetch_categories')
103
                        .replace ('loadMarkets',       'load_markets')
104
                        .replace ('fetchMarkets',      'fetch_markets')
105
                        .replace ('fetchOrderBook',    'fetch_order_book')
106
                        .replace ('fetchOHLCV',        'fetch_ohlcv')
107
                        .replace ('parseOHLCVs',       'parse_ohlcvs')
108
                        .replace ('parseOHLCV',        'parse_ohlcv')
109
                        .replace ('fetchTickers',      'fetch_tickers')
110
                        .replace ('fetchTicker',       'fetch_ticker')
111
                        .replace ('parseTicker',       'parse_ticker')
112
                        .replace ('parseTradesData',   'parse_trades_data')
113
                        .replace ('parseTrades',       'parse_trades')
114
                        .replace ('parseTrade',        'parse_trade')
115
                        .replace ('parseOrderBook',    'parse_order_book')
116
                        .replace ('parseBidAsks',      'parse_bidasks')
117
                        .replace ('parseBidAsk',       'parse_bidask')
118
                        .replace ('parseOrders',       'parse_orders')
119
                        .replace ('parseOrder',        'parse_order')
120
                        .replace ('fetchTrades',       'fetch_trades')
121
                        .replace ('fetchOrderStatus',  'fetch_order_status')
122
                        .replace ('fetchOrderTrades',  'fetch_order_trades')
123
                        .replace ('fetchOrders',       'fetch_orders')
124
                        .replace ('fetchOrder',        'fetch_order')
125
                        .replace ('fetchOpenOrders',   'fetch_open_orders')
126
                        .replace ('fetchMyTrades',     'fetch_my_trades')
127
                        .replace ('fetchAllMyTrades',  'fetch_all_my_trades')
128
                        .replace ('createOrder',       'create_order')
129
                        .replace ('cancelOrder',       'cancel_order')
130
                        .replace ('signIn',            'sign_in')
131
132
        args = args.length ? args.split (',').map (x => x.trim ()) : []
133
134
        let phArgs = args.join (', $').trim ()
135
        phArgs = phArgs.length ? ('$' + phArgs) : ''
136
137
        let pyArgs = args.map (x => x.replace (' = ', '=')).join (', ')
138
139
        let variables = args.map (arg => arg.split ('=').map (x => x.trim ()) [0])
140
141
        let body = lines.slice (1, -1).join ("\n")
142
143
        let regex3 = /[^a-zA-Z0-9_]let\s+(?:\[([^\]]+)\]|([a-zA-Z0-9_]+))/g // local variables
144
145
        let localVariablesMatches
146
        while (localVariablesMatches = regex3.exec (body)) {
147
            let m = localVariablesMatches[1] ? localVariablesMatches[1] : localVariablesMatches[2]
148
            m = m.trim ().split (', ')
149
            m.forEach (x => variables.push (x.trim ()))
150
            variables.push (localVariablesMatches[1])
151
        }
152
153
        let phVarsRegex = variables.map (x => [ "([^$$a-zA-Z0-9\\.\\>'_])" + x + "([^a-zA-Z0-9'_])", '$1$$' + x + '$2' ])
154
155
        let pyRegex = [
156
            [ /typeof\s+([^\s\[]+)(?:\s|\[(.+?)\])\s+\=\=\s+\'undefined\'/g, '$1[$2] is None' ],
157
            [ /undefined/g, 'None' ],
158
            [ /this\.stringToBinary\s*\((.*)\)/g, '$1' ],
159
            [ /this\.stringToBase64\s/g, 'base64.b64encode' ],
160
            [ /this\.base64ToBinary\s/g, 'base64.b64decode' ],
161
            [ /\.safeFloat\s/g, '.safe_float'],
162
            [ /\.binaryConcat\s/g, '.binary_concat'],
163
            [ /\.binaryToString\s/g, '.binary_to_string' ],
164
            [ /\.implodeParams\s/g, '.implode_params'],
165
            [ /\.extractParams\s/g, '.extract_params'],
166
            [ /\.parseOHLCVs/g, '.parse_ohlcvs'],
167
            [ /\.parseOHLCV/g, '.parse_ohlcv'],
168
            [ /\.parseTicker\s/g, '.parse_ticker'],
169
            [ /\.parseTradesData\s/g, '.parse_trades_data'],
170
            [ /\.parseTrades\s/g, '.parse_trades'],
171
            [ /\.parseTrade\s/g, '.parse_trade'],
172
            [ /\.parseOrderBook\s/g, '.parse_order_book'],
173
            [ /\.parseBidAsks\s/g, '.parse_bidasks'],
174
            [ /\.parseBidAsk\s/g, '.parse_bidask'],
175
            [ /\.parseOrders\s/g, '.parse_orders'],
176
            [ /\.parseOrder\s/g, '.parse_order'],
177
            [ /\.indexBy\s/g, '.index_by'],
178
            [ /\.sortBy\s/g, '.sort_by'],
179
            [ /\.marketIds\s/g, '.market_ids'],
180
            [ /\.marketId\s/g, '.market_id'],
181
            [ /\.fetchOrderStatus\s/g, '.fetch_order_status'],
182
            [ /\.fetchOpenOrders\s/g, '.fetch_open_orders'],
183
            [ /\.fetchOrders\s/g, '.fetch_orders'],
184
            [ /\.loadMarkets\s/g, '.load_markets'],
185
            [ /\.encodeURIComponent\s/g, '.encode_uri_component'],
186
            // [ /this\.urlencode\s/g, '_urlencode.urlencode ' ], // use self.urlencode instead
187
            [ /this\./g, 'self.' ],
188
            [ /([^a-zA-Z\'])this([^a-zA-Z])/g, '$1self$2' ],
189
            [ /([^a-zA-Z0-9_])let\s\[\s*([^\]]+)\s\]/g, '$1$2' ],
190
            [ /([^a-zA-Z0-9_])let\s/g, '$1' ],
191
            [ /Object\.keys\s*\((.*)\)\.length/g, '$1' ],
192
            [ /Object\.keys\s*\((.*)\)/g, 'list($1.keys())' ],
193
            [ /\[([^\]]+)\]\.join\s*\(([^\)]+)\)/g, "$2.join([$1])" ],
194
            [ /hash \(([^,]+)\, \'(sha[0-9])\'/g, "hash($1, '$2'" ],
195
            [ /hmac \(([^,]+)\, ([^,]+)\, \'(md5)\'/g, 'hmac($1, $2, hashlib.$3' ],
196
            [ /hmac \(([^,]+)\, ([^,]+)\, \'(sha[0-9]+)\'/g, 'hmac($1, $2, hashlib.$3' ],
197
            [ /throw new ([\S]+) \((.*)\)/g, 'raise $1($2)'],
198
            [ /throw ([\S]+)/g, 'raise $1'],
199
            [ /try {/g, 'try:'],
200
            [ /\}\s+catch \(([\S]+)\) {/g, 'except Exception as $1:'],
201
            [ /([\s\(])extend(\s)/g, '$1self.extend$2' ],
202
            [ /\} else if/g, 'elif' ],
203
            [ /if\s+\((.*)\)\s+\{/g, 'if $1:' ],
204
            [ /if\s+\((.*)\)\s*[\n]/g, "if $1:\n" ],
205
            [ /\}\s*else\s*\{/g, 'else:' ],
206
            [ /else\s*[\n]/g, "else:\n" ],
207
            [ /for\s+\(([a-zA-Z0-9_]+)\s*=\s*([^\;\s]+\s*)\;[^\<\>\=]+(?:\<=|\>=|<|>)\s*(.*)\.length\s*\;[^\)]+\)\s*{/g, 'for $1 in range($2, len($3)):'],
208
            [ /\s\|\|\s/g, ' or ' ],
209
            [ /\s\&\&\s/g, ' and ' ],
210
            [ /\!([^\=])/g, 'not $1'],
211
            [ /([^\s]+)\.length/g, 'len($1)' ],
212
            [ /\.push\s*\(([\s\S]+?)\);/g, '.append($1);' ],
213
            [ /^\s*}\s*[\n]/gm, '' ],
214
            [ /;/g, '' ],
215
            [ /\.toUpperCase\s*/g, '.upper' ],
216
            [ /\.toLowerCase\s*/g, '.lower' ],
217
            [ /JSON\.stringify\s*/g, 'json.dumps' ],
218
            // [ /\'%([^\']+)\'\.sprintf\s*\(([^\)]+)\)/g, "'{:$1}'.format($2)" ],
219
            [ /([^\s]+)\.toFixed\s*\(([^\)]+)\)/g, "'{:.$2f}'.format($1)" ],
220
            [ /parseFloat\s*/g, 'float'],
221
            [ /parseInt\s*/g, 'int'],
222
            [ /self\[([^\]+]+)\]/g, 'getattr(self, $1)' ],
223
            [ /([^\s]+)\.slice \(([^\,\)]+)\,\s?([^\)]+)\)/g, '$1[$2:$3]' ],
224
            [ /([^\s]+)\.slice \(([^\)\:]+)\)/g, '$1[$2:]' ],
225
            [ /Math\.floor\s*\(([^\)]+)\)/g, 'int(math.floor($1))' ],
226
            [ /Math\.abs\s*\(([^\)]+)\)/g, 'abs($1)' ],
227
            [ /Math\.round\s*\(([^\)]+)\)/g, 'int(round($1))' ],
228
            [ /(\([^\)]+\)|[^\s]+)\s*\?\s*(\([^\)]+\)|[^\s]+)\s*\:\s*(\([^\)]+\)|[^\s]+)/g, '$2 if $1 else $3'],
229
            [/ \/\//g, ' #' ],
230
            [ /\.indexOf/g, '.find'],
231
            [ /\strue/g, ' True'],
232
            [ /\sfalse/g, ' False'],
233
            [ /\(([^\s]+)\sin\s([^\)]+)\)/g, '($1 in list($2.keys()))' ],
234
            [ /([^\s]+\s*\(\))\.toString\s+\(\)/g, 'str($1)' ],
235
            [ /([^\s]+)\.toString \(\)/g, 'str($1)' ],
236
            [ /([^\s]+)\.join\s*\(\s*([^\)\[\]]+?)\s*\)/g, '$2.join($1)' ],
237
            [ /Math\.(max|min)\s/g, '$1' ],
238
            [ /console\.log\s/g, 'print'],
239
            [ /process\.exit\s+/g, 'sys.exit'],
240
            [ /([^+=\s]+) \(/g, '$1(' ], // PEP8 E225 remove whitespaces before left ( round bracket
241
            [ /\[ /g, '[' ],             // PEP8 E201 remove whitespaces after left [ square bracket
242
            [ /\{ /g, '{' ],             // PEP8 E201 remove whitespaces after left { bracket
243
            [ /([^\s]+) \]/g, '$1]' ],   // PEP8 E202 remove whitespaces before right ] square bracket
244
            [ /([^\s]+) \}/g, '$1}' ],   // PEP8 E202 remove whitespaces before right } bracket
245
        ]
246
247
        let phRegex = [
248
            [ /typeof\s+([^\s\[]+)(?:\s|\[(.+?)\])\s+\=\=\s+\'undefined\'/g, '$1[$2] == null' ],
249
            [ /undefined/g, 'null' ],
250
            [ /this\.extend/g, 'array_merge' ],
251
            [ /this\.stringToBinary\s*\((.*)\)/g, '$1' ],
252
            [ /this\.stringToBase64/g, 'base64_encode' ],
253
            [ /this\.base64ToBinary/g, 'base64_decode' ],
254
            [ /\.safeFloat/g, '.safe_float'],
255
            [ /\.parseOHLCVs/g, '.parse_ohlcvs'],
256
            [ /\.parseOHLCV/g, '.parse_ohlcv'],
257
            [ /\.parseTicker/g, '.parse_ticker'],
258
            [ /\.parseTradesData/g, '.parse_trades_data'],
259
            [ /\.parseTrades/g, '.parse_trades'],
260
            [ /\.parseTrade/g, '.parse_trade'],
261
            [ /\.parseOrderBook/g, '.parse_order_book'],
262
            [ /\.parseBidAsks/g, '.parse_bidasks'],
263
            [ /\.parseBidAsk/g, '.parse_bidask'],
264
            [ /\.binaryConcat/g, '.binary_concat'],
265
            [ /\.binaryToString/g, '.binary_to_string' ],
266
            [ /\.implodeParams/g, '.implode_params'],
267
            [ /\.extractParams/g, '.extract_params'],
268
            [ /\.indexBy/g, '.index_by'],
269
            [ /\.sortBy/g, '.sort_by'],
270
            [ /\.marketIds/g, '.market_ids'],
271
            [ /\.marketId/g, '.market_id'],
272
            [ /\.fetchOrderStatus/g, '.fetch_order_status'],
273
            [ /\.fetchOpenOrders/g, '.fetch_open_orders'],
274
            [ /\.fetchOrders/g, '.fetch_orders'],
275
            [ /\.parseOrders/g, '.parse_orders'],
276
            [ /\.parseOrder/g, '.parse_order'],
277
            [ /\.loadMarkets/g, '.load_markets'],
278
            [ /\.encodeURIComponent/g, '.encode_uri_component'],
279
            [ /this\./g, '$this->' ],
280
            [ / this;/g, ' $this;' ],
281
            [ /([^'])this_\./g, '$1$this_->' ],
282
            [ /\{\}/g, 'array ()' ],
283
            [ /\[\]/g, 'array ()' ],
284
            [ /\{([^\n\}]+)\}/g, 'array ($1)' ],
285
            [ /([^a-zA-Z0-9_])let\s\[\s*([^\]]+)\s\]/g, '$1list ($2)' ],
286
            [ /([^a-zA-Z0-9_])let\s/g, '$1' ],
287
            [ /Object\.keys\s*\((.*)\)\.length/g, '$1' ],
288
            [ /Object\.keys\s*\((.*)\)/g, 'array_keys ($1)' ],
289
            [ /([^\s]+\s*\(\))\.toString \(\)/g, '(string) $1' ],
290
            [ /([^\s]+)\.toString \(\)/g, '(string) $1' ],
291
            [ /throw new Error \((.*)\)/g, 'throw new \\Exception ($1)'],
292
            [ /throw new ([\S]+) \((.*)\)/g, 'throw new $1 ($2)'],
293
            [ /for\s+\(([a-zA-Z0-9_]+)\s*=\s*([^\;\s]+\s*)\;[^\<\>\=]+(\<=|\>=|<|>)\s*(.*)\.length\s*\;([^\)]+)\)\s*{/g, 'for ($1 = $2; $1 $3 count ($4);$5) {'],
294
            [ /([^\s]+)\.length\;/g, 'count ($1);' ],
295
            [ /([^\s]+)\.length/g, 'strlen ($1)' ],
296
            [ /\.push\s*\(([\s\S]+?)\)\;/g, '[] = $1;' ],
297
            [ /(\s)await(\s)/g, '$1' ],
298
            [ /([\S])\: /g, '$1 => ' ],
299
            [ /\{([^\;\{]+?)\}([^\s])/g, 'array ($1)$2' ],
300
            [ /\[\s*([^\]]+?)\s*\]\.join\s*\(\s*([^\)]+?)\s*\)/g, "implode ($2, array ($1))" ],
301
            [ /\[\s([^\]]+?)\s\]/g, 'array ($1)' ],
302
            [ /JSON\.stringify/g, 'json_encode' ],
303
            // [ /\'([^\']+)\'\.sprintf\s*\(([^\)]+)\)/g, "sprintf ('$1', $2)" ],
304
            [ /([^\s]+)\.toFixed\s*\(([^\)]+)\)/g, "sprintf ('%$2f', $1)" ],
305
            [ /parseFloat\s/g, 'floatval '],
306
            [ /parseInt\s/g, 'intval '],
307
            [ / \+ /g, ' . ' ],
308
            [ / \+\= /g, ' .= ' ],
309
            [ /([^\s]+(?:\s*\(.+\))?)\.toUpperCase\s*\(\)/g, 'strtoupper ($1)' ],
310
            [ /([^\s]+(?:\s*\(.+\))?)\.toLowerCase\s*\(\)/g, 'strtolower ($1)' ],
311
            [ /([^\s]+(?:\s*\(.+\))?)\.replace\s*\(([^\)]+)\)/g, 'str_replace ($2, $1)' ],
312
            [ /this\[([^\]+]+)\]/g, '$$this->$$$1' ],
313
            [ /([^\s]+).slice \(([^\)\:]+)\)/g, 'mb_substr ($1, $2)' ],
314
            [ /([^\s]+).slice \(([^\,\)]+)\,\s*([^\)]+)\)/g, 'mb_substr ($1, $2, $3)' ],
315
            [ /([^\s]+).split \(([^\,]+?)\)/g, 'explode ($2, $1)' ],
316
            [ /Math\.floor\s*\(([^\)]+)\)/g, '(int) floor ($1)' ],
317
            [ /Math\.abs\s*\(([^\)]+)\)/g, 'abs ($1)' ],
318
            [ /Math\.round\s*\(([^\)]+)\)/g, '(int) round ($1)' ],
319
            [ /([^\(\s]+)\s+%\s+([^\s\)]+)/g, 'fmod ($1, $2)' ],
320
            [ /\(([^\s]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0\)/g, '(mb_strpos ($1, $2) !== false)' ],
321
            [ /([^\s]+)\.indexOf\s*\(([^\)]+)\)\s*\>\=\s*0/g, 'mb_strpos ($1, $2) !== false' ],
322
            [ /([^\s]+)\.indexOf\s*\(([^\)]+)\)/g, 'mb_strpos ($1, $2)' ],
323
            [ /\(([^\s]+)\sin\s([^\)]+)\)/g, '(array_key_exists ($1, $2))' ],
324
            [ /([^\s]+)\.join\s*\(\s*([^\)]+?)\s*\)/g, 'implode ($2, $1)' ],
325
            [ /Math\.(max|min)/g, '$1' ],
326
            [ /console\.log/g, 'var_dump'],
327
            [ /process\.exit/g, 'exit'],
328
        ]
329
330
        let pyRegexSync = pyRegex.concat ([
331
            [ /(\s)await(\s)/g, '$1' ]
332
        ])
333
334
        let pyBody      = regexAll (body, pyRegexSync)
335
        let pyBodyAsync = regexAll (body, pyRegex)
336
337
        // special case for Python OrderedDicts
338
339
        let orderedRegex = /\.ordered\s+\(\{([^\}]+)\}\)/g
340
        let orderedMatches = undefined
0 ignored issues
show
Unused Code Comprehensibility introduced by
The assignment of undefined is not necessary as orderedMatches is implicitly marked as undefined by the declaration.
Loading history...
341
        while (orderedMatches = orderedRegex.exec (pyBody)) {
342
            let replaced = orderedMatches[1].replace (/^(\s+)([^\:]+)\:\s*([^\,]+)\,$/gm, '$1($2, $3),')
343
            pyBody = pyBody.replace (orderedRegex, '\.ordered ([' + replaced + '])')
344
        }
345
346
        let pyString = 'def ' + method + '(self' + (pyArgs.length ? ', ' + pyArgs.replace (/undefined/g, 'None').replace (/false/g, 'False').replace (/true/g, 'True') : '') + '):'
347
348
        py.push ('');
349
        py.push ('    ' + pyString);
350
        py.push (pyBody);
351
352
        pyAsync.push ('');
353
        pyAsync.push ('    ' + keyword + pyString);
354
        pyAsync.push (pyBodyAsync);
355
356
        let phBody = regexAll (body, phRegex.concat (phVarsRegex))
357
358
        ph.push ('');
359
        ph.push ('    public function ' + method + ' (' + phArgs.replace (/undefined/g, 'null').replace ('{}', 'array ()') + ') {');
360
        ph.push (phBody);
361
        ph.push ('    }')
362
    }
363
364
    py.push ('')
365
    pyAsync.push ('')
366
367
    python.push (py.join ("\n"))
368
    pythonAsync.push (pyAsync.join ("\n"))
369
370
    ph.push ('}')
371
    ph.push ('')
372
373
    php.push (ph.join ("\n"))
374
}
375
376
//-----------------------------------------------------------------------------
377
378
function transpile (oldName, newName, content, comment = '//') {
379
    log.bright.cyan ('Transpiling ' + oldName.yellow + ' → ' + newName.yellow)
380
    let fileContents = fs.readFileSync (oldName, 'utf8')
381
    fileContents = fileContents.split ("\n" + comment + "====") [0]
382
    fileContents +=
383
        "\n" + comment + "==============================================================================\n" +
384
        content.join ("\n" + comment + "------------------------------------------------------------------------------\n")
385
    fs.truncateSync (newName)
386
    fs.writeFileSync (newName, fileContents)
387
}
388
389
//-----------------------------------------------------------------------------
390
391
function copyFile (oldName, newName) {
392
    let contents = fs.readFileSync (oldName, 'utf8')
393
    fs.truncateSync (newName)
394
    fs.writeFileSync (newName, contents)
395
}
396
397
//-----------------------------------------------------------------------------
398
399
transpile ('./ccxt/exchanges.py',       './ccxt/exchanges.py',       python,      '#')
400
transpile ('./ccxt/async/exchanges.py', './ccxt/async/exchanges.py', pythonAsync, '#')
401
transpile ('./ccxt.php',                './build/ccxt.php',          php,         '//')
402
403
//-----------------------------------------------------------------------------
404
405
log.bright.green ('Transpiled successfully.')
406