pyscript-programming-language 1.12.0__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.
- pyscript/__init__.py +49 -0
- pyscript/__init__.pyi +96 -0
- pyscript/__main__.py +303 -0
- pyscript/core/__init__.py +61 -0
- pyscript/core/analyzer.py +531 -0
- pyscript/core/bases.py +2 -0
- pyscript/core/buffer.py +43 -0
- pyscript/core/cache.py +70 -0
- pyscript/core/checks.py +42 -0
- pyscript/core/constants.py +123 -0
- pyscript/core/context.py +63 -0
- pyscript/core/editor/__init__.py +15 -0
- pyscript/core/editor/bases.py +35 -0
- pyscript/core/editor/gui.py +144 -0
- pyscript/core/editor/terminal.py +175 -0
- pyscript/core/exceptions.py +123 -0
- pyscript/core/handlers.py +57 -0
- pyscript/core/highlight.py +552 -0
- pyscript/core/interpreter.py +1546 -0
- pyscript/core/lexer.py +863 -0
- pyscript/core/mapping.py +139 -0
- pyscript/core/nodes.py +663 -0
- pyscript/core/objects.py +213 -0
- pyscript/core/parser.py +2456 -0
- pyscript/core/position.py +114 -0
- pyscript/core/pysbuiltins.py +703 -0
- pyscript/core/results.py +186 -0
- pyscript/core/runner.py +363 -0
- pyscript/core/shell.py +287 -0
- pyscript/core/symtab.py +103 -0
- pyscript/core/token.py +25 -0
- pyscript/core/utils/__init__.py +27 -0
- pyscript/core/utils/ansi.py +127 -0
- pyscript/core/utils/debug.py +60 -0
- pyscript/core/utils/decorators.py +53 -0
- pyscript/core/utils/generic.py +46 -0
- pyscript/core/utils/jsdict.py +32 -0
- pyscript/core/utils/module.py +28 -0
- pyscript/core/utils/path.py +29 -0
- pyscript/core/utils/similarity.py +22 -0
- pyscript/core/utils/string.py +49 -0
- pyscript/core/version.py +120 -0
- pyscript/lib/__hello__.pys +7 -0
- pyscript/lib/ansi.pys +14 -0
- pyscript/lib/ast/__init__.pys +36 -0
- pyscript/lib/ast/ast_dump.py +433 -0
- pyscript/lib/ast/ast_literal_eval.py +80 -0
- pyscript/lib/ast/ast_unparse.py +540 -0
- pyscript/lib/ast/ast_walk.py +256 -0
- pyscript/lib/brainfuck.pys +190 -0
- pyscript/lib/dis.pys +7 -0
- pyscript/lib/explorer.pys +218 -0
- pyscript/lib/fpstimer/__init__.pys +6 -0
- pyscript/lib/fpstimer/py_fpstimer.py +54 -0
- pyscript/lib/getch.pys +28 -0
- pyscript/lib/inspect.pys +25 -0
- pyscript/lib/jsdict.pys +5 -0
- pyscript/lib/keyword.pys +2 -0
- pyscript/lib/opcode.pys +1 -0
- pyscript/lib/parser.pys +165 -0
- pyscript/lib/site.pys +55 -0
- pyscript/lib/symtable.pys +5 -0
- pyscript/lib/token.pys +12 -0
- pyscript/lib/tokenize/__init__.pys +14 -0
- pyscript/lib/tokenize/tok_untokenize.py +64 -0
- pyscript/other/.nomedia +0 -0
- pyscript/other/PyScript.ico +0 -0
- pyscript/other/copyright +2 -0
- pyscript/other/credits +2 -0
- pyscript/other/license +21 -0
- pyscript/site-packages/this.pys +19 -0
- pyscript/this.py +8 -0
- pyscript_programming_language-1.12.0.dist-info/METADATA +133 -0
- pyscript_programming_language-1.12.0.dist-info/RECORD +76 -0
- pyscript_programming_language-1.12.0.dist-info/WHEEL +5 -0
- pyscript_programming_language-1.12.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
from .bases import Pys
|
|
2
|
+
from .buffer import PysFileBuffer
|
|
3
|
+
from .cache import pys_sys
|
|
4
|
+
from .checks import is_blacklist_python_builtins, is_private_attribute
|
|
5
|
+
from .constants import OTHER_PATH, NO_COLOR, CLASSIC_LINE_SHELL
|
|
6
|
+
from .exceptions import PysSignal
|
|
7
|
+
from .handlers import handle_call
|
|
8
|
+
from .mapping import ACOLORS, EMPTY_MAP
|
|
9
|
+
from .objects import PysFunction, PysPythonFunction, PysBuiltinFunction
|
|
10
|
+
from .results import PysRunTimeResult
|
|
11
|
+
from .shell import PysClassicLineShell, PysPromptToolkitLineShell
|
|
12
|
+
from .symtab import new_symbol_table
|
|
13
|
+
from .utils.debug import import_readline
|
|
14
|
+
from .utils.generic import dkeys, get_subscript, is_object_of as isobjectof
|
|
15
|
+
from .utils.module import get_module_path, set_python_path, remove_python_path
|
|
16
|
+
from .utils.path import getcwd, normpath, get_name_from_path
|
|
17
|
+
from .utils.string import normstr
|
|
18
|
+
|
|
19
|
+
from math import inf, nan, isclose
|
|
20
|
+
from importlib import import_module
|
|
21
|
+
from inspect import signature
|
|
22
|
+
from os.path import dirname, isdir
|
|
23
|
+
from types import BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, ModuleType
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
import builtins
|
|
27
|
+
import sys
|
|
28
|
+
|
|
29
|
+
real_number = (int, float)
|
|
30
|
+
sequence = (list, tuple, set)
|
|
31
|
+
optional_mapping = (dict, type(None))
|
|
32
|
+
static_wrapper_function = (staticmethod,)
|
|
33
|
+
wrapper_function = (MethodType, PysPythonFunction, classmethod)
|
|
34
|
+
python_function = (BuiltinFunctionType, BuiltinMethodType, FunctionType)
|
|
35
|
+
|
|
36
|
+
pyhelp = builtins.help
|
|
37
|
+
pyvars = builtins.vars
|
|
38
|
+
pydir = builtins.dir
|
|
39
|
+
|
|
40
|
+
def _supported_method(pyfunc, object, name, *args, **kwargs):
|
|
41
|
+
if callable(method := getattr(object, name, None)):
|
|
42
|
+
code = pyfunc.__code__
|
|
43
|
+
handle_call(method, code.context, code.position)
|
|
44
|
+
try:
|
|
45
|
+
result = method(*args, **kwargs)
|
|
46
|
+
if result is not NotImplemented:
|
|
47
|
+
return True, result
|
|
48
|
+
except NotImplementedError:
|
|
49
|
+
pass
|
|
50
|
+
return False, None
|
|
51
|
+
|
|
52
|
+
def _unpack_comprehension_function(pyfunc, function):
|
|
53
|
+
code = pyfunc.__code__
|
|
54
|
+
check = function
|
|
55
|
+
final = function
|
|
56
|
+
offset = 0
|
|
57
|
+
|
|
58
|
+
if isinstance(function, wrapper_function):
|
|
59
|
+
check = function.__func__
|
|
60
|
+
offset += 1
|
|
61
|
+
elif isinstance(function, static_wrapper_function):
|
|
62
|
+
check = function.__func__
|
|
63
|
+
|
|
64
|
+
if isinstance(check, PysFunction):
|
|
65
|
+
length = max(check.__code__.parameters_length - offset, 0)
|
|
66
|
+
if length == 0:
|
|
67
|
+
def final(item):
|
|
68
|
+
return function()
|
|
69
|
+
elif length > 1:
|
|
70
|
+
def final(item):
|
|
71
|
+
return function(*item)
|
|
72
|
+
|
|
73
|
+
elif isinstance(check, python_function):
|
|
74
|
+
parameters = signature(check).parameters
|
|
75
|
+
length = max(len(parameters) - offset, 0)
|
|
76
|
+
if length == 0:
|
|
77
|
+
def final(item):
|
|
78
|
+
return function()
|
|
79
|
+
elif length > 1 or any(p.kind == p.VAR_POSITIONAL for p in parameters.values()):
|
|
80
|
+
def final(item):
|
|
81
|
+
return function(*item)
|
|
82
|
+
|
|
83
|
+
handle_call(function, code.context, code.position)
|
|
84
|
+
return final
|
|
85
|
+
|
|
86
|
+
class _Printer(Pys):
|
|
87
|
+
|
|
88
|
+
def __init__(self, name: str, text: str | Any) -> None:
|
|
89
|
+
self.name = name
|
|
90
|
+
self.text = text
|
|
91
|
+
|
|
92
|
+
def __repr__(self) -> str:
|
|
93
|
+
return f'Type {self.name}() to see the full information text.'
|
|
94
|
+
|
|
95
|
+
def __call__(self) -> None:
|
|
96
|
+
print(self.text)
|
|
97
|
+
|
|
98
|
+
class _Helper(_Printer):
|
|
99
|
+
|
|
100
|
+
def __init__(self) -> None:
|
|
101
|
+
super().__init__('help', None)
|
|
102
|
+
|
|
103
|
+
def __repr__(self) -> str:
|
|
104
|
+
return f'Type {self.name}() for interactive help, or {self.name}(object) for help about object.'
|
|
105
|
+
|
|
106
|
+
def __call__(self, *args, **kwargs):
|
|
107
|
+
if not (args or kwargs):
|
|
108
|
+
print(
|
|
109
|
+
"Welcome to the PyScript programming language! "
|
|
110
|
+
"This is the help utility directly to the Python help.\n\n"
|
|
111
|
+
"To get help on a specific object, type 'help(object)'.\n"
|
|
112
|
+
"To get the list of builtin functions, types, exceptions, and other objects, type 'help(\"builtins\")'."
|
|
113
|
+
)
|
|
114
|
+
else:
|
|
115
|
+
return pyhelp(*args, **kwargs)
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
with (
|
|
119
|
+
open(normpath(OTHER_PATH, 'copyright', absolute=False)) as copyright,
|
|
120
|
+
open(normpath(OTHER_PATH, 'credits', absolute=False)) as credits,
|
|
121
|
+
open(normpath(OTHER_PATH, 'license', absolute=False)) as license
|
|
122
|
+
):
|
|
123
|
+
copyright = _Printer('copyright', copyright.read())
|
|
124
|
+
credits = _Printer('credits', credits.read())
|
|
125
|
+
license = _Printer('license', license.read())
|
|
126
|
+
except:
|
|
127
|
+
copyright = _Printer('copyright', '')
|
|
128
|
+
credits = _Printer('credits', '')
|
|
129
|
+
license = _Printer('license', '')
|
|
130
|
+
|
|
131
|
+
help = _Helper()
|
|
132
|
+
|
|
133
|
+
@PysBuiltinFunction
|
|
134
|
+
def require(pyfunc, name):
|
|
135
|
+
|
|
136
|
+
"""
|
|
137
|
+
require(name: str | bytes) -> ModuleType | Any
|
|
138
|
+
|
|
139
|
+
Import a PyScript module.
|
|
140
|
+
|
|
141
|
+
name: A name or path of the module to be imported.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
name, *other_components = normstr(name).split('>')
|
|
145
|
+
code = pyfunc.__code__
|
|
146
|
+
context = code.context
|
|
147
|
+
filename = context.file.name
|
|
148
|
+
|
|
149
|
+
for p in pys_sys.path:
|
|
150
|
+
module_path = get_module_path(normpath(p, name, absolute=False))
|
|
151
|
+
if module_path is not None:
|
|
152
|
+
break
|
|
153
|
+
else:
|
|
154
|
+
module_path = get_module_path(normpath(dirname(filename) or getcwd(), name, absolute=False))
|
|
155
|
+
if module_path == filename:
|
|
156
|
+
module_path = None
|
|
157
|
+
|
|
158
|
+
if module_path is None:
|
|
159
|
+
if name == '_pyscript':
|
|
160
|
+
from .. import core as module
|
|
161
|
+
elif name == 'builtins':
|
|
162
|
+
module = pys_builtins
|
|
163
|
+
elif name == 'sys':
|
|
164
|
+
module = pys_sys
|
|
165
|
+
else:
|
|
166
|
+
module_path = name
|
|
167
|
+
|
|
168
|
+
if module_path is not None:
|
|
169
|
+
loading_modules = pys_sys.loading_modules
|
|
170
|
+
modules = pys_sys.modules
|
|
171
|
+
module = modules.get(module_path, None)
|
|
172
|
+
|
|
173
|
+
if module is None:
|
|
174
|
+
|
|
175
|
+
if isdir(module_path):
|
|
176
|
+
raise ModuleNotFoundError(f"No module named {name!r}: Invalid module")
|
|
177
|
+
elif module_path in loading_modules:
|
|
178
|
+
raise ImportError(
|
|
179
|
+
f"cannot import module name {name!r} from partially initialized module {filename!r}, "
|
|
180
|
+
"mostly during circular import"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
loading_modules.add(module_path)
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
with open(module_path, 'r', encoding='utf-8') as file:
|
|
188
|
+
file = PysFileBuffer(file, module_path)
|
|
189
|
+
except FileNotFoundError as e:
|
|
190
|
+
raise ModuleNotFoundError(f"No module named {name!r}") from e
|
|
191
|
+
except (IsADirectoryError, NotADirectoryError) as e:
|
|
192
|
+
raise ModuleNotFoundError(f"No module named {name!r}: Invalid module") from e
|
|
193
|
+
except BaseException as e:
|
|
194
|
+
raise ImportError(f"Cannot import module named {name!r}: {e}") from e
|
|
195
|
+
|
|
196
|
+
from .runner import pys_runner
|
|
197
|
+
|
|
198
|
+
symtab, module = new_symbol_table(file=file.name, name=get_name_from_path(name))
|
|
199
|
+
|
|
200
|
+
# minimize circular imports (python standard)
|
|
201
|
+
modules[module_path] = module
|
|
202
|
+
|
|
203
|
+
result = pys_runner(
|
|
204
|
+
file=file,
|
|
205
|
+
mode='exec',
|
|
206
|
+
symbol_table=symtab,
|
|
207
|
+
context_parent=context,
|
|
208
|
+
context_parent_entry_position=code.position
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
if result.error:
|
|
212
|
+
raise PysSignal(PysRunTimeResult().failure(result.error))
|
|
213
|
+
|
|
214
|
+
# this can also get circular imports
|
|
215
|
+
# modules[module_path] = module
|
|
216
|
+
|
|
217
|
+
except:
|
|
218
|
+
modules.pop(module_path, None)
|
|
219
|
+
raise
|
|
220
|
+
|
|
221
|
+
finally:
|
|
222
|
+
loading_modules.discard(module_path)
|
|
223
|
+
|
|
224
|
+
for component in other_components:
|
|
225
|
+
module = getattr(module, component)
|
|
226
|
+
|
|
227
|
+
return module
|
|
228
|
+
|
|
229
|
+
@PysBuiltinFunction
|
|
230
|
+
def pyimport(pyfunc, name):
|
|
231
|
+
|
|
232
|
+
"""
|
|
233
|
+
pyimport(name: str | bytes) -> ModuleType
|
|
234
|
+
|
|
235
|
+
Import a Python module.
|
|
236
|
+
|
|
237
|
+
name: A name of the module to be imported.
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
dirpath = dirname(pyfunc.__code__.context.file.name)
|
|
241
|
+
try:
|
|
242
|
+
set_python_path(dirpath)
|
|
243
|
+
return import_module(normstr(name))
|
|
244
|
+
finally:
|
|
245
|
+
remove_python_path(dirpath)
|
|
246
|
+
|
|
247
|
+
@PysBuiltinFunction
|
|
248
|
+
def breakpoint(pyfunc):
|
|
249
|
+
|
|
250
|
+
"""
|
|
251
|
+
Pauses program execution and enters shell debugging mode.
|
|
252
|
+
"""
|
|
253
|
+
|
|
254
|
+
if pys_sys.__running_breakpoint__:
|
|
255
|
+
raise RuntimeError("another breakpoint is still running")
|
|
256
|
+
|
|
257
|
+
from .runner import pys_runner
|
|
258
|
+
|
|
259
|
+
code = pyfunc.__code__
|
|
260
|
+
context = code.context
|
|
261
|
+
position = code.position
|
|
262
|
+
symtab = context.symbol_table
|
|
263
|
+
flags = context.flags
|
|
264
|
+
colored = not (flags & NO_COLOR)
|
|
265
|
+
scopes = []
|
|
266
|
+
|
|
267
|
+
if colored:
|
|
268
|
+
reset = ACOLORS('reset')
|
|
269
|
+
bmagenta = ACOLORS('bold-magenta')
|
|
270
|
+
else:
|
|
271
|
+
reset = ''
|
|
272
|
+
bmagenta = ''
|
|
273
|
+
|
|
274
|
+
shell = (PysClassicLineShell if flags & CLASSIC_LINE_SHELL else PysPromptToolkitLineShell)(
|
|
275
|
+
f'{bmagenta}(Pdb) {reset}',
|
|
276
|
+
f'{bmagenta}... {reset}',
|
|
277
|
+
colored=colored
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def show_line():
|
|
281
|
+
print(f'> {context.file.name}({position.start_line}){context.name}')
|
|
282
|
+
|
|
283
|
+
import_readline()
|
|
284
|
+
show_line()
|
|
285
|
+
|
|
286
|
+
try:
|
|
287
|
+
pys_sys.__running_breakpoint__ = True
|
|
288
|
+
|
|
289
|
+
while True:
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
text = shell.prompt()
|
|
293
|
+
if text == 1:
|
|
294
|
+
print("*** Unable to clean up namespace", file=sys.stderr)
|
|
295
|
+
continue
|
|
296
|
+
|
|
297
|
+
split = ['exit'] if text == 0 else text.split()
|
|
298
|
+
if split:
|
|
299
|
+
command, *args = split
|
|
300
|
+
else:
|
|
301
|
+
command, args = '', []
|
|
302
|
+
|
|
303
|
+
if command in ('c', 'continue'):
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
elif command in ('h', 'help'):
|
|
307
|
+
print(
|
|
308
|
+
"\n"
|
|
309
|
+
"Documented commands:\n"
|
|
310
|
+
"====================\n"
|
|
311
|
+
"(c)ontinue : Exit the debugger and continue the program.\n"
|
|
312
|
+
"(d)own [count] : Decrease the scope level (default one) to the older frame.\n"
|
|
313
|
+
"(h)elp : Show this help display.\n"
|
|
314
|
+
"(l)ine : Show the position where breakpoint() was called.\n"
|
|
315
|
+
"(q)uit / exit [code]: Exit the interpreter by throwing SystemExit.\n"
|
|
316
|
+
"(u)p [count] : Increase the scope level (default one) to the older frame.\n"
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
elif command in ('l', 'line'):
|
|
320
|
+
show_line()
|
|
321
|
+
|
|
322
|
+
elif command in ('q', 'quit', 'exit'):
|
|
323
|
+
code = get_subscript(args, 0, '0')
|
|
324
|
+
raise SystemExit(int(code) if code.isdigit() else code)
|
|
325
|
+
|
|
326
|
+
elif command in ('u', 'up'):
|
|
327
|
+
count = get_subscript(args, 0, '')
|
|
328
|
+
for _ in range(int(count) if count.isdigit() else 1):
|
|
329
|
+
if scopes:
|
|
330
|
+
symtab = scopes.pop()
|
|
331
|
+
else:
|
|
332
|
+
print('*** Oldest frame')
|
|
333
|
+
break
|
|
334
|
+
|
|
335
|
+
elif command in ('d', 'down'):
|
|
336
|
+
count = get_subscript(args, 0, '')
|
|
337
|
+
parent = symtab.parent
|
|
338
|
+
for _ in range(int(count) if count.isdigit() else 1):
|
|
339
|
+
if parent is None:
|
|
340
|
+
print('*** Newest frame')
|
|
341
|
+
break
|
|
342
|
+
else:
|
|
343
|
+
scopes.append(symtab)
|
|
344
|
+
symtab = parent
|
|
345
|
+
|
|
346
|
+
else:
|
|
347
|
+
exit_code, exit = pys_runner(
|
|
348
|
+
file=PysFileBuffer(text, '<breakpoint>'),
|
|
349
|
+
mode='single',
|
|
350
|
+
symbol_table=symtab
|
|
351
|
+
).end_process()
|
|
352
|
+
|
|
353
|
+
if exit:
|
|
354
|
+
raise SystemExit(exit_code)
|
|
355
|
+
|
|
356
|
+
except KeyboardInterrupt:
|
|
357
|
+
shell.reset()
|
|
358
|
+
print('\r--KeyboardInterrupt--', file=sys.stderr)
|
|
359
|
+
|
|
360
|
+
except EOFError as e:
|
|
361
|
+
raise SystemExit from e
|
|
362
|
+
|
|
363
|
+
finally:
|
|
364
|
+
pys_sys.__running_breakpoint__ = False
|
|
365
|
+
|
|
366
|
+
@PysBuiltinFunction
|
|
367
|
+
def globals(pyfunc):
|
|
368
|
+
|
|
369
|
+
"""
|
|
370
|
+
Returns a dictionary containing the current global scope of variables.
|
|
371
|
+
|
|
372
|
+
NOTE: Modifying the contents of a dictionary within a program or module scope will affect that scope. However,
|
|
373
|
+
this does not apply to local scopes (creating a new dictionary).
|
|
374
|
+
"""
|
|
375
|
+
|
|
376
|
+
original = pyfunc.__code__.context.symbol_table
|
|
377
|
+
symbol_table = original.parent
|
|
378
|
+
|
|
379
|
+
if symbol_table:
|
|
380
|
+
result = {}
|
|
381
|
+
|
|
382
|
+
while symbol_table:
|
|
383
|
+
result |= symbol_table.symbols
|
|
384
|
+
symbol_table = symbol_table.parent
|
|
385
|
+
|
|
386
|
+
return result
|
|
387
|
+
|
|
388
|
+
return original.symbols
|
|
389
|
+
|
|
390
|
+
@PysBuiltinFunction
|
|
391
|
+
def locals(pyfunc):
|
|
392
|
+
|
|
393
|
+
"""
|
|
394
|
+
Returns a dictionary containing the current local scope of variables.
|
|
395
|
+
|
|
396
|
+
NOTE: Changing the contents of the dictionary will affect the scope.
|
|
397
|
+
"""
|
|
398
|
+
|
|
399
|
+
return pyfunc.__code__.context.symbol_table.symbols
|
|
400
|
+
|
|
401
|
+
@PysBuiltinFunction
|
|
402
|
+
def vars(pyfunc, *args):
|
|
403
|
+
|
|
404
|
+
"""
|
|
405
|
+
Without arguments, equivalent to locals(). With an argument, equivalent to object.__dict__.
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
return pyvars(*args) if args else pyfunc.__code__.context.symbol_table.symbols
|
|
409
|
+
|
|
410
|
+
@PysBuiltinFunction
|
|
411
|
+
def dir(pyfunc, *args):
|
|
412
|
+
|
|
413
|
+
"""
|
|
414
|
+
If called without an argument, return the names in the current scope. Else, return an alphabetized list of names
|
|
415
|
+
comprising (some of) the attributes of the given object, and of attributes reachable from it. If the object supplies
|
|
416
|
+
a method named __dir__, it will be used; otherwise the default dir() logic is used and returns:
|
|
417
|
+
for a module object: the module's attributes.
|
|
418
|
+
for a class object: its attributes, and recursively the attributes of its bases.
|
|
419
|
+
for any other object: its attributes, its class's attributes, and recursively the attributes of its class's base
|
|
420
|
+
classes.
|
|
421
|
+
"""
|
|
422
|
+
|
|
423
|
+
return pydir(*args) if args else list(dkeys(pyfunc.__code__.context.symbol_table.symbols))
|
|
424
|
+
|
|
425
|
+
@PysBuiltinFunction
|
|
426
|
+
def exec(pyfunc, source, globals=None):
|
|
427
|
+
|
|
428
|
+
"""
|
|
429
|
+
exec(source: str | bytes, globals: Optional[dict]) -> None
|
|
430
|
+
|
|
431
|
+
Executes PyScript code statements from the given source.
|
|
432
|
+
|
|
433
|
+
source: A string containing the code statements to be executed.
|
|
434
|
+
globals: The namespace scope for the code that can be accessed, modified, and deleted. If not provided, the current
|
|
435
|
+
local scope will be used.
|
|
436
|
+
"""
|
|
437
|
+
|
|
438
|
+
if not isinstance(globals, optional_mapping):
|
|
439
|
+
raise TypeError("exec(): globals must be dict")
|
|
440
|
+
|
|
441
|
+
file = PysFileBuffer(source, '<exec>')
|
|
442
|
+
code = pyfunc.__code__
|
|
443
|
+
|
|
444
|
+
if globals is None:
|
|
445
|
+
symtab = code.context.symbol_table
|
|
446
|
+
else:
|
|
447
|
+
symtab, _ = new_symbol_table(symbols=globals)
|
|
448
|
+
|
|
449
|
+
from .runner import pys_runner
|
|
450
|
+
|
|
451
|
+
result = pys_runner(
|
|
452
|
+
file=file,
|
|
453
|
+
mode='exec',
|
|
454
|
+
symbol_table=symtab,
|
|
455
|
+
context_parent=code.context,
|
|
456
|
+
context_parent_entry_position=code.position
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
if result.error:
|
|
460
|
+
raise PysSignal(PysRunTimeResult().failure(result.error))
|
|
461
|
+
|
|
462
|
+
@PysBuiltinFunction
|
|
463
|
+
def eval(pyfunc, source, globals=None):
|
|
464
|
+
|
|
465
|
+
"""
|
|
466
|
+
eval(source: str | bytes, globals: Optional[dict]) -> None
|
|
467
|
+
|
|
468
|
+
Executes a PyScript code expression from the given source.
|
|
469
|
+
|
|
470
|
+
source: A string containing the code statements to be executed.
|
|
471
|
+
globals: The namespace scope for the code that can be accessed, modified, and deleted. If not provided, the current
|
|
472
|
+
local scope will be used.
|
|
473
|
+
"""
|
|
474
|
+
|
|
475
|
+
if not isinstance(globals, optional_mapping):
|
|
476
|
+
raise TypeError("eval(): globals must be dict")
|
|
477
|
+
|
|
478
|
+
file = PysFileBuffer(source, '<eval>')
|
|
479
|
+
code = pyfunc.__code__
|
|
480
|
+
|
|
481
|
+
if globals is None:
|
|
482
|
+
symtab = code.context.symbol_table
|
|
483
|
+
else:
|
|
484
|
+
symtab, _ = new_symbol_table(symbols=globals)
|
|
485
|
+
|
|
486
|
+
from .runner import pys_runner
|
|
487
|
+
|
|
488
|
+
result = pys_runner(
|
|
489
|
+
file=file,
|
|
490
|
+
mode='eval',
|
|
491
|
+
symbol_table=symtab,
|
|
492
|
+
context_parent=code.context,
|
|
493
|
+
context_parent_entry_position=code.position
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
if result.error:
|
|
497
|
+
raise PysSignal(PysRunTimeResult().failure(result.error))
|
|
498
|
+
|
|
499
|
+
return result.value
|
|
500
|
+
|
|
501
|
+
@PysBuiltinFunction
|
|
502
|
+
def ce(pyfunc, a, b, *, rel_tol=1e-9, abs_tol=0):
|
|
503
|
+
|
|
504
|
+
"""
|
|
505
|
+
ce(a: Any, b: Any, *, rel_tol: Any = 1e-9, abs_tol: Any = 0) -> Any
|
|
506
|
+
a ~= b
|
|
507
|
+
|
|
508
|
+
Comparing two objects a and b to close equal.
|
|
509
|
+
|
|
510
|
+
a, b: Two objects to be compared. If both are integer or float, it will call `math.isclose()` function. Otherwise,
|
|
511
|
+
it will attempt to call the __ce__ method (if both fail, it calls the negated __nce__ method) of one of the
|
|
512
|
+
two objects. If all else fails, it will throw a TypeError.
|
|
513
|
+
rel_tol: maximum difference for being considered "close", relative to the magnitude of the input values.
|
|
514
|
+
abs_tol: maximum difference for being considered "close", regardless of the magnitude of the input values.
|
|
515
|
+
"""
|
|
516
|
+
|
|
517
|
+
if isinstance(a, real_number) and isinstance(b, real_number):
|
|
518
|
+
return isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
519
|
+
|
|
520
|
+
success, result = _supported_method(pyfunc, a, '__ce__', b, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
521
|
+
if not success:
|
|
522
|
+
success, result = _supported_method(pyfunc, b, '__ce__', a, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
523
|
+
if not success:
|
|
524
|
+
success, result = _supported_method(pyfunc, a, '__nce__', b, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
525
|
+
if not success:
|
|
526
|
+
success, result = _supported_method(pyfunc, b, '__nce__', a, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
527
|
+
if not success:
|
|
528
|
+
raise TypeError(
|
|
529
|
+
f"unsupported operand type(s) for ~= or ce(): {type(a).__name__!r} and {type(b).__name__!r}"
|
|
530
|
+
)
|
|
531
|
+
result = not result
|
|
532
|
+
|
|
533
|
+
return result
|
|
534
|
+
|
|
535
|
+
@PysBuiltinFunction
|
|
536
|
+
def nce(pyfunc, a, b, *, rel_tol=1e-9, abs_tol=0):
|
|
537
|
+
|
|
538
|
+
"""
|
|
539
|
+
nce(a: Any, b: Any, *, rel_tol: Any = 1e-9, abs_tol: Any = 0) -> Any
|
|
540
|
+
a ~! b
|
|
541
|
+
|
|
542
|
+
Comparing two objects a and b to not close equal.
|
|
543
|
+
|
|
544
|
+
a, b: Two objects to be compared. If both are integer or float, it calls the `not math.isclose()` function.
|
|
545
|
+
Otherwise, it attempts to call the __nce__ method (if both fail, it calls the negated __ce__ method) of one of
|
|
546
|
+
the two objects. If both fail, it throws a TypeError.
|
|
547
|
+
rel_tol: maximum difference for being considered "close", relative to the magnitude of the input values.
|
|
548
|
+
abs_tol: maximum difference for being considered "close", regardless of the magnitude of the input values.
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
if isinstance(a, real_number) and isinstance(b, real_number):
|
|
552
|
+
return not isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
553
|
+
|
|
554
|
+
success, result = _supported_method(pyfunc, a, '__nce__', b, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
555
|
+
if not success:
|
|
556
|
+
success, result = _supported_method(pyfunc, b, '__nce__', a, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
557
|
+
if not success:
|
|
558
|
+
success, result = _supported_method(pyfunc, a, '__ce__', b, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
559
|
+
if not success:
|
|
560
|
+
success, result = _supported_method(pyfunc, b, '__ce__', a, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
561
|
+
if not success:
|
|
562
|
+
raise TypeError(
|
|
563
|
+
f"unsupported operand type(s) for ~! or nce(): {type(a).__name__!r} and {type(b).__name__!r}"
|
|
564
|
+
)
|
|
565
|
+
result = not result
|
|
566
|
+
|
|
567
|
+
return result
|
|
568
|
+
|
|
569
|
+
@PysBuiltinFunction
|
|
570
|
+
def increment(pyfunc, object):
|
|
571
|
+
|
|
572
|
+
"""
|
|
573
|
+
increment(object: Any) -> Any
|
|
574
|
+
object++
|
|
575
|
+
++object
|
|
576
|
+
|
|
577
|
+
Increase to the object. If the given type is integer or float, it will increment by 1, if the given type is unpack
|
|
578
|
+
assignment (list, tuple, or set), it will increment each element. Otherwise, it will attempt to call the
|
|
579
|
+
__increment__ method, which if unsuccessful will throw a TypeError.
|
|
580
|
+
"""
|
|
581
|
+
|
|
582
|
+
if isinstance(object, real_number):
|
|
583
|
+
return object + 1
|
|
584
|
+
elif isinstance(object, sequence):
|
|
585
|
+
return tuple(pyincrement(pyfunc, obj) for obj in object)
|
|
586
|
+
|
|
587
|
+
success, result = _supported_method(pyfunc, object, '__increment__')
|
|
588
|
+
if not success:
|
|
589
|
+
raise TypeError(f"bad operand type for unary ++ or increment(): {type(object).__name__!r}")
|
|
590
|
+
|
|
591
|
+
return result
|
|
592
|
+
|
|
593
|
+
@PysBuiltinFunction
|
|
594
|
+
def decrement(pyfunc, object):
|
|
595
|
+
|
|
596
|
+
"""
|
|
597
|
+
decrement(object: Any) -> Any
|
|
598
|
+
object--
|
|
599
|
+
--object
|
|
600
|
+
|
|
601
|
+
Decrease to the object. If the given type is integer or float, it will decrement by 1, if the given type is unpack
|
|
602
|
+
assignment (list, tuple, or set), it will decrement each element. Otherwise, it will attempt to
|
|
603
|
+
call the __decrement__ method, which if unsuccessful will throw a TypeError.
|
|
604
|
+
"""
|
|
605
|
+
|
|
606
|
+
if isinstance(object, real_number):
|
|
607
|
+
return object - 1
|
|
608
|
+
elif isinstance(object, sequence):
|
|
609
|
+
return tuple(pydecrement(pyfunc, obj) for obj in object)
|
|
610
|
+
|
|
611
|
+
success, result = _supported_method(pyfunc, object, '__decrement__')
|
|
612
|
+
if not success:
|
|
613
|
+
raise TypeError(f"bad operand type for unary -- or decrement(): {type(object).__name__!r}")
|
|
614
|
+
|
|
615
|
+
return result
|
|
616
|
+
|
|
617
|
+
pyincrement = increment.__func__
|
|
618
|
+
pydecrement = decrement.__func__
|
|
619
|
+
|
|
620
|
+
@PysBuiltinFunction
|
|
621
|
+
def unpack(pyfunc, function, args=(), kwargs=EMPTY_MAP):
|
|
622
|
+
|
|
623
|
+
"""
|
|
624
|
+
unpack(function: Callable, args: Iterable = (), kwargs: Mapping = {}) -> Any
|
|
625
|
+
|
|
626
|
+
A replacement function for Python's argument unpack on function calls, which uses the syntax
|
|
627
|
+
`function(*args, **kwargs)`.
|
|
628
|
+
|
|
629
|
+
function: the function to be called.
|
|
630
|
+
args: regular arguments (iterable object).
|
|
631
|
+
kwargs: keyword arguments (mapping object).
|
|
632
|
+
"""
|
|
633
|
+
|
|
634
|
+
code = pyfunc.__code__
|
|
635
|
+
handle_call(function, code.context, code.position)
|
|
636
|
+
return function(*args, **kwargs)
|
|
637
|
+
|
|
638
|
+
@PysBuiltinFunction
|
|
639
|
+
def comprehension(pyfunc, init, wrap, condition=None):
|
|
640
|
+
|
|
641
|
+
"""
|
|
642
|
+
comprehension(
|
|
643
|
+
init: Iterable[Any],
|
|
644
|
+
wrap: Callable[[Any], Any],
|
|
645
|
+
condition: Optional[Callable[[Any], bool]] = None
|
|
646
|
+
) -> Iterable[Any]
|
|
647
|
+
|
|
648
|
+
A replacement function for Python's list comprehension, which uses the syntax
|
|
649
|
+
`[wrap for item in init if condition]`.
|
|
650
|
+
|
|
651
|
+
init: The iterable object to be iterated.
|
|
652
|
+
wrap: The function that wraps the results of the iteration (Unpack per-iteration if parameter is more than 1).
|
|
653
|
+
condition: The function that filters the iteration (Unpack per-iteration if parameter is more than 1).
|
|
654
|
+
"""
|
|
655
|
+
|
|
656
|
+
if not callable(wrap):
|
|
657
|
+
raise TypeError("comprehension(): wrap must be callable")
|
|
658
|
+
if not (condition is None or callable(condition)):
|
|
659
|
+
raise TypeError("comprehension(): condition must be callable")
|
|
660
|
+
|
|
661
|
+
return map(
|
|
662
|
+
_unpack_comprehension_function(pyfunc, wrap),
|
|
663
|
+
init if condition is None else filter(_unpack_comprehension_function(pyfunc, condition), init)
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
pys_builtins = ModuleType(
|
|
667
|
+
'builtins',
|
|
668
|
+
"Built-in functions, types, exceptions, and other objects.\n\n"
|
|
669
|
+
"This module provides direct access to all 'built-in' identifiers of PyScript and Python."
|
|
670
|
+
)
|
|
671
|
+
|
|
672
|
+
pys_builtins.__dict__.update(
|
|
673
|
+
(name, getattr(builtins, name))
|
|
674
|
+
for name in pydir(builtins)
|
|
675
|
+
if not (is_private_attribute(name) or is_blacklist_python_builtins(name))
|
|
676
|
+
)
|
|
677
|
+
|
|
678
|
+
pys_builtins.true = True
|
|
679
|
+
pys_builtins.false = False
|
|
680
|
+
pys_builtins.none = None
|
|
681
|
+
pys_builtins.ellipsis = Ellipsis
|
|
682
|
+
pys_builtins.inf = pys_builtins.infinity = pys_builtins.Infinity = inf
|
|
683
|
+
pys_builtins.nan = pys_builtins.notanumber = pys_builtins.NaN = pys_builtins.NotANumber = nan
|
|
684
|
+
pys_builtins.copyright = copyright
|
|
685
|
+
pys_builtins.credits = credits
|
|
686
|
+
pys_builtins.license = license
|
|
687
|
+
pys_builtins.help = help
|
|
688
|
+
pys_builtins.require = require
|
|
689
|
+
pys_builtins.pyimport = pyimport
|
|
690
|
+
pys_builtins.breakpoint = breakpoint
|
|
691
|
+
pys_builtins.globals = globals
|
|
692
|
+
pys_builtins.locals = locals
|
|
693
|
+
pys_builtins.vars = vars
|
|
694
|
+
pys_builtins.dir = dir
|
|
695
|
+
pys_builtins.exec = exec
|
|
696
|
+
pys_builtins.eval = eval
|
|
697
|
+
pys_builtins.ce = ce
|
|
698
|
+
pys_builtins.nce = nce
|
|
699
|
+
pys_builtins.increment = increment
|
|
700
|
+
pys_builtins.decrement = decrement
|
|
701
|
+
pys_builtins.unpack = unpack
|
|
702
|
+
pys_builtins.comprehension = comprehension
|
|
703
|
+
pys_builtins.isobjectof = isobjectof
|