pyscript-programming-language 1.13.4__tar.gz → 1.15.0.dev1__tar.gz

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.
Files changed (98) hide show
  1. {pyscript_programming_language-1.13.4/pyscript_programming_language.egg-info → pyscript_programming_language-1.15.0.dev1}/PKG-INFO +32 -29
  2. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/README.md +31 -28
  3. pyscript_programming_language-1.15.0.dev1/changelog.md +30 -0
  4. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyproject.toml +1 -1
  5. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/__init__.py +2 -1
  6. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/__init__.pyi +1 -0
  7. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/__main__.py +87 -48
  8. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/analyzer.py +31 -40
  9. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/buffer.py +6 -10
  10. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/cache.py +4 -3
  11. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/checks.py +5 -21
  12. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/constants.py +2 -2
  13. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/context.py +7 -10
  14. pyscript_programming_language-1.15.0.dev1/pyscript/core/editor/__init__.py +31 -0
  15. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/editor/bases.py +16 -16
  16. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/editor/gui.py +110 -28
  17. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/editor/terminal.py +17 -4
  18. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/exceptions.py +8 -13
  19. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/handlers.py +34 -32
  20. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/highlight.py +23 -3
  21. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/interpreter.py +58 -65
  22. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/lexer.py +51 -52
  23. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/mapping.py +11 -8
  24. pyscript_programming_language-1.15.0.dev1/pyscript/core/nodes.py +885 -0
  25. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/parser.py +236 -246
  26. pyscript_programming_language-1.15.0.dev1/pyscript/core/position.py +120 -0
  27. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/pysbuiltins.py +41 -81
  28. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/pystypes.py +66 -13
  29. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/results.py +2 -2
  30. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/runner.py +5 -5
  31. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/shell.py +50 -73
  32. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/symtab.py +14 -15
  33. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/token.py +3 -4
  34. pyscript_programming_language-1.15.0.dev1/pyscript/core/utils/ansi.py +176 -0
  35. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/utils/debug.py +18 -5
  36. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/utils/decorators.py +8 -8
  37. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/utils/generic.py +19 -3
  38. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/utils/module.py +6 -3
  39. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/utils/similarity.py +8 -6
  40. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/utils/string.py +8 -13
  41. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/version.py +2 -2
  42. pyscript_programming_language-1.15.0.dev1/pyscript/lib/ansi.pys +1 -0
  43. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/ast/ast_dump.py +20 -32
  44. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/ast/ast_literal_eval.py +5 -12
  45. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/ast/ast_unparse.py +10 -10
  46. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/ast/ast_walk.py +20 -26
  47. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/brainfuck.pys +10 -8
  48. pyscript_programming_language-1.15.0.dev1/pyscript/lib/dual/__init__.pys +17 -0
  49. pyscript_programming_language-1.15.0.dev1/pyscript/lib/dual/py_dual.py +246 -0
  50. pyscript_programming_language-1.15.0.dev1/pyscript/lib/getch/__init__.pys +10 -0
  51. pyscript_programming_language-1.15.0.dev1/pyscript/lib/getch/py_getch.py +99 -0
  52. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/history.pys +10 -8
  53. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/inspect.pys +1 -1
  54. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/parser.pys +6 -4
  55. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1/pyscript_programming_language.egg-info}/PKG-INFO +32 -29
  56. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript_programming_language.egg-info/SOURCES.txt +2 -1
  57. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/setup.py +2 -2
  58. pyscript_programming_language-1.13.4/changelog.md +0 -20
  59. pyscript_programming_language-1.13.4/pyscript/core/editor/__init__.py +0 -15
  60. pyscript_programming_language-1.13.4/pyscript/core/nodes.py +0 -673
  61. pyscript_programming_language-1.13.4/pyscript/core/position.py +0 -115
  62. pyscript_programming_language-1.13.4/pyscript/core/utils/ansi.py +0 -129
  63. pyscript_programming_language-1.13.4/pyscript/lib/ansi.pys +0 -14
  64. pyscript_programming_language-1.13.4/pyscript/lib/getch/__init__.pys +0 -5
  65. pyscript_programming_language-1.13.4/pyscript/lib/getch/py_getch.py +0 -18
  66. pyscript_programming_language-1.13.4/pyscript/site-packages/anniversary.pys +0 -4
  67. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/MANIFEST.in +0 -0
  68. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/__init__.py +0 -0
  69. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/bases.py +0 -0
  70. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/utils/__init__.py +0 -0
  71. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/core/utils/path.py +0 -0
  72. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/__hello__.pys +0 -0
  73. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/ast/__init__.pys +0 -0
  74. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/code.pys +0 -0
  75. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/dis.pys +0 -0
  76. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/explorer.pys +0 -0
  77. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/fpstimer/__init__.pys +0 -0
  78. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/fpstimer/py_fpstimer.py +0 -0
  79. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/jsdict.pys +0 -0
  80. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/keyword.pys +0 -0
  81. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/opcode.pys +0 -0
  82. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/pdisplay.pys +0 -0
  83. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/site.pys +0 -0
  84. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/symtable.pys +0 -0
  85. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/token.pys +0 -0
  86. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/tokenize/__init__.pys +0 -0
  87. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/lib/tokenize/tok_untokenize.py +0 -0
  88. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/other/.nomedia +0 -0
  89. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/other/PyScript.ico +0 -0
  90. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/other/copyright +0 -0
  91. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/other/credits +0 -0
  92. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/other/license +0 -0
  93. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/site-packages/this.pys +0 -0
  94. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript/this.py +0 -0
  95. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript_programming_language.egg-info/dependency_links.txt +0 -0
  96. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript_programming_language.egg-info/requires.txt +0 -0
  97. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/pyscript_programming_language.egg-info/top_level.txt +0 -0
  98. {pyscript_programming_language-1.13.4 → pyscript_programming_language-1.15.0.dev1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyscript-programming-language
3
- Version: 1.13.4
3
+ Version: 1.15.0.dev1
4
4
  Summary: PyScript Programming Language
5
5
  Home-page: https://azzammuhyala.github.io/pyscript
6
6
  Author: AzzamMuhyala
@@ -107,41 +107,44 @@ Familiar? There it is!
107
107
  | 2 | `builtins` | **required** |
108
108
  | 3 | `cmath` | **required** |
109
109
  | 4 | `collections.abc` | **required** |
110
- | 5 | `functools` | **required** |
111
- | 6 | `html` | **required** |
112
- | 7 | `importlib` | **required** |
113
- | 8 | `inspect` | **required** |
114
- | 9 | `io` | **required** |
115
- | 10 | `itertools` | **required** |
116
- | 11 | `json` | **required** |
117
- | 12 | `operator` | **required** |
118
- | 13 | `os` | **required** |
119
- | 14 | `re` | **required** |
120
- | 15 | `subprocess` | **required** |
121
- | 16 | `sys` | **required** |
122
- | 17 | `threading` | **required** |
123
- | 18 | `types` | **required** |
124
- | 19 | `typing` | **required** |
125
- | 20 | `unicodedata` | **required** |
110
+ | 5 | `difflib` | **required** |
111
+ | 6 | `functools` | **required** |
112
+ | 7 | `html` | **required** |
113
+ | 8 | `importlib` | **required** |
114
+ | 9 | `inspect` | **required** |
115
+ | 10 | `io` | **required** |
116
+ | 11 | `itertools` | **required** |
117
+ | 12 | `json` | **required** |
118
+ | 13 | `operator` | **required** |
119
+ | 14 | `os` | **required** |
120
+ | 15 | `pkgutil` | **required** |
121
+ | 16 | `re` | **required** |
122
+ | 17 | `subprocess` | **required** |
123
+ | 18 | `sys` | **required** |
124
+ | 19 | `types` | **required** |
125
+ | 20 | `typing` | **required** |
126
+ | 21 | `unicodedata` | **required** |
126
127
  | 1 | `ast` | **required (library)** |
127
128
  | 2 | `msvcrt` | **required (library)** |
128
129
  | 3 | `pprint` | **required (library)** |
129
130
  | 4 | `shutil` | **required (library)** |
130
- | 5 | `stat` | **required (library)** |
131
- | 6 | `termios` | **required (library)** |
132
- | 7 | `time` | **required (library)** |
133
- | 8 | `tty` | **required (library)** |
134
- | 1 | `beartype` | **optional** |
135
- | 2 | `prompt_toolkit` | **optional** |
136
- | 3 | `pygments` | **optional** |
137
- | 4 | `readline` | **optional** |
138
- | 5 | `tkinter` | **optional** |
139
- | 6 | `IPython` | **optional** |
131
+ | 5 | `signal` | **required (library)** |
132
+ | 6 | `stat` | **required (library)** |
133
+ | 7 | `termios` | **required (library)** |
134
+ | 8 | `time` | **required (library)** |
135
+ | 9 | `tty` | **required (library)** |
136
+ | 1 | `_colorize` | **optional** |
137
+ | 2 | `beartype` | **optional** |
138
+ | 3 | `prompt_toolkit` | **optional** |
139
+ | 4 | `pygments` | **optional** |
140
+ | 5 | `readline` | **optional** |
141
+ | 6 | `threading` | **optional** |
142
+ | 7 | `tkinter` | **optional** |
143
+ | 8 | `IPython` | **optional** |
140
144
 
141
145
  ### Status Explanation
142
146
  - **required**: Required by PyScript entirely.
143
- - **required (library)**: Required PyScript library (located in `pyscript/lib`). PyScript is not affected unless you
144
- import it.
147
+ - **required (library)**: Required by PyScript optional library. PyScript is not affected, unless you import it.
145
148
  - **optional**: Not required, but if it is present, some features can be used without issue.
146
149
 
147
150
  ## Highlights 🎨
@@ -75,41 +75,44 @@ Familiar? There it is!
75
75
  | 2 | `builtins` | **required** |
76
76
  | 3 | `cmath` | **required** |
77
77
  | 4 | `collections.abc` | **required** |
78
- | 5 | `functools` | **required** |
79
- | 6 | `html` | **required** |
80
- | 7 | `importlib` | **required** |
81
- | 8 | `inspect` | **required** |
82
- | 9 | `io` | **required** |
83
- | 10 | `itertools` | **required** |
84
- | 11 | `json` | **required** |
85
- | 12 | `operator` | **required** |
86
- | 13 | `os` | **required** |
87
- | 14 | `re` | **required** |
88
- | 15 | `subprocess` | **required** |
89
- | 16 | `sys` | **required** |
90
- | 17 | `threading` | **required** |
91
- | 18 | `types` | **required** |
92
- | 19 | `typing` | **required** |
93
- | 20 | `unicodedata` | **required** |
78
+ | 5 | `difflib` | **required** |
79
+ | 6 | `functools` | **required** |
80
+ | 7 | `html` | **required** |
81
+ | 8 | `importlib` | **required** |
82
+ | 9 | `inspect` | **required** |
83
+ | 10 | `io` | **required** |
84
+ | 11 | `itertools` | **required** |
85
+ | 12 | `json` | **required** |
86
+ | 13 | `operator` | **required** |
87
+ | 14 | `os` | **required** |
88
+ | 15 | `pkgutil` | **required** |
89
+ | 16 | `re` | **required** |
90
+ | 17 | `subprocess` | **required** |
91
+ | 18 | `sys` | **required** |
92
+ | 19 | `types` | **required** |
93
+ | 20 | `typing` | **required** |
94
+ | 21 | `unicodedata` | **required** |
94
95
  | 1 | `ast` | **required (library)** |
95
96
  | 2 | `msvcrt` | **required (library)** |
96
97
  | 3 | `pprint` | **required (library)** |
97
98
  | 4 | `shutil` | **required (library)** |
98
- | 5 | `stat` | **required (library)** |
99
- | 6 | `termios` | **required (library)** |
100
- | 7 | `time` | **required (library)** |
101
- | 8 | `tty` | **required (library)** |
102
- | 1 | `beartype` | **optional** |
103
- | 2 | `prompt_toolkit` | **optional** |
104
- | 3 | `pygments` | **optional** |
105
- | 4 | `readline` | **optional** |
106
- | 5 | `tkinter` | **optional** |
107
- | 6 | `IPython` | **optional** |
99
+ | 5 | `signal` | **required (library)** |
100
+ | 6 | `stat` | **required (library)** |
101
+ | 7 | `termios` | **required (library)** |
102
+ | 8 | `time` | **required (library)** |
103
+ | 9 | `tty` | **required (library)** |
104
+ | 1 | `_colorize` | **optional** |
105
+ | 2 | `beartype` | **optional** |
106
+ | 3 | `prompt_toolkit` | **optional** |
107
+ | 4 | `pygments` | **optional** |
108
+ | 5 | `readline` | **optional** |
109
+ | 6 | `threading` | **optional** |
110
+ | 7 | `tkinter` | **optional** |
111
+ | 8 | `IPython` | **optional** |
108
112
 
109
113
  ### Status Explanation
110
114
  - **required**: Required by PyScript entirely.
111
- - **required (library)**: Required PyScript library (located in `pyscript/lib`). PyScript is not affected unless you
112
- import it.
115
+ - **required (library)**: Required by PyScript optional library. PyScript is not affected, unless you import it.
113
116
  - **optional**: Not required, but if it is present, some features can be used without issue.
114
117
 
115
118
  ## Highlights 🎨
@@ -0,0 +1,30 @@
1
+ # Change Logs
2
+
3
+ ## [1.15.0.dev1] - 19/10/2026
4
+
5
+ ### Added
6
+ - Added line number display to each editor mode.
7
+ - In `gui` editor mode, the system now attempts to locate the best available monospace font; a 500ms delay has also been
8
+ introduced before updating syntax highlighting to improve performance.
9
+ - The `getch` module now includes `init()`, `quit()`, `kbhit()`, `getwch()`, and `getach()`. Calling `getch()` requires
10
+ an initial call to `init()`, followed by `quit()` upon completion to restore the terminal to its original state.
11
+ - Added color-coding for opening and closing delimiters in Pygments syntax highlighting.
12
+ - Added the `intern_object` function to `pys_sys`.
13
+ - `history.load()` now returns entries ordered from oldest to newest (retrieved from the cache).
14
+ - `PysPrinter` is now a subclass of `PysObject` and is recognized as a function by `inspect.isfunction()`
15
+ (PyScript’s `inspect` module).
16
+ - Added support for constant folding and AST optimizations.
17
+ - Introduced `PysConstantNode` to store constant values ​​directly.
18
+ - Added the `dual` library in `lib/`
19
+ (representing dual numbers: $a + b\epsilon$, where $\epsilon^2 = 0$ and $\epsilon \ne 0$).
20
+ - _etc._
21
+
22
+ ### Fixed
23
+ - Fixed several bugs.
24
+ - Limited the maximum number of stored history entries to 1024 to optimize history file read/write operations.
25
+ - Renamed the environment variable `PYSCRIPT_MAXIMUM_LINE_HISTORY` to `PYSCRIPT_HISTORY_LIMIT`.
26
+ - _etc._
27
+
28
+ ### Removed
29
+ - Removed `PysNumberNode`, `PysStringNode`, and `PysKeywordNode`, which have been replaced by `PysConstantNode`.
30
+ - _etc._
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyscript-programming-language"
7
- version = "1.13.4"
7
+ version = "1.15.0.dev1"
8
8
  description = "PyScript Programming Language"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.10"
@@ -12,7 +12,7 @@ from .core.constants import (
12
12
  DEFAULT, NO_COLOR, NO_WARNING, SILENT, DEBUG, RETURN_RESULT, DONT_SHOW_BANNER_ON_SHELL, CLASSIC_LINE_SHELL,
13
13
  NO_COLOR_PROMPT, NOTEBOOK, LEXER_HIGHLIGHT, DICT_TO_JSDICT
14
14
  )
15
- from .core.cache import undefined
15
+ from .core.cache import pys_sys, undefined
16
16
  from .core.highlight import (
17
17
  HLFMT_HTML, HLFMT_ANSI, HLFMT_BBCODE, pys_highlight, PygmentsPyScriptStyle, PygmentsPyScriptLexer,
18
18
  PygmentsPyScriptShellLexer
@@ -38,6 +38,7 @@ __all__ = (
38
38
  'HLFMT_ANSI',
39
39
  'HLFMT_BBCODE',
40
40
  'undefined',
41
+ 'pys_sys',
41
42
  'version',
42
43
  'version_info',
43
44
  'pys_highlight',
@@ -37,6 +37,7 @@ HLFMT_HTML: PysHighlightFormatter
37
37
  HLFMT_ANSI: PysHighlightFormatter
38
38
  HLFMT_BBCODE: PysHighlightFormatter
39
39
 
40
+ pys_sys: ModuleType
40
41
  undefined: PysUndefined
41
42
  version: str
42
43
  version_info: PysVersionInfo
@@ -4,8 +4,7 @@ from .core.constants import (
4
4
  ENV_PYSCRIPT_NO_COLOR_PROMPT, ENV_PYSCRIPT_CLASSIC_LINE_SHELL, DEFAULT, NO_COLOR, NO_WARNING, DEBUG,
5
5
  DONT_SHOW_BANNER_ON_SHELL, CLASSIC_LINE_SHELL, NO_COLOR_PROMPT, NOTEBOOK
6
6
  )
7
- from .core.editor.gui import PysGUIEditor, GUI_SUPPORT
8
- from .core.editor.terminal import PysTerminalEditor, TERMINAL_SUPPORT
7
+ from .core import editor
9
8
  from .core.highlight import (
10
9
  PYGMENTS, HLFMT_HTML, HLFMT_ANSI, HLFMT_BBCODE, pys_highlight, PygmentsPyScriptStyle, PygmentsPyScriptLexer
11
10
  )
@@ -33,24 +32,29 @@ if PYGMENTS:
33
32
  }
34
33
 
35
34
  from argparse import OPTIONAL, REMAINDER, ArgumentParser
35
+ from re import compile as compile_regex
36
36
 
37
37
  import sys
38
38
 
39
+ if sys.version_info >= (3, 13):
40
+ try:
41
+ from _colorize import can_colorize
42
+ COLORIZE = can_colorize()
43
+ except:
44
+ # respect for NO_COLOR, see more here: https://no-color.org
45
+ COLORIZE = not is_environ('NO_COLOR')
46
+ else:
47
+ COLORIZE = True
48
+
39
49
  FORMATER_HIGHLIGHT_MAP = {
40
50
  'html': HLFMT_HTML,
41
51
  'ansi': HLFMT_ANSI,
42
52
  'bbcode': HLFMT_BBCODE
43
53
  }
44
54
 
45
- EDITOR_MAP = {
46
- name: cls
47
- for support, name, cls in [
48
- (GUI_SUPPORT, 'gui', PysGUIEditor),
49
- (TERMINAL_SUPPORT, 'terminal', PysTerminalEditor)
50
- ] if support
51
- }
52
-
53
- arguments_requiring_value = {'-l', '--highlight', '-r', '--py-recursion'}
55
+ editors = tuple(editor for editor in editor.__all__ if editor != 'bases')
56
+ arguments_requiring_argv = {'-c', '--command', '-m', '--module'}
57
+ arguments_requiring_value = {'-e', '--editor', '-l', '--highlight', '-r', '--py-recursion'}
54
58
 
55
59
  parser = ArgumentParser(
56
60
  prog=f'{base(sys.executable)} -m pyscript',
@@ -77,14 +81,12 @@ parser.add_argument(
77
81
  help="set a debug flag, this will ignore assert statement. Check the flag is active with the __debug__ keyword"
78
82
  )
79
83
 
80
- if EDITOR_MAP:
81
- parser.add_argument(
82
- '-e', '--editor',
83
- choices=tuple(EDITOR_MAP.keys()),
84
- default=None,
85
- help="open the editor panel from a 'file'",
86
- )
87
- arguments_requiring_value.update({'-e', '--editor'})
84
+ parser.add_argument(
85
+ '-e', '--editor',
86
+ choices=editors,
87
+ default=None,
88
+ help="open the editor panel from a 'file'",
89
+ )
88
90
 
89
91
  parser.add_argument(
90
92
  '-i', '--inspect',
@@ -185,23 +187,27 @@ argv = sys.argv[1:]
185
187
  argc = len(argv)
186
188
  index = 0
187
189
  arg_index = -1
190
+ parser_color = COLORIZE
188
191
 
189
192
  while index < argc:
190
193
  arg = argv[index]
191
- if not arg.startswith('-') or arg == '--':
192
- break
193
194
 
194
- if arg in ('-c', '--command'):
195
- arg_index = index + 2
195
+ if not arg.startswith('-') or arg == '--':
196
196
  break
197
- elif arg in ('-m', '--module'):
197
+ elif arg in arguments_requiring_argv:
198
198
  arg_index = index + 2
199
199
  break
200
+ elif arg in ('-n', '--no-color'):
201
+ parser_color = False
200
202
 
201
203
  index += 1
202
204
  if arg in arguments_requiring_value:
203
205
  index += 1
204
206
 
207
+ if sys.version_info >= (3, 14):
208
+ parser.color = parser_color
209
+ parser.suggest_on_error = True
210
+
205
211
  args = parser.parse_args(argv if arg_index == -1 else argv[:arg_index])
206
212
  arg = args.arg if arg_index == -1 else argv[arg_index:]
207
213
 
@@ -226,7 +232,7 @@ if args.terminal:
226
232
  pass
227
233
 
228
234
  if args.file is None:
229
- if EDITOR_MAP and args.editor:
235
+ if args.editor:
230
236
  argument_error('-e/--editor', "argument 'file' is required")
231
237
  elif args.highlight:
232
238
  argument_error('-l/--highlight', "argument 'file' is required")
@@ -237,13 +243,17 @@ if args.py_recursion is not None:
237
243
  except BaseException as e:
238
244
  argument_error('-r/--py-recursion', e)
239
245
 
246
+ if args.P:
247
+ for cwd in {'', '.', getcwd()}:
248
+ remove_python_path(cwd)
249
+
240
250
  code = 0
241
251
  flags = DEFAULT
242
252
 
243
253
  for condition, flag in [
244
254
  (args.notebook or USE_NOTEBOOK, NOTEBOOK),
245
255
  (args.classic_line_shell or is_environ(ENV_PYSCRIPT_CLASSIC_LINE_SHELL), CLASSIC_LINE_SHELL),
246
- (args.no_color or is_environ('NO_COLOR'), NO_COLOR),
256
+ (args.no_color or not COLORIZE, NO_COLOR),
247
257
  (args.no_color_prompt or is_environ(ENV_PYSCRIPT_NO_COLOR_PROMPT), NO_COLOR_PROMPT),
248
258
  (args.debug, DEBUG),
249
259
  (args.no_warning, NO_WARNING),
@@ -252,52 +262,78 @@ for condition, flag in [
252
262
  if condition:
253
263
  flags |= flag
254
264
 
255
- if args.P:
256
- for cwd in {'', '.', getcwd()}:
257
- remove_python_path(cwd)
258
-
259
265
  pys_sys.argv = argv = ['', *arg]
260
266
 
261
267
  def clean_up() -> None:
262
268
  g = globals()
263
269
 
264
270
  for name in {
265
- 'ArgumentParser', 'BBCodeFormatter', 'CLASSIC_LINE_SHELL', 'DEBUG', 'DEFAULT', 'EDITOR_MAP',
266
- 'ENV_PYSCRIPT_CLASSIC_LINE_SHELL', 'ENV_PYSCRIPT_NO_COLOR_PROMPT', 'FORMATER_HIGHLIGHT_MAP',
267
- 'FORMATER_PYGMENTS_MAP', 'GUI_SUPPORT', 'HLFMT_ANSI', 'HLFMT_BBCODE', 'HLFMT_HTML', 'HtmlFormatter',
268
- 'LatexFormatter', 'NOTEBOOK', 'NO_COLOR', 'NO_WARNING', 'NO_COLOR_PROMPT', 'OPTIONAL', 'PYGMENTS',
269
- 'PygmentsPyScriptLexer', 'PygmentsPyScriptStyle', 'PysFileBuffer', 'PysGUIEditor', 'PysTerminalEditor',
270
- 'REMAINDER', 'TERMINAL_SUPPORT', 'Terminal256Formatter', 'TerminalFormatter', 'TerminalTrueColorFormatter',
271
- 'USE_NOTEBOOK', '__version__', '_namespace_to_symbol_table', 'arg', 'arg_index', 'argc', 'args',
271
+ 'ArgumentParser', 'BBCodeFormatter', 'CLASSIC_LINE_SHELL', 'DEBUG', 'DEFAULT', 'i', 'index', 'is_environ', 'fd',
272
+ 'kernel32', 'ENV_PYSCRIPT_CLASSIC_LINE_SHELL', 'ENV_PYSCRIPT_NO_COLOR_PROMPT', 'FORMATER_HIGHLIGHT_MAP', 'arg',
273
+ 'FORMATER_PYGMENTS_MAP', 'HLFMT_ANSI', 'HLFMT_BBCODE', 'HLFMT_HTML', 'HtmlFormatter', 'OPTIONAL', 'PYGMENTS',
274
+ 'LatexFormatter', 'NOTEBOOK', 'NO_COLOR', 'NO_WARNING', 'NO_COLOR_PROMPT', 'PygmentsPyScriptLexer', 'args',
275
+ 'PygmentsPyScriptStyle', 'PysFileBuffer', 'REMAINDER', 'Terminal256Formatter', 'TerminalFormatter', 'flag',
276
+ 'TerminalTrueColorFormatter', 'USE_NOTEBOOK', '__version__', '_namespace_to_symbol_table', 'arg_index', 'argc',
272
277
  'argument_error', 'arguments_requiring_value', 'argv', 'base', 'clean_up', 'condition', 'ctypes', 'execute',
273
- 'fd', 'file', 'find_module_path', 'flag', 'getcwd', 'highlight', 'i', 'index', 'is_environ', 'kernel32',
274
- 'load_file', 'module_path', 'parser', 'pys_highlight', 'pys_sys', 'remove_python_path'
278
+ 'file', 'find_module_path', 'getcwd', 'highlight', 'load_editor_module', 'load_file', 'module_path', 'parser',
279
+ 'pys_highlight', 'pys_sys', 'remove_python_path', 'editors', 'editor', 'compile_regex', 'can_colorize',
280
+ 'arguments_requiring_argv', 'COLORIZE', 'parser_color'
275
281
  }:
276
282
  try:
277
283
  del g[name]
278
284
  except:
279
285
  continue
280
286
 
287
+ def load_editor_module(name: str) -> tuple[type | None, bool]:
288
+ if name not in editors:
289
+ return None, False
290
+
291
+ module = getattr(editor, name, None)
292
+ if module is None:
293
+ return None, False
294
+
295
+ class_name = compile_regex(r'Pys[A-Za-z0-9_]+Editor').fullmatch
296
+ support_name = compile_regex(r'[A-Z0-9_]+_SUPPORT').fullmatch
297
+
298
+ cls = None
299
+ support = None
300
+ for name in dir(module):
301
+ if not (cls is None or support is None):
302
+ break
303
+ elif class_name(name) and cls is None:
304
+ cls = getattr(module, name)
305
+ elif support_name(name) and support is None:
306
+ support = getattr(module, name)
307
+ else:
308
+ return None, False
309
+
310
+ return cls, support
311
+
281
312
  def load_file(path) -> PysFileBuffer:
282
313
  normalized = normpath(path)
314
+
315
+ def open_error(message: str) -> None:
316
+ argument_error('file', f"can't open file \"{normalized}\": {message}")
317
+
283
318
  try:
284
319
  with open(normalized, 'r', encoding=pys_sys.encoding) as file:
285
320
  return PysFileBuffer(file, normalized)
286
321
  except FileNotFoundError:
287
- if not (EDITOR_MAP and args.editor):
288
- argument_error('file', f"can't open file \"{normalized}\": No such file or directory")
322
+ if not args.editor:
323
+ open_error("No such file or directory")
289
324
  except PermissionError:
290
- argument_error('file', f"can't open file \"{normalized}\": Permission denied")
325
+ open_error("Permission denied")
291
326
  except IsADirectoryError:
292
- argument_error('file', f"can't open file \"{normalized}\": Path is not a file")
327
+ open_error("Path is not a file")
293
328
  except NotADirectoryError:
294
- argument_error('file', f"can't open file \"{normalized}\": Attempting to access directory from file")
329
+ open_error("Attempting to access directory from file")
295
330
  except (OSError, IOError):
296
- argument_error('file', f"can't open file \"{normalized}\": Attempting to access a system directory or file")
331
+ open_error("Attempting to access a system directory or file")
297
332
  except UnicodeDecodeError:
298
- argument_error('file', f"can't read file \"{normalized}\": Bad file")
333
+ open_error("Bad file")
299
334
  except BaseException as e:
300
335
  argument_error('file', f"file \"{normalized}\": Unexpected error: {e}")
336
+
301
337
  return PysFileBuffer('', path)
302
338
 
303
339
  def execute(file: PysFileBuffer) -> None:
@@ -334,9 +370,12 @@ if args.file is not None:
334
370
  argv[0] = args.file
335
371
  file = load_file(args.file)
336
372
 
337
- if EDITOR_MAP and args.editor:
373
+ if args.editor:
374
+ cls, supported = load_editor_module(args.editor)
375
+ if not supported:
376
+ argument_error('-e/--editor', f"'{args.editor}' mode not supported")
338
377
  try:
339
- EDITOR_MAP[args.editor](file=file, colored=not (flags & NO_COLOR)).run()
378
+ cls(file, colored=not (flags & NO_COLOR)).run()
340
379
  except BaseException as e:
341
380
  argument_error('-e/--editor', e)
342
381
 
@@ -102,18 +102,17 @@ class PysAnalyzer(Pys):
102
102
 
103
103
  keyword_names = set()
104
104
 
105
- for element in node.arguments:
105
+ for argument in node.arguments:
106
106
 
107
- if element.__class__ is tuple:
108
- token, value = element
107
+ if argument.__class__ is tuple:
108
+ token, value = argument
109
109
  name = token.value
110
110
  if name in keyword_names:
111
111
  self.throw(f"duplicate argument {name!r} in call definition", token.position)
112
112
  return
113
113
  keyword_names.add(name)
114
-
115
114
  else:
116
- value = element
115
+ value = argument
117
116
 
118
117
  self.visit(value)
119
118
  if self.error:
@@ -163,7 +162,7 @@ class PysAnalyzer(Pys):
163
162
  self.visit_declaration_from_AssignmentNode(node.target, f"cannot {operator} literal", operator)
164
163
 
165
164
  def visit_StatementsNode(self, node: PysStatementsNode) -> None:
166
- for element in node.body:
165
+ for element in node.elements:
167
166
  self.visit(element)
168
167
  if self.error:
169
168
  return
@@ -179,7 +178,7 @@ class PysAnalyzer(Pys):
179
178
  self.visit(node.value)
180
179
 
181
180
  def visit_IfNode(self, node: PysIfNode) -> None:
182
- for condition, body in node.cases_body:
181
+ for condition, body in node.cases:
183
182
  self.visit(condition)
184
183
  if self.error:
185
184
  return
@@ -188,8 +187,8 @@ class PysAnalyzer(Pys):
188
187
  if self.error:
189
188
  return
190
189
 
191
- if node.else_body:
192
- self.visit(node.else_body)
190
+ if node.else_:
191
+ self.visit(node.else_)
193
192
 
194
193
  def visit_SwitchNode(self, node: PysSwitchNode) -> None:
195
194
  self.visit(node.target)
@@ -198,8 +197,8 @@ class PysAnalyzer(Pys):
198
197
 
199
198
  self.in_switch += 1
200
199
 
201
- for condition, body in node.case_cases:
202
- self.visit(condition)
200
+ for case, body in node.cases:
201
+ self.visit(case)
203
202
  if self.error:
204
203
  return
205
204
 
@@ -207,8 +206,8 @@ class PysAnalyzer(Pys):
207
206
  if self.error:
208
207
  return
209
208
 
210
- if node.default_body:
211
- self.visit(node.default_body)
209
+ if node.default:
210
+ self.visit(node.default)
212
211
  if self.error:
213
212
  return
214
213
 
@@ -220,8 +219,8 @@ class PysAnalyzer(Pys):
220
219
  if self.error:
221
220
  return
222
221
 
223
- for condition, value in node.cases:
224
- self.visit(condition)
222
+ for case, value in node.cases:
223
+ self.visit(case)
225
224
  if self.error:
226
225
  return
227
226
 
@@ -237,18 +236,18 @@ class PysAnalyzer(Pys):
237
236
  if self.error:
238
237
  return
239
238
 
240
- for _, body in node.catch_cases:
239
+ for _, body in node.catches:
241
240
  self.visit(body)
242
241
  if self.error:
243
242
  return
244
243
 
245
- if node.else_body:
246
- self.visit(node.else_body)
244
+ if node.else_:
245
+ self.visit(node.else_)
247
246
  if self.error:
248
247
  return
249
248
 
250
- if node.finally_body:
251
- self.visit(node.finally_body)
249
+ if node.finally_:
250
+ self.visit(node.finally_)
252
251
 
253
252
  def visit_WithNode(self, node: PysWithNode) -> None:
254
253
  for context, _ in node.contexts:
@@ -284,8 +283,8 @@ class PysAnalyzer(Pys):
284
283
 
285
284
  self.in_loop -= 1
286
285
 
287
- if node.else_body:
288
- self.visit(node.else_body)
286
+ if node.else_:
287
+ self.visit(node.else_)
289
288
 
290
289
  def visit_WhileNode(self, node: PysWhileNode) -> None:
291
290
  self.visit(node.condition)
@@ -300,8 +299,8 @@ class PysAnalyzer(Pys):
300
299
 
301
300
  self.in_loop -= 1
302
301
 
303
- if node.else_body:
304
- self.visit(node.else_body)
302
+ if node.else_:
303
+ self.visit(node.else_)
305
304
 
306
305
  def visit_DoWhileNode(self, node: PysDoWhileNode) -> None:
307
306
  self.in_loop += 1
@@ -316,11 +315,10 @@ class PysAnalyzer(Pys):
316
315
  if self.error:
317
316
  return
318
317
 
319
- if node.else_body:
320
- self.visit(node.else_body)
318
+ if node.else_:
319
+ self.visit(node.else_)
321
320
 
322
321
  def visit_RepeatNode(self, node: PysRepeatNode) -> None:
323
-
324
322
  if node.body:
325
323
  self.in_loop += 1
326
324
 
@@ -334,8 +332,8 @@ class PysAnalyzer(Pys):
334
332
  if self.error:
335
333
  return
336
334
 
337
- if node.else_body:
338
- self.visit(node.else_body)
335
+ if node.else_:
336
+ self.visit(node.else_)
339
337
 
340
338
  def visit_ClassNode(self, node: PysClassNode) -> None:
341
339
  for decorator in node.decorators:
@@ -378,9 +376,9 @@ class PysAnalyzer(Pys):
378
376
 
379
377
  parameter_names = set()
380
378
 
381
- for element in node.parameters:
382
- is_keyword = element.__class__ is tuple
383
- token = element[0] if is_keyword else element
379
+ for parameter in node.parameters:
380
+ is_keyword = parameter.__class__ is tuple
381
+ token = parameter[0] if is_keyword else parameter
384
382
  name = token.value
385
383
 
386
384
  if name in parameter_names:
@@ -389,7 +387,7 @@ class PysAnalyzer(Pys):
389
387
  parameter_names.add(name)
390
388
 
391
389
  if is_keyword:
392
- self.visit(element[1])
390
+ self.visit(parameter[1])
393
391
  if self.error:
394
392
  return
395
393
 
@@ -464,10 +462,6 @@ class PysAnalyzer(Pys):
464
462
  if self.error:
465
463
  return
466
464
 
467
- elif type is PysKeywordNode:
468
- self.throw(f"cannot delete {target.name.value}", target.position)
469
- return
470
-
471
465
  elif type is PysDebugNode:
472
466
  self.throw("cannot delete to __debug__", node.position)
473
467
  return
@@ -537,9 +531,6 @@ class PysAnalyzer(Pys):
537
531
  if self.error:
538
532
  return
539
533
 
540
- elif type is PysKeywordNode:
541
- self.throw(f"cannot {operator_name} to {node.name.value}", node.position)
542
-
543
534
  elif type is PysDebugNode:
544
535
  self.throw(f"cannot {operator_name} to __debug__", node.position)
545
536