rapydscript-ns 0.9.2 → 0.9.3
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.
- package/.agignore +1 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +19 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/PYTHON_GAPS.md +420 -0
- package/README.md +153 -29
- package/TODO.md +16 -118
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +70 -70
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +237 -8
- package/memory/project_string_impl.md +43 -0
- package/package.json +1 -1
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +248 -38
- package/release/baselib-plain-ugly.js +8 -8
- package/release/compiler.js +778 -277
- package/release/signatures.json +30 -30
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +4 -1
- package/src/baselib-builtins.pyj +56 -2
- package/src/baselib-containers.pyj +2 -0
- package/src/baselib-errors.pyj +7 -3
- package/src/baselib-internal.pyj +51 -6
- package/src/baselib-str.pyj +5 -3
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/asyncio.pyj +534 -0
- package/src/lib/base64.pyj +399 -0
- package/src/lib/bisect.pyj +73 -0
- package/src/lib/collections.pyj +1 -1
- package/src/lib/copy.pyj +120 -120
- package/src/lib/csv.pyj +494 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/gettext.pyj +569 -569
- package/src/lib/heapq.pyj +98 -0
- package/src/lib/html.pyj +382 -0
- package/src/lib/http/__init__.pyj +98 -0
- package/src/lib/http/client.pyj +304 -0
- package/src/lib/http/cookies.pyj +236 -0
- package/src/lib/itertools.pyj +580 -580
- package/src/lib/logging.pyj +672 -0
- package/src/lib/math.pyj +193 -193
- package/src/lib/operator.pyj +11 -11
- package/src/lib/pythonize.pyj +20 -20
- package/src/lib/random.pyj +118 -118
- package/src/lib/react.pyj +74 -74
- package/src/lib/string.pyj +357 -0
- package/src/lib/textwrap.pyj +329 -0
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/urllib/__init__.pyj +14 -0
- package/src/lib/urllib/error.pyj +66 -0
- package/src/lib/urllib/parse.pyj +475 -0
- package/src/lib/urllib/request.pyj +86 -0
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/analyzer.js +5 -2
- package/src/monaco-language-service/completions.js +26 -0
- package/src/monaco-language-service/diagnostics.js +202 -3
- package/src/monaco-language-service/dts.js +550 -550
- package/src/monaco-language-service/scope.js +1 -0
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/functions.pyj +152 -6
- package/src/output/jsx.pyj +164 -164
- package/src/output/loops.pyj +17 -2
- package/src/output/modules.pyj +1 -1
- package/src/output/operators.pyj +15 -0
- package/src/output/stream.pyj +0 -1
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +80 -17
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +1 -1
- package/src/unicode_aliases.pyj +576 -576
- package/src/utils.pyj +192 -192
- package/test/_import_one.pyj +37 -37
- package/test/_import_two/__init__.pyj +11 -11
- package/test/_import_two/level2/deep.pyj +4 -4
- package/test/_import_two/other.pyj +6 -6
- package/test/_import_two/sub.pyj +13 -13
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/async_generators.pyj +144 -0
- package/test/asyncio.pyj +307 -0
- package/test/base64.pyj +202 -0
- package/test/bisect.pyj +178 -0
- package/test/csv.pyj +405 -0
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/float_special.pyj +64 -0
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/heapq.pyj +174 -0
- package/test/html.pyj +212 -0
- package/test/http.pyj +259 -0
- package/test/imports.pyj +79 -72
- package/test/internationalization.pyj +73 -73
- package/test/lint.pyj +164 -164
- package/test/logging.pyj +356 -0
- package/test/long.pyj +130 -0
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/parenthesized_with.pyj +141 -0
- package/test/python_compat.pyj +3 -5
- package/test/python_modulo.pyj +76 -0
- package/test/python_modulo_off.pyj +21 -0
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/str.pyj +14 -0
- package/test/string.pyj +245 -0
- package/test/textwrap.pyj +172 -0
- package/test/type_display.pyj +48 -0
- package/test/type_enforcement.pyj +164 -0
- package/test/unit/index.js +14 -6
- package/test/unit/language-service-completions.js +119 -0
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service-scope.js +32 -0
- package/test/unit/language-service.js +127 -3
- package/test/unit/run-language-service.js +17 -3
- package/test/unit/web-repl.js +2094 -29
- package/test/urllib.pyj +193 -0
- package/tools/compile.js +1 -1
- package/tools/compiler.d.ts +367 -367
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +7 -7
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/msgfmt.js +187 -187
- package/tools/repl.js +223 -223
- package/tools/test.js +118 -118
- package/tools/utils.js +128 -128
- package/tools/web_repl.js +95 -95
- package/try +41 -41
- package/web-repl/env.js +196 -196
- package/web-repl/index.html +163 -163
- package/web-repl/main.js +1 -1
- package/web-repl/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +224 -224
- package/web-repl/sha1.js +25 -25
- package/test/omit_function_metadata.pyj +0 -20
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
###########################################################
|
|
2
|
+
# RapydScript Standard Library
|
|
3
|
+
# License: Apache License 2.0
|
|
4
|
+
# This library is covered under Apache license, so that
|
|
5
|
+
# you can distribute it with your RapydScript applications.
|
|
6
|
+
###########################################################
|
|
7
|
+
|
|
8
|
+
# Python-compatible logging module.
|
|
9
|
+
#
|
|
10
|
+
# Provides: getLogger, basicConfig, debug, info, warning, error, critical,
|
|
11
|
+
# exception, log, disable, addLevelName, getLevelName,
|
|
12
|
+
# captureWarnings, makeLogRecord, setLogRecordFactory,
|
|
13
|
+
# getLogRecordFactory, Logger, Handler, StreamHandler,
|
|
14
|
+
# FileHandler, NullHandler, Formatter, Filter, LogRecord,
|
|
15
|
+
# NOTSET, DEBUG, INFO, WARNING, WARN, ERROR, CRITICAL, FATAL,
|
|
16
|
+
# lastResort, root.
|
|
17
|
+
#
|
|
18
|
+
# Notes:
|
|
19
|
+
# - FileHandler raises NotImplementedError (no file I/O in JS environments).
|
|
20
|
+
# - StreamHandler writes to console by default (debug→console.debug,
|
|
21
|
+
# info→console.info, warning→console.warn, error/critical→console.error).
|
|
22
|
+
# Pass a stream with a .write(s) method to capture output.
|
|
23
|
+
# - Logger hierarchy (dotted names, propagation) is fully supported.
|
|
24
|
+
# - exception() logs at ERROR level without automatic exc_info capture.
|
|
25
|
+
# - basicConfig() may be called multiple times; pass force=True to reconfigure.
|
|
26
|
+
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
# Level constants
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
NOTSET = 0
|
|
32
|
+
DEBUG = 10
|
|
33
|
+
INFO = 20
|
|
34
|
+
WARNING = 30
|
|
35
|
+
WARN = WARNING
|
|
36
|
+
ERROR = 40
|
|
37
|
+
CRITICAL = 50
|
|
38
|
+
FATAL = CRITICAL
|
|
39
|
+
|
|
40
|
+
_level_to_name = {}
|
|
41
|
+
_level_to_name[NOTSET] = 'NOTSET'
|
|
42
|
+
_level_to_name[DEBUG] = 'DEBUG'
|
|
43
|
+
_level_to_name[INFO] = 'INFO'
|
|
44
|
+
_level_to_name[WARNING] = 'WARNING'
|
|
45
|
+
_level_to_name[ERROR] = 'ERROR'
|
|
46
|
+
_level_to_name[CRITICAL] = 'CRITICAL'
|
|
47
|
+
|
|
48
|
+
_name_to_level = {}
|
|
49
|
+
_name_to_level['NOTSET'] = NOTSET
|
|
50
|
+
_name_to_level['DEBUG'] = DEBUG
|
|
51
|
+
_name_to_level['INFO'] = INFO
|
|
52
|
+
_name_to_level['WARNING'] = WARNING
|
|
53
|
+
_name_to_level['WARN'] = WARNING
|
|
54
|
+
_name_to_level['ERROR'] = ERROR
|
|
55
|
+
_name_to_level['CRITICAL'] = CRITICAL
|
|
56
|
+
_name_to_level['FATAL'] = CRITICAL
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def getLevelName(level):
|
|
60
|
+
if jstype(level) is 'number':
|
|
61
|
+
return _level_to_name[level] if level in _level_to_name else ('Level ' + level)
|
|
62
|
+
if jstype(level) is 'string':
|
|
63
|
+
uname = level.toUpperCase()
|
|
64
|
+
return _name_to_level[uname] if uname in _name_to_level else None
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def addLevelName(level, name):
|
|
69
|
+
_level_to_name[level] = name
|
|
70
|
+
_name_to_level[name.toUpperCase()] = level
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _check_level(level):
|
|
74
|
+
if jstype(level) is 'string':
|
|
75
|
+
uname = level.toUpperCase()
|
|
76
|
+
if uname not in _name_to_level:
|
|
77
|
+
raise ValueError('Unknown level: ' + level)
|
|
78
|
+
return _name_to_level[uname]
|
|
79
|
+
if jstype(level) is 'number':
|
|
80
|
+
return level
|
|
81
|
+
raise TypeError('Level must be a string or integer')
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# ---------------------------------------------------------------------------
|
|
85
|
+
# Internal JS helpers
|
|
86
|
+
# ---------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
v"""
|
|
89
|
+
var _logging_start_time = Date.now();
|
|
90
|
+
|
|
91
|
+
// %-style message formatting: %s %d %i %f %e %g %x %o %%
|
|
92
|
+
function _logging_fmt_msg(tmpl, args) {
|
|
93
|
+
var i = 0, n = args ? args.length : 0;
|
|
94
|
+
return String(tmpl).replace(/%([sdifFeEgGxo%])/g, function(m, c) {
|
|
95
|
+
if (c === '%') return '%';
|
|
96
|
+
if (i >= n) return m;
|
|
97
|
+
var a = args[i++];
|
|
98
|
+
if (c === 'd' || c === 'i') return String(Math.trunc(Number(a)));
|
|
99
|
+
if (c === 'f' || c === 'F') return Number(a).toFixed(6);
|
|
100
|
+
if (c === 'e') return Number(a).toExponential();
|
|
101
|
+
if (c === 'E') return Number(a).toExponential().toUpperCase();
|
|
102
|
+
if (c === 'g' || c === 'G') return String(Number(a));
|
|
103
|
+
if (c === 'x') return Math.trunc(Number(a)).toString(16);
|
|
104
|
+
if (c === 'o') return Math.trunc(Number(a)).toString(8);
|
|
105
|
+
return String(a);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// %(attr)s / %(attr)d / %(attr)f style format for Formatter
|
|
110
|
+
function _logging_format_record(fmt, record) {
|
|
111
|
+
return fmt.replace(/%\((\w+)\)(?:[-+# 0]*\d*(?:\.\d+)?)([sdifFeEgGxo%])/g,
|
|
112
|
+
function(match, key, conv) {
|
|
113
|
+
if (conv === '%') return '%';
|
|
114
|
+
var val = record[key];
|
|
115
|
+
if (val === undefined || val === null) return '';
|
|
116
|
+
if (conv === 'd' || conv === 'i') return String(Math.trunc(Number(val)));
|
|
117
|
+
if (conv === 'f' || conv === 'F') {
|
|
118
|
+
var pm = match.match(/\.(\d+)[fF]/);
|
|
119
|
+
return Number(val).toFixed(pm ? parseInt(pm[1]) : 6);
|
|
120
|
+
}
|
|
121
|
+
if (conv === 'e') return Number(val).toExponential();
|
|
122
|
+
if (conv === 'E') return Number(val).toExponential().toUpperCase();
|
|
123
|
+
if (conv === 'g' || conv === 'G') return String(Number(val));
|
|
124
|
+
if (conv === 'x') return Math.trunc(Number(val)).toString(16);
|
|
125
|
+
if (conv === 'o') return Math.trunc(Number(val)).toString(8);
|
|
126
|
+
return String(val);
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Route to the right console method based on level number
|
|
132
|
+
function _logging_console_emit(levelno, msg) {
|
|
133
|
+
if (typeof console === 'undefined') return;
|
|
134
|
+
if (levelno >= 40) {
|
|
135
|
+
console.error(msg);
|
|
136
|
+
} else if (levelno >= 30) {
|
|
137
|
+
console.warn(msg);
|
|
138
|
+
} else if (levelno >= 20) {
|
|
139
|
+
console.info(msg);
|
|
140
|
+
} else {
|
|
141
|
+
console.debug(msg);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Format a timestamp from record.created (seconds since epoch)
|
|
146
|
+
function _logging_iso_time(created, datefmt) {
|
|
147
|
+
var d = new Date(created * 1000);
|
|
148
|
+
function pad2(n) { return n < 10 ? '0' + n : String(n); }
|
|
149
|
+
function pad3(n) { return n < 10 ? '00' + n : (n < 100 ? '0' + n : String(n)); }
|
|
150
|
+
if (datefmt) {
|
|
151
|
+
return datefmt
|
|
152
|
+
.replace('%Y', d.getFullYear())
|
|
153
|
+
.replace('%m', pad2(d.getMonth() + 1))
|
|
154
|
+
.replace('%d', pad2(d.getDate()))
|
|
155
|
+
.replace('%H', pad2(d.getHours()))
|
|
156
|
+
.replace('%M', pad2(d.getMinutes()))
|
|
157
|
+
.replace('%S', pad2(d.getSeconds()))
|
|
158
|
+
.replace('%f', pad3(d.getMilliseconds()) + '000');
|
|
159
|
+
}
|
|
160
|
+
return d.getFullYear() + '-' + pad2(d.getMonth() + 1) + '-' + pad2(d.getDate()) + ' ' +
|
|
161
|
+
pad2(d.getHours()) + ':' + pad2(d.getMinutes()) + ':' + pad2(d.getSeconds()) + ',' +
|
|
162
|
+
pad3(d.getMilliseconds());
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Safe kwargs accessor — handles plain JS objects and ρσ_dict (web-repl mode)
|
|
166
|
+
function _logging_kwget(kw, key, dflt) {
|
|
167
|
+
if (kw && kw.jsmap && typeof kw.jsmap.get === 'function') {
|
|
168
|
+
return kw.jsmap.has(key) ? kw.jsmap.get(key) : dflt;
|
|
169
|
+
}
|
|
170
|
+
return (kw && kw[key] !== undefined) ? kw[key] : dflt;
|
|
171
|
+
}
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ---------------------------------------------------------------------------
|
|
176
|
+
# LogRecord
|
|
177
|
+
# ---------------------------------------------------------------------------
|
|
178
|
+
|
|
179
|
+
class LogRecord:
|
|
180
|
+
def __init__(self, name, level, pathname, lineno, msg, args, exc_info, func=None):
|
|
181
|
+
self.name = name
|
|
182
|
+
self.levelno = level
|
|
183
|
+
self.levelname = _level_to_name[level] if level in _level_to_name else ('Level ' + level)
|
|
184
|
+
self.pathname = pathname or ''
|
|
185
|
+
self.filename = pathname or ''
|
|
186
|
+
self.module = ''
|
|
187
|
+
self.funcName = func or '(unknown)'
|
|
188
|
+
self.lineno = lineno or 0
|
|
189
|
+
self.msg = msg
|
|
190
|
+
self.args = args
|
|
191
|
+
self.exc_info = exc_info
|
|
192
|
+
self.exc_text = None
|
|
193
|
+
self.stack_info = None
|
|
194
|
+
now = v'Date.now()'
|
|
195
|
+
self.created = now / 1000.0
|
|
196
|
+
self.msecs = now % 1000
|
|
197
|
+
self.relativeCreated = now - v'_logging_start_time'
|
|
198
|
+
self.thread = 0
|
|
199
|
+
self.threadName = 'MainThread'
|
|
200
|
+
self.process = 0
|
|
201
|
+
self.processName = 'MainProcess'
|
|
202
|
+
self.message = ''
|
|
203
|
+
|
|
204
|
+
def getMessage(self):
|
|
205
|
+
msg = str(self.msg)
|
|
206
|
+
msg = v'_logging_fmt_msg(msg, this.args)'
|
|
207
|
+
return msg
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
_log_record_factory = LogRecord
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def makeLogRecord(d):
|
|
214
|
+
rv = LogRecord('', 0, '', 0, '', None, None)
|
|
215
|
+
v"""
|
|
216
|
+
var _src = (d && d.jsmap) ? (function(){
|
|
217
|
+
var o = {}; d.jsmap.forEach(function(v,k){ o[k]=v; }); return o;
|
|
218
|
+
})() : (d || {});
|
|
219
|
+
var _ks = Object.keys(_src);
|
|
220
|
+
for (var _i = 0; _i < _ks.length; _i++) { rv[_ks[_i]] = _src[_ks[_i]]; }
|
|
221
|
+
"""
|
|
222
|
+
return rv
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def setLogRecordFactory(factory):
|
|
226
|
+
global _log_record_factory
|
|
227
|
+
_log_record_factory = factory
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def getLogRecordFactory():
|
|
231
|
+
return _log_record_factory
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _make_log_record(name, level, msg, args, exc_info=None):
|
|
235
|
+
return _log_record_factory(name, level, '', 0, msg, args, exc_info)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# ---------------------------------------------------------------------------
|
|
239
|
+
# Filter / Filterer
|
|
240
|
+
# ---------------------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
class Filter:
|
|
243
|
+
def __init__(self, name=''):
|
|
244
|
+
self.name = name
|
|
245
|
+
self.nlen = name.length
|
|
246
|
+
|
|
247
|
+
def filter(self, record):
|
|
248
|
+
if self.nlen == 0:
|
|
249
|
+
return True
|
|
250
|
+
if record.name == self.name:
|
|
251
|
+
return True
|
|
252
|
+
return record.name.startsWith(self.name + '.')
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class Filterer:
|
|
256
|
+
def __init__(self):
|
|
257
|
+
self.filters = []
|
|
258
|
+
|
|
259
|
+
def addFilter(self, fltr):
|
|
260
|
+
if self.filters.indexOf(fltr) < 0:
|
|
261
|
+
self.filters.push(fltr)
|
|
262
|
+
|
|
263
|
+
def removeFilter(self, fltr):
|
|
264
|
+
idx = self.filters.indexOf(fltr)
|
|
265
|
+
if idx >= 0:
|
|
266
|
+
self.filters.splice(idx, 1)
|
|
267
|
+
|
|
268
|
+
def filter(self, record):
|
|
269
|
+
for f in self.filters:
|
|
270
|
+
result = True
|
|
271
|
+
if hasattr(f, 'filter'):
|
|
272
|
+
result = f.filter(record)
|
|
273
|
+
elif jstype(f) is 'function':
|
|
274
|
+
result = f(record)
|
|
275
|
+
if not result:
|
|
276
|
+
return False
|
|
277
|
+
return True
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
# ---------------------------------------------------------------------------
|
|
281
|
+
# Formatter
|
|
282
|
+
# ---------------------------------------------------------------------------
|
|
283
|
+
|
|
284
|
+
_DEFAULT_FMT = '%(levelname)s:%(name)s:%(message)s'
|
|
285
|
+
_DEFAULT_DATEFMT = None
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class Formatter:
|
|
289
|
+
def __init__(self, fmt=None, datefmt=None, style='%', validate=True):
|
|
290
|
+
self._fmt = fmt if fmt is not None else _DEFAULT_FMT
|
|
291
|
+
self.datefmt = datefmt
|
|
292
|
+
self._style = style
|
|
293
|
+
|
|
294
|
+
def format(self, record):
|
|
295
|
+
record.message = record.getMessage()
|
|
296
|
+
if self._fmt.indexOf('%(asctime)') >= 0:
|
|
297
|
+
record.asctime = self.formatTime(record, self.datefmt)
|
|
298
|
+
s = v'_logging_format_record(this._fmt, record)'
|
|
299
|
+
if record.exc_info and not record.exc_text:
|
|
300
|
+
record.exc_text = self.formatException(record.exc_info)
|
|
301
|
+
if record.exc_text:
|
|
302
|
+
if s and not s.endsWith('\n'):
|
|
303
|
+
s += '\n'
|
|
304
|
+
s += record.exc_text
|
|
305
|
+
if record.stack_info:
|
|
306
|
+
if s and not s.endsWith('\n'):
|
|
307
|
+
s += '\n'
|
|
308
|
+
s += self.formatStack(record.stack_info)
|
|
309
|
+
return s
|
|
310
|
+
|
|
311
|
+
def formatTime(self, record, datefmt=None):
|
|
312
|
+
return v'_logging_iso_time(record.created, datefmt)'
|
|
313
|
+
|
|
314
|
+
def formatException(self, exc_info):
|
|
315
|
+
if exc_info is None:
|
|
316
|
+
return ''
|
|
317
|
+
exc = exc_info[1] if Array.isArray(exc_info) and exc_info.length > 1 else exc_info
|
|
318
|
+
if exc is None:
|
|
319
|
+
return ''
|
|
320
|
+
if hasattr(exc, 'stack'):
|
|
321
|
+
return str(exc.stack)
|
|
322
|
+
return str(exc)
|
|
323
|
+
|
|
324
|
+
def formatStack(self, stack_info):
|
|
325
|
+
return str(stack_info)
|
|
326
|
+
|
|
327
|
+
def usesTime(self):
|
|
328
|
+
return self._fmt.indexOf('%(asctime)') >= 0
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
# ---------------------------------------------------------------------------
|
|
332
|
+
# Handler
|
|
333
|
+
# ---------------------------------------------------------------------------
|
|
334
|
+
|
|
335
|
+
class Handler(Filterer):
|
|
336
|
+
def __init__(self, level=NOTSET):
|
|
337
|
+
Filterer.__init__(self)
|
|
338
|
+
self.level = _check_level(level)
|
|
339
|
+
self._name = None
|
|
340
|
+
self.formatter = None
|
|
341
|
+
|
|
342
|
+
def setLevel(self, level):
|
|
343
|
+
self.level = _check_level(level)
|
|
344
|
+
|
|
345
|
+
def setFormatter(self, fmt):
|
|
346
|
+
self.formatter = fmt
|
|
347
|
+
|
|
348
|
+
def format(self, record):
|
|
349
|
+
if self.formatter is not None:
|
|
350
|
+
return self.formatter.format(record)
|
|
351
|
+
return _default_formatter.format(record)
|
|
352
|
+
|
|
353
|
+
def emit(self, record):
|
|
354
|
+
raise NotImplementedError('Handler subclasses must implement emit()')
|
|
355
|
+
|
|
356
|
+
def handle(self, record):
|
|
357
|
+
if not self.filter(record):
|
|
358
|
+
return False
|
|
359
|
+
self.emit(record)
|
|
360
|
+
return True
|
|
361
|
+
|
|
362
|
+
def handleError(self, record):
|
|
363
|
+
pass
|
|
364
|
+
|
|
365
|
+
def close(self):
|
|
366
|
+
pass
|
|
367
|
+
|
|
368
|
+
def createLock(self):
|
|
369
|
+
pass
|
|
370
|
+
|
|
371
|
+
def acquire(self):
|
|
372
|
+
pass
|
|
373
|
+
|
|
374
|
+
def release(self):
|
|
375
|
+
pass
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class StreamHandler(Handler):
|
|
379
|
+
def __init__(self, stream=None):
|
|
380
|
+
Handler.__init__(self)
|
|
381
|
+
self.stream = stream
|
|
382
|
+
|
|
383
|
+
def emit(self, record):
|
|
384
|
+
try:
|
|
385
|
+
msg = self.format(record)
|
|
386
|
+
if self.stream is not None:
|
|
387
|
+
self.stream.write(msg + '\n')
|
|
388
|
+
else:
|
|
389
|
+
_logging_console_emit(record.levelno, msg)
|
|
390
|
+
except Exception:
|
|
391
|
+
self.handleError(record)
|
|
392
|
+
|
|
393
|
+
def flush(self):
|
|
394
|
+
pass
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
class FileHandler(StreamHandler):
|
|
398
|
+
def __init__(self, filename, mode='a', encoding=None, delay=False):
|
|
399
|
+
raise NotImplementedError('FileHandler is not available in JS environments; use StreamHandler with a custom stream instead')
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
class NullHandler(Handler):
|
|
403
|
+
def emit(self, record):
|
|
404
|
+
pass
|
|
405
|
+
|
|
406
|
+
def handle(self, record):
|
|
407
|
+
pass
|
|
408
|
+
|
|
409
|
+
def createLock(self):
|
|
410
|
+
pass
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
# ---------------------------------------------------------------------------
|
|
414
|
+
# Default formatter / last-resort handler (initialised after class defs)
|
|
415
|
+
# ---------------------------------------------------------------------------
|
|
416
|
+
|
|
417
|
+
_default_formatter = Formatter()
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
class _LastResortHandler(StreamHandler):
|
|
421
|
+
def __init__(self):
|
|
422
|
+
StreamHandler.__init__(self)
|
|
423
|
+
self.level = WARNING
|
|
424
|
+
|
|
425
|
+
def emit(self, record):
|
|
426
|
+
msg = record.getMessage()
|
|
427
|
+
_logging_console_emit(record.levelno,
|
|
428
|
+
record.levelname + ':' + record.name + ':' + msg)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
lastResort = _LastResortHandler()
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
# ---------------------------------------------------------------------------
|
|
435
|
+
# Logger
|
|
436
|
+
# ---------------------------------------------------------------------------
|
|
437
|
+
|
|
438
|
+
_manager_loggers = {}
|
|
439
|
+
_disable_level = NOTSET
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
class Logger(Filterer):
|
|
443
|
+
def __init__(self, name, level=NOTSET):
|
|
444
|
+
Filterer.__init__(self)
|
|
445
|
+
self.name = name
|
|
446
|
+
self.level = _check_level(level)
|
|
447
|
+
self.parent = None
|
|
448
|
+
self.propagate = True
|
|
449
|
+
self.handlers = []
|
|
450
|
+
self.disabled = False
|
|
451
|
+
|
|
452
|
+
def setLevel(self, level):
|
|
453
|
+
self.level = _check_level(level)
|
|
454
|
+
|
|
455
|
+
def isEnabledFor(self, level):
|
|
456
|
+
if self.disabled:
|
|
457
|
+
return False
|
|
458
|
+
if level <= _disable_level:
|
|
459
|
+
return False
|
|
460
|
+
return level >= self.getEffectiveLevel()
|
|
461
|
+
|
|
462
|
+
def getEffectiveLevel(self):
|
|
463
|
+
logger = self
|
|
464
|
+
while logger is not None:
|
|
465
|
+
if logger.level != NOTSET:
|
|
466
|
+
return logger.level
|
|
467
|
+
logger = logger.parent
|
|
468
|
+
return WARNING
|
|
469
|
+
|
|
470
|
+
def addHandler(self, hdlr):
|
|
471
|
+
if self.handlers.indexOf(hdlr) < 0:
|
|
472
|
+
self.handlers.push(hdlr)
|
|
473
|
+
|
|
474
|
+
def removeHandler(self, hdlr):
|
|
475
|
+
idx = self.handlers.indexOf(hdlr)
|
|
476
|
+
if idx >= 0:
|
|
477
|
+
self.handlers.splice(idx, 1)
|
|
478
|
+
|
|
479
|
+
def hasHandlers(self):
|
|
480
|
+
c = self
|
|
481
|
+
while c is not None:
|
|
482
|
+
if c.handlers.length > 0:
|
|
483
|
+
return True
|
|
484
|
+
if not c.propagate:
|
|
485
|
+
break
|
|
486
|
+
c = c.parent
|
|
487
|
+
return False
|
|
488
|
+
|
|
489
|
+
def callHandlers(self, record):
|
|
490
|
+
c = self
|
|
491
|
+
found = 0
|
|
492
|
+
while c is not None:
|
|
493
|
+
for hdlr in c.handlers:
|
|
494
|
+
found += 1
|
|
495
|
+
if record.levelno >= hdlr.level:
|
|
496
|
+
hdlr.handle(record)
|
|
497
|
+
if not c.propagate:
|
|
498
|
+
c = None
|
|
499
|
+
else:
|
|
500
|
+
c = c.parent
|
|
501
|
+
if found == 0 and lastResort is not None:
|
|
502
|
+
if record.levelno >= lastResort.level:
|
|
503
|
+
lastResort.handle(record)
|
|
504
|
+
|
|
505
|
+
def handle(self, record):
|
|
506
|
+
if self.disabled:
|
|
507
|
+
return
|
|
508
|
+
if not self.filter(record):
|
|
509
|
+
return
|
|
510
|
+
self.callHandlers(record)
|
|
511
|
+
|
|
512
|
+
def _log(self, level, msg, args, exc_info=None, stack_info=None):
|
|
513
|
+
record = _make_log_record(self.name, level, msg, args, exc_info)
|
|
514
|
+
record.stack_info = stack_info
|
|
515
|
+
self.handle(record)
|
|
516
|
+
|
|
517
|
+
def debug(self, msg, *args):
|
|
518
|
+
if self.isEnabledFor(DEBUG):
|
|
519
|
+
self._log(DEBUG, msg, args)
|
|
520
|
+
|
|
521
|
+
def info(self, msg, *args):
|
|
522
|
+
if self.isEnabledFor(INFO):
|
|
523
|
+
self._log(INFO, msg, args)
|
|
524
|
+
|
|
525
|
+
def warning(self, msg, *args):
|
|
526
|
+
if self.isEnabledFor(WARNING):
|
|
527
|
+
self._log(WARNING, msg, args)
|
|
528
|
+
|
|
529
|
+
def warn(self, msg, *args):
|
|
530
|
+
if self.isEnabledFor(WARNING):
|
|
531
|
+
self._log(WARNING, msg, args)
|
|
532
|
+
|
|
533
|
+
def error(self, msg, *args):
|
|
534
|
+
if self.isEnabledFor(ERROR):
|
|
535
|
+
self._log(ERROR, msg, args)
|
|
536
|
+
|
|
537
|
+
def critical(self, msg, *args):
|
|
538
|
+
if self.isEnabledFor(CRITICAL):
|
|
539
|
+
self._log(CRITICAL, msg, args)
|
|
540
|
+
|
|
541
|
+
def fatal(self, msg, *args):
|
|
542
|
+
if self.isEnabledFor(CRITICAL):
|
|
543
|
+
self._log(CRITICAL, msg, args)
|
|
544
|
+
|
|
545
|
+
def exception(self, msg, *args):
|
|
546
|
+
self._log(ERROR, msg, args)
|
|
547
|
+
|
|
548
|
+
def log(self, level, msg, *args):
|
|
549
|
+
lvl = _check_level(level)
|
|
550
|
+
if self.isEnabledFor(lvl):
|
|
551
|
+
self._log(lvl, msg, args)
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
# ---------------------------------------------------------------------------
|
|
555
|
+
# Root logger and hierarchy
|
|
556
|
+
# ---------------------------------------------------------------------------
|
|
557
|
+
|
|
558
|
+
root = Logger('root', WARNING)
|
|
559
|
+
root.parent = None
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
def _fix_up_parents(alogger):
|
|
563
|
+
name = alogger.name
|
|
564
|
+
i = name.lastIndexOf('.')
|
|
565
|
+
rv = None
|
|
566
|
+
while i > 0 and rv is None:
|
|
567
|
+
substr = name.slice(0, i)
|
|
568
|
+
if substr in _manager_loggers:
|
|
569
|
+
rv = _manager_loggers[substr]
|
|
570
|
+
i = substr.lastIndexOf('.')
|
|
571
|
+
alogger.parent = rv if rv is not None else root
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def getLogger(name=None):
|
|
575
|
+
if name is None or name == '' or name == 'root':
|
|
576
|
+
return root
|
|
577
|
+
if name in _manager_loggers:
|
|
578
|
+
return _manager_loggers[name]
|
|
579
|
+
logger = Logger(name)
|
|
580
|
+
_manager_loggers[name] = logger
|
|
581
|
+
_fix_up_parents(logger)
|
|
582
|
+
return logger
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
def disable(level=CRITICAL):
|
|
586
|
+
global _disable_level
|
|
587
|
+
_disable_level = _check_level(level)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
# ---------------------------------------------------------------------------
|
|
591
|
+
# Module-level convenience functions
|
|
592
|
+
# ---------------------------------------------------------------------------
|
|
593
|
+
|
|
594
|
+
def debug(msg, *args):
|
|
595
|
+
if root.isEnabledFor(DEBUG):
|
|
596
|
+
root._log(DEBUG, msg, args)
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
def info(msg, *args):
|
|
600
|
+
if root.isEnabledFor(INFO):
|
|
601
|
+
root._log(INFO, msg, args)
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
def warning(msg, *args):
|
|
605
|
+
if root.isEnabledFor(WARNING):
|
|
606
|
+
root._log(WARNING, msg, args)
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
def warn(msg, *args):
|
|
610
|
+
if root.isEnabledFor(WARNING):
|
|
611
|
+
root._log(WARNING, msg, args)
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
def error(msg, *args):
|
|
615
|
+
if root.isEnabledFor(ERROR):
|
|
616
|
+
root._log(ERROR, msg, args)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def critical(msg, *args):
|
|
620
|
+
if root.isEnabledFor(CRITICAL):
|
|
621
|
+
root._log(CRITICAL, msg, args)
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
def exception(msg, *args):
|
|
625
|
+
root._log(ERROR, msg, args)
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
def log(level, msg, *args):
|
|
629
|
+
lvl = _check_level(level)
|
|
630
|
+
if root.isEnabledFor(lvl):
|
|
631
|
+
root._log(lvl, msg, args)
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
def captureWarnings(capture):
|
|
635
|
+
pass
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
# ---------------------------------------------------------------------------
|
|
639
|
+
# basicConfig
|
|
640
|
+
# ---------------------------------------------------------------------------
|
|
641
|
+
|
|
642
|
+
_basic_config_done = False
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def basicConfig(**kwargs):
|
|
646
|
+
global _basic_config_done
|
|
647
|
+
force = v'_logging_kwget(kwargs, "force", false)'
|
|
648
|
+
if _basic_config_done and not force:
|
|
649
|
+
return
|
|
650
|
+
if force:
|
|
651
|
+
root.handlers = []
|
|
652
|
+
|
|
653
|
+
level = v'_logging_kwget(kwargs, "level", null)'
|
|
654
|
+
fmt = v'_logging_kwget(kwargs, "format", null)'
|
|
655
|
+
datefmt = v'_logging_kwget(kwargs, "datefmt", null)'
|
|
656
|
+
stream = v'_logging_kwget(kwargs, "stream", null)'
|
|
657
|
+
handlers_arg = v'_logging_kwget(kwargs, "handlers", null)'
|
|
658
|
+
|
|
659
|
+
if handlers_arg is not None:
|
|
660
|
+
for h in handlers_arg:
|
|
661
|
+
if h.formatter is None and (fmt is not None or datefmt is not None):
|
|
662
|
+
h.setFormatter(Formatter(fmt, datefmt))
|
|
663
|
+
root.addHandler(h)
|
|
664
|
+
elif root.handlers.length == 0:
|
|
665
|
+
h = StreamHandler(stream)
|
|
666
|
+
h.setFormatter(Formatter(fmt, datefmt))
|
|
667
|
+
root.addHandler(h)
|
|
668
|
+
|
|
669
|
+
if level is not None:
|
|
670
|
+
root.setLevel(level)
|
|
671
|
+
|
|
672
|
+
_basic_config_done = True
|