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,46 @@
|
|
|
1
|
+
from inspect import currentframe
|
|
2
|
+
from types import UnionType
|
|
3
|
+
|
|
4
|
+
getattribute = object.__getattribute__
|
|
5
|
+
setimuattr = object.__setattr__
|
|
6
|
+
delimuattr = object.__delattr__
|
|
7
|
+
dinit = dict.__init__
|
|
8
|
+
drepr = dict.__repr__
|
|
9
|
+
dor = dict.__or__
|
|
10
|
+
dcontains = dict.__contains__
|
|
11
|
+
dgetitem = dict.__getitem__
|
|
12
|
+
dsetitem = dict.__setitem__
|
|
13
|
+
ddelitem = dict.__delitem__
|
|
14
|
+
dget = dict.get
|
|
15
|
+
dkeys = dict.keys
|
|
16
|
+
ditems = dict.items
|
|
17
|
+
|
|
18
|
+
def get_frame(deep=0):
|
|
19
|
+
deep += 1
|
|
20
|
+
frame = currentframe()
|
|
21
|
+
while deep > 0 and frame:
|
|
22
|
+
frame = frame.f_back
|
|
23
|
+
deep -= 1
|
|
24
|
+
return frame
|
|
25
|
+
|
|
26
|
+
def get_locals(deep=0):
|
|
27
|
+
if frame := get_frame(deep + 1):
|
|
28
|
+
locals = frame.f_locals
|
|
29
|
+
return locals if isinstance(locals, dict) else dict(locals)
|
|
30
|
+
return {}
|
|
31
|
+
|
|
32
|
+
def get_subscript(object, key, default=None):
|
|
33
|
+
return object[key] if 0 <= key < len(object) else default
|
|
34
|
+
|
|
35
|
+
def is_object_of(obj: object | type, class_or_tuple: type | UnionType | tuple[type | UnionType, ...]) -> bool:
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
Returns whether an object is derived from a parent class.
|
|
39
|
+
The object here can be an initialized object, which calls `isinstance(obj, class_or_type)`,
|
|
40
|
+
or a class type, which calls `issubclass(obj, class_or_tuple)`.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
isinstance(obj, class_or_tuple) or
|
|
45
|
+
(isinstance(obj, type) and issubclass(obj, class_or_tuple))
|
|
46
|
+
)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from .generic import dinit, drepr, dor, dsetitem, ddelitem, ditems
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
class jsdict(dict):
|
|
6
|
+
|
|
7
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
8
|
+
dinit(self, *args, **kwargs)
|
|
9
|
+
for key, value in ditems(self):
|
|
10
|
+
if value is None:
|
|
11
|
+
ddelitem(self, key)
|
|
12
|
+
|
|
13
|
+
def __repr__(self) -> str:
|
|
14
|
+
return f'jsdict({drepr(self)})'
|
|
15
|
+
|
|
16
|
+
def __or__(self, *args, **kwargs) -> 'jsdict':
|
|
17
|
+
return jsdict(dor(self, *args, **kwargs))
|
|
18
|
+
|
|
19
|
+
def __setattr__(self, key: Any, value: Any) -> None:
|
|
20
|
+
if value is None:
|
|
21
|
+
if key in self:
|
|
22
|
+
ddelitem(self, key)
|
|
23
|
+
else:
|
|
24
|
+
dsetitem(self, key, value)
|
|
25
|
+
|
|
26
|
+
def __delattr__(self, key: Any) -> None:
|
|
27
|
+
if key in self:
|
|
28
|
+
ddelitem(self, key)
|
|
29
|
+
|
|
30
|
+
__getitem__ = __getattribute__ = dict.get
|
|
31
|
+
__setitem__ = __setattr__
|
|
32
|
+
__delitem__ = __delattr__
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from .path import extension
|
|
2
|
+
|
|
3
|
+
from os.path import isdir, isfile, join
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
def get_module_path(path):
|
|
8
|
+
# circular import problem solved
|
|
9
|
+
from ..checks import is_python_extensions
|
|
10
|
+
|
|
11
|
+
if isfile(path) and not is_python_extensions(extension(path)):
|
|
12
|
+
return path
|
|
13
|
+
|
|
14
|
+
candidate = path + '.pys'
|
|
15
|
+
if isfile(candidate):
|
|
16
|
+
return candidate
|
|
17
|
+
|
|
18
|
+
candidate = join(path, '__init__.pys')
|
|
19
|
+
if isdir(path) and isfile(candidate):
|
|
20
|
+
return candidate
|
|
21
|
+
|
|
22
|
+
def set_python_path(path):
|
|
23
|
+
if path not in sys.path:
|
|
24
|
+
sys.path.insert(0, path)
|
|
25
|
+
|
|
26
|
+
def remove_python_path(path):
|
|
27
|
+
if path in sys.path:
|
|
28
|
+
sys.path.remove(path)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from os import getcwd as osgetcwd
|
|
2
|
+
from os.path import sep, abspath as osabspath, normpath as osnormpath, splitext, basename
|
|
3
|
+
|
|
4
|
+
from .string import normstr
|
|
5
|
+
|
|
6
|
+
def getcwd():
|
|
7
|
+
try:
|
|
8
|
+
return osgetcwd()
|
|
9
|
+
except:
|
|
10
|
+
return '.'
|
|
11
|
+
|
|
12
|
+
def abspath(path):
|
|
13
|
+
try:
|
|
14
|
+
return osabspath(path)
|
|
15
|
+
except:
|
|
16
|
+
return path
|
|
17
|
+
|
|
18
|
+
def base(path):
|
|
19
|
+
return splitext(basename(path))[0]
|
|
20
|
+
|
|
21
|
+
def extension(path):
|
|
22
|
+
return splitext(basename(path))[1]
|
|
23
|
+
|
|
24
|
+
def normpath(*paths, absolute=True):
|
|
25
|
+
path = osnormpath(sep.join(map(normstr, paths)))
|
|
26
|
+
return abspath(path) if absolute else path
|
|
27
|
+
|
|
28
|
+
def get_name_from_path(path):
|
|
29
|
+
return base(normpath(path, absolute=False))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from itertools import pairwise
|
|
2
|
+
from re import compile as re_compile
|
|
3
|
+
|
|
4
|
+
replace = re_compile(r'\s+').sub
|
|
5
|
+
|
|
6
|
+
def get_similarity_ratio(string1, string2):
|
|
7
|
+
bigram1 = set(s1 + s2 for s1, s2 in pairwise(replace('', string1).lower()))
|
|
8
|
+
bigram2 = set(s1 + s2 for s1, s2 in pairwise(replace('', string2).lower()))
|
|
9
|
+
max_bigrams_count = max(len(bigram1), len(bigram2))
|
|
10
|
+
return len(bigram1 & bigram2) / max_bigrams_count if max_bigrams_count else 0.0
|
|
11
|
+
|
|
12
|
+
def get_closest(elements, target, cutoff=0.6):
|
|
13
|
+
best_match = None
|
|
14
|
+
best_score = 0.0
|
|
15
|
+
|
|
16
|
+
for element in elements:
|
|
17
|
+
score = get_similarity_ratio(target, element)
|
|
18
|
+
if score >= cutoff and score > best_score:
|
|
19
|
+
best_score = score
|
|
20
|
+
best_match = element
|
|
21
|
+
|
|
22
|
+
return best_match
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from io import IOBase, TextIOWrapper
|
|
3
|
+
from json import detect_encoding
|
|
4
|
+
from types import BuiltinMethodType
|
|
5
|
+
|
|
6
|
+
def normstr(obj):
|
|
7
|
+
if isinstance(obj, str):
|
|
8
|
+
return obj.replace('\r\n', '\n').replace('\r', '\n').replace('\v', '\n')
|
|
9
|
+
|
|
10
|
+
elif isinstance(obj, (bytes, bytearray)):
|
|
11
|
+
return normstr(obj.decode(detect_encoding(obj), 'surrogatepass'))
|
|
12
|
+
|
|
13
|
+
elif isinstance(obj, IOBase):
|
|
14
|
+
if not obj.readable():
|
|
15
|
+
raise TypeError("unreadable IO")
|
|
16
|
+
return normstr(obj.read())
|
|
17
|
+
|
|
18
|
+
elif isinstance(obj, Iterable):
|
|
19
|
+
return '\n'.join(map(normstr, obj))
|
|
20
|
+
|
|
21
|
+
elif (
|
|
22
|
+
isinstance(obj, BuiltinMethodType) and
|
|
23
|
+
isinstance(self := getattr(obj, '__self__', None), TextIOWrapper) and
|
|
24
|
+
obj.__name__ == 'readline'
|
|
25
|
+
):
|
|
26
|
+
|
|
27
|
+
if not self.readable():
|
|
28
|
+
raise TypeError("unreadable IO, provides readline function")
|
|
29
|
+
|
|
30
|
+
lines = []
|
|
31
|
+
while True:
|
|
32
|
+
if not (line := obj()):
|
|
33
|
+
break
|
|
34
|
+
lines.append(normstr(line))
|
|
35
|
+
return '\n'.join(lines)
|
|
36
|
+
|
|
37
|
+
raise TypeError('not a string')
|
|
38
|
+
|
|
39
|
+
def join(sequence, conjunction='and'):
|
|
40
|
+
length = len(sequence)
|
|
41
|
+
if length == 1:
|
|
42
|
+
return sequence[0]
|
|
43
|
+
elif length == 2:
|
|
44
|
+
return f'{sequence[0]} {conjunction} {sequence[1]}'
|
|
45
|
+
return f'{", ".join(sequence[:-1])}, {conjunction} {sequence[-1]}'
|
|
46
|
+
|
|
47
|
+
def indent(string, length):
|
|
48
|
+
prefix = ' ' * length
|
|
49
|
+
return '\n'.join(prefix + line for line in normstr(string).splitlines())
|
pyscript/core/version.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from .bases import Pys
|
|
2
|
+
from .cache import pys_sys
|
|
3
|
+
from .utils.decorators import immutable, inheritable, singleton
|
|
4
|
+
|
|
5
|
+
from re import compile as re_compile
|
|
6
|
+
from types import MappingProxyType
|
|
7
|
+
|
|
8
|
+
version_match = re_compile(r'^(\d+)\.(\d+)\.(\d+)((?:a|b|rc)(\d+)|\.(dev|post)(\d+))?$').match
|
|
9
|
+
|
|
10
|
+
__version__ = '1.12.0'
|
|
11
|
+
__date__ = '18 February 2026, 17:52 UTC+7'
|
|
12
|
+
|
|
13
|
+
version = pys_sys.version = f'{__version__} ({__date__})'
|
|
14
|
+
|
|
15
|
+
TAG_VERSION_MAP = MappingProxyType({
|
|
16
|
+
'a': 'alpha',
|
|
17
|
+
'b': 'beta',
|
|
18
|
+
'rc': 'release candidate',
|
|
19
|
+
'dev': 'development',
|
|
20
|
+
'post': 'post'
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
@singleton
|
|
24
|
+
@immutable
|
|
25
|
+
@inheritable
|
|
26
|
+
class PysVersionInfo(Pys, tuple):
|
|
27
|
+
|
|
28
|
+
__slots__ = ()
|
|
29
|
+
|
|
30
|
+
def __new_singleton__(cls) -> 'PysVersionInfo':
|
|
31
|
+
match = version_match(__version__)
|
|
32
|
+
if not match:
|
|
33
|
+
raise ValueError(f"invalid format version: {__version__!r}")
|
|
34
|
+
|
|
35
|
+
major, minor, micro, pre_full, pre_num1, pre_tag2, pre_num2 = match.groups()
|
|
36
|
+
|
|
37
|
+
if pre_full:
|
|
38
|
+
|
|
39
|
+
if pre_tag2:
|
|
40
|
+
pre_num = int(pre_num2)
|
|
41
|
+
pre_tag_full = TAG_VERSION_MAP[pre_tag2]
|
|
42
|
+
else:
|
|
43
|
+
pre_num = int(pre_num1)
|
|
44
|
+
pre_tag_full = (
|
|
45
|
+
TAG_VERSION_MAP[pre_full[0]]
|
|
46
|
+
if pre_full.startswith(('a', 'b')) else
|
|
47
|
+
TAG_VERSION_MAP['rc']
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
else:
|
|
51
|
+
pre_tag_full = pre_num = None
|
|
52
|
+
|
|
53
|
+
global version_info
|
|
54
|
+
version_info = pys_sys.version_info = tuple.__new__(
|
|
55
|
+
cls,
|
|
56
|
+
(
|
|
57
|
+
int(major), int(minor), int(micro), pre_tag_full, pre_num
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
return version_info
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def major(self) -> int:
|
|
64
|
+
return self[0]
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def minor(self) -> int:
|
|
68
|
+
return self[1]
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def micro(self) -> int:
|
|
72
|
+
return self[2]
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def pre_tag(self) -> str | None:
|
|
76
|
+
return self[3]
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def pre_num(self) -> int | None:
|
|
80
|
+
return self[4]
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def release(self) -> tuple[int, int, int]:
|
|
84
|
+
return self[0:3]
|
|
85
|
+
|
|
86
|
+
def __lt__(self, other: tuple) -> bool:
|
|
87
|
+
return self.release < other
|
|
88
|
+
|
|
89
|
+
def __gt__(self, other: tuple) -> bool:
|
|
90
|
+
return self.release > other
|
|
91
|
+
|
|
92
|
+
def __le__(self, other: tuple) -> bool:
|
|
93
|
+
return self.release <= other
|
|
94
|
+
|
|
95
|
+
def __ge__(self, other: tuple) -> bool:
|
|
96
|
+
return self.release >= other
|
|
97
|
+
|
|
98
|
+
def __eq__(self, other: tuple) -> bool:
|
|
99
|
+
return self.release == other
|
|
100
|
+
|
|
101
|
+
def __ne__(self, other: tuple) -> bool:
|
|
102
|
+
return self.release != other
|
|
103
|
+
|
|
104
|
+
def __repr__(self) -> str:
|
|
105
|
+
return (
|
|
106
|
+
'VersionInfo('
|
|
107
|
+
f'major={self.major!r}, '
|
|
108
|
+
f'minor={self.minor!r}, '
|
|
109
|
+
f'micro={self.micro!r}' +
|
|
110
|
+
(
|
|
111
|
+
''
|
|
112
|
+
if self.pre_tag is None else
|
|
113
|
+
', '
|
|
114
|
+
f'pre_tag={self.pre_tag!r}, '
|
|
115
|
+
f'pre_num={self.pre_num!r}'
|
|
116
|
+
) +
|
|
117
|
+
')'
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
PysVersionInfo()
|
pyscript/lib/ansi.pys
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from parser import DEFAULT, ast as parse
|
|
2
|
+
from ast_dump import dump
|
|
3
|
+
from ast_literal_eval import visit as _visit_literal_eval
|
|
4
|
+
from ast_unparse import unparse
|
|
5
|
+
from ast_walk import walk
|
|
6
|
+
from _pyscript import nodes
|
|
7
|
+
|
|
8
|
+
func literal_eval(node_or_string, flags=DEFAULT)
|
|
9
|
+
return _visit_literal_eval(parse(node_or_string, mode='eval', flags=flags))
|
|
10
|
+
|
|
11
|
+
Node = nodes.PysNode
|
|
12
|
+
|
|
13
|
+
allNodes = []
|
|
14
|
+
|
|
15
|
+
locals().update(
|
|
16
|
+
comprehension(
|
|
17
|
+
Node.__subclasses__(),
|
|
18
|
+
func(cls) {
|
|
19
|
+
name = cls.__name__
|
|
20
|
+
nodeName = name.removeprefix('Pys')
|
|
21
|
+
allNodes.append(nodeName)
|
|
22
|
+
return nodeName, getattr(nodes, name)
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
__all__ = (
|
|
28
|
+
'parse',
|
|
29
|
+
'dump',
|
|
30
|
+
'literal_eval',
|
|
31
|
+
'unparse',
|
|
32
|
+
'walk',
|
|
33
|
+
'Node'
|
|
34
|
+
) + tuple(allNodes)
|
|
35
|
+
|
|
36
|
+
del allNodes, nodes
|