pyscript-programming-language 1.8.1__tar.gz → 1.9.0__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 (72) hide show
  1. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/PKG-INFO +1 -1
  2. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/__init__.py +7 -5
  3. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/__init__.pyi +9 -7
  4. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/__init__.py +1 -1
  5. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/analyzer.py +23 -12
  6. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/buffer.py +6 -1
  7. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/cache.py +16 -15
  8. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/checks.py +1 -1
  9. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/constants.py +5 -3
  10. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/context.py +21 -14
  11. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/exceptions.py +20 -5
  12. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/highlight.py +34 -10
  13. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/interpreter.py +3 -4
  14. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/mapping.py +3 -1
  15. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/nodes.py +48 -41
  16. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/objects.py +6 -1
  17. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/parser.py +39 -14
  18. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/pysbuiltins.py +66 -52
  19. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/runner.py +3 -3
  20. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/symtab.py +3 -9
  21. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/token.py +6 -14
  22. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/ansi.py +8 -6
  23. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/string.py +3 -3
  24. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/version.py +3 -4
  25. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/ast/__init__.pys +6 -7
  26. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/ast/ast_dump.py +2 -1
  27. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/ast/ast_unparse.py +7 -5
  28. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/explorer.pys +38 -70
  29. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/jsdict.pys +4 -7
  30. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript_programming_language.egg-info/PKG-INFO +1 -1
  31. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/setup.py +1 -1
  32. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/MANIFEST.in +0 -0
  33. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/README.md +0 -0
  34. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/__main__.py +0 -0
  35. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/bases.py +0 -0
  36. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/handlers.py +0 -0
  37. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/lexer.py +0 -0
  38. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/position.py +0 -0
  39. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/results.py +0 -0
  40. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/__init__.py +0 -0
  41. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/debug.py +0 -0
  42. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/decorators.py +0 -0
  43. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/generic.py +0 -0
  44. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/module.py +0 -0
  45. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/path.py +0 -0
  46. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/shell.py +0 -0
  47. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/core/utils/similarity.py +0 -0
  48. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/__hello__.pys +0 -0
  49. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/ansi.pys +0 -0
  50. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/ast/ast_literal_eval.py +0 -0
  51. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/ast/ast_walk.py +0 -0
  52. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/brainfuck.pys +0 -0
  53. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/dis.pys +0 -0
  54. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/fpstimer.pys +0 -0
  55. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/getch.pys +0 -0
  56. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/inspect.pys +0 -0
  57. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/keyword.pys +0 -0
  58. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/parser.pys +0 -0
  59. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/site.pys +0 -0
  60. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/symtable.pys +0 -0
  61. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/sys.pys +0 -0
  62. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/this.pys +0 -0
  63. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/token.pys +0 -0
  64. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/tokenize/__init__.pys +0 -0
  65. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/lib/tokenize/tok_untokenize.py +0 -0
  66. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/site-packages/67.pys +0 -0
  67. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript/this.py +0 -0
  68. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript_programming_language.egg-info/SOURCES.txt +0 -0
  69. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript_programming_language.egg-info/dependency_links.txt +0 -0
  70. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript_programming_language.egg-info/requires.txt +0 -0
  71. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/pyscript_programming_language.egg-info/top_level.txt +0 -0
  72. {pyscript_programming_language-1.8.1 → pyscript_programming_language-1.9.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyscript-programming-language
3
- Version: 1.8.1
3
+ Version: 1.9.0
4
4
  Summary: PyScript Programming Language
5
5
  Home-page: https://azzammuhyala.github.io/pyscript
6
6
  Author: azzammuhyala
@@ -1,5 +1,5 @@
1
1
  """
2
- PyScript is a programming language written in Python. \
2
+ PyScript is a programming language written 100% in Python. \
3
3
  This language is not isolated and is directly integrated with the Python's library and namespace levels.
4
4
  """
5
5
 
@@ -8,18 +8,18 @@ if __import__('sys').version_info < (3, 10):
8
8
 
9
9
  from . import core
10
10
 
11
- from .core.constants import DEFAULT, DEBUG, SILENT, RETRES, HIGHLIGHT, NO_COLOR, REVERSE_POW_XOR
12
- from .core.cache import undefined
11
+ from .core.constants import DEFAULT, DEBUG, SILENT, RETURN_RESULT, HIGHLIGHT, NO_COLOR, REVERSE_POW_XOR
12
+ from .core.cache import undefined, hook
13
13
  from .core.highlight import HLFMT_HTML, HLFMT_ANSI, HLFMT_BBCODE, pys_highlight, PygmentsPyScriptLexer
14
14
  from .core.runner import pys_exec, pys_eval, pys_require, pys_shell
15
- from .core.version import version_info, __version__, __date__
15
+ from .core.version import version, version_info, __version__, __date__
16
16
 
17
17
  __all__ = (
18
18
  'core',
19
19
  'DEFAULT',
20
20
  'DEBUG',
21
21
  'SILENT',
22
- 'RETRES',
22
+ 'RETURN_RESULT',
23
23
  'HIGHLIGHT',
24
24
  'NO_COLOR',
25
25
  'REVERSE_POW_XOR',
@@ -27,6 +27,8 @@ __all__ = (
27
27
  'HLFMT_ANSI',
28
28
  'HLFMT_BBCODE',
29
29
  'undefined',
30
+ 'hook',
31
+ 'version',
30
32
  'version_info',
31
33
  'pys_highlight',
32
34
  'pys_exec',
@@ -1,8 +1,8 @@
1
- from typing import TYPE_CHECKING, Any, Callable, Iterator, Literal, Optional
1
+ from typing import TYPE_CHECKING, Any, Callable, Iterable, Literal, Optional
2
2
 
3
3
  if TYPE_CHECKING:
4
4
  from .core.buffer import PysFileBuffer
5
- from .core.cache import PysUndefined
5
+ from .core.cache import PysUndefined, PysHook
6
6
  from .core.highlight import _PysHighlightFormatter
7
7
  from .core.position import PysPosition
8
8
  from .core.results import PysExecuteResult
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
10
10
  from .core.version import PysVersionInfo
11
11
 
12
12
  from io import IOBase
13
- from types import ModuleType
13
+ from types import BuiltinMethodType, ModuleType
14
14
 
15
15
  from . import core as core
16
16
  from .core.highlight import PygmentsPyScriptLexer as PygmentsPyScriptLexer
@@ -18,7 +18,7 @@ from .core.highlight import PygmentsPyScriptLexer as PygmentsPyScriptLexer
18
18
  DEFAULT: int
19
19
  DEBUG: int
20
20
  SILENT: int
21
- RETRES: int
21
+ RETURN_RESULT: int
22
22
  HIGHLIGHT: int
23
23
  NO_COLOR: int
24
24
  REVERSE_POW_XOR: int
@@ -28,10 +28,12 @@ HLFMT_ANSI: _PysHighlightFormatter
28
28
  HLFMT_BBCODE: _PysHighlightFormatter
29
29
 
30
30
  undefined: PysUndefined
31
+ hook: PysHook
32
+ version: str
31
33
  version_info: PysVersionInfo
32
34
 
33
35
  def pys_highlight(
34
- source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
36
+ source: str | bytes | bytearray | Iterable | BuiltinMethodType | IOBase | PysFileBuffer,
35
37
  format: Optional[
36
38
  Callable[
37
39
  [
@@ -49,13 +51,13 @@ def pys_highlight(
49
51
  ) -> str: ...
50
52
 
51
53
  def pys_exec(
52
- source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
54
+ source: str | bytes | bytearray | Iterable | BuiltinMethodType | IOBase | PysFileBuffer,
53
55
  globals: Optional[dict[str, Any] | PysSymbolTable | PysUndefined] = None,
54
56
  flags: int = DEFAULT
55
57
  ) -> None | PysExecuteResult: ...
56
58
 
57
59
  def pys_eval(
58
- source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
60
+ source: str | bytes | bytearray | Iterable | BuiltinMethodType | IOBase | PysFileBuffer,
59
61
  globals: Optional[dict[str, Any] | PysSymbolTable | PysUndefined] = None,
60
62
  flags: int = DEFAULT
61
63
  ) -> Any | PysExecuteResult: ...
@@ -1,5 +1,5 @@
1
1
  """
2
- PyScript implementations.
2
+ The Core of PyScript Implementations.
3
3
  """
4
4
 
5
5
  from . import (
@@ -1,6 +1,6 @@
1
1
  from .bases import Pys
2
- from .checks import is_assign, is_incremental
3
- from .constants import TOKENS, DEFAULT
2
+ from .checks import is_unpack_assignment, is_incremental
3
+ from .constants import TOKENS, KEYWORDS, DEFAULT
4
4
  from .context import PysContext
5
5
  from .exceptions import PysTraceback
6
6
  from .nodes import PysNode, PysKeywordNode, PysIdentifierNode, PysAttributeNode, PysSubscriptNode
@@ -42,9 +42,10 @@ class PysAnalyzer(Pys):
42
42
  def analyze(self) -> PysTraceback | None:
43
43
  self.in_loop = 0
44
44
  self.in_function = 0
45
+ self.in_class = 0
45
46
  self.in_switch = 0
46
- self.error = None
47
47
  self.parameters = set()
48
+ self.error = None
48
49
 
49
50
  self.visit(self.node)
50
51
  return self.error
@@ -357,15 +358,23 @@ class PysAnalyzer(Pys):
357
358
  self.in_function = 0
358
359
  self.in_switch = 0
359
360
 
361
+ self.in_class += 1
362
+
360
363
  self.visit(node.body)
361
364
  if self.error:
362
365
  return
363
366
 
367
+ self.in_class -= 1
368
+
364
369
  self.in_loop = in_loop
365
370
  self.in_function = in_function
366
371
  self.in_switch = in_switch
367
372
 
368
373
  def visit_FunctionNode(self, node):
374
+ if node.constructor and self.in_class == 0:
375
+ self.throw(f"{KEYWORDS['constructor']} function outside of class", node.name.position)
376
+ return
377
+
369
378
  for decorator in node.decorators:
370
379
  self.visit(decorator)
371
380
  if self.error:
@@ -387,9 +396,10 @@ class PysAnalyzer(Pys):
387
396
  if self.error:
388
397
  return
389
398
 
390
- in_loop, in_switch, parameters = self.in_loop, self.in_switch, self.parameters
399
+ in_loop, in_class, in_switch, parameters = self.in_loop, self.in_class, self.in_switch, self.parameters
391
400
 
392
401
  self.in_loop = 0
402
+ self.in_class = 0
393
403
  self.in_switch = 0
394
404
 
395
405
  self.in_function += 1
@@ -403,20 +413,21 @@ class PysAnalyzer(Pys):
403
413
  self.parameters = parameters
404
414
 
405
415
  self.in_loop = in_loop
416
+ self.in_class = in_class
406
417
  self.in_switch = in_switch
407
418
 
408
419
  def visit_GlobalNode(self, node):
409
420
  if self.in_function == 0:
410
- self.throw("global outside of function", node.position)
421
+ self.throw(f"{KEYWORDS['global']} outside of function", node.position)
411
422
 
412
423
  for identifier in node.identifiers:
413
424
  if identifier.value in self.parameters:
414
- self.throw("name {!r} is parameter and global".format(identifier.value), identifier.position)
425
+ self.throw(f"name {identifier.value!r} is parameter and global", identifier.position)
415
426
  return
416
427
 
417
428
  def visit_ReturnNode(self, node):
418
429
  if self.in_function == 0:
419
- self.throw("return outside of function", node.position)
430
+ self.throw(f"{KEYWORDS['return']} outside of function", node.position)
420
431
  return
421
432
 
422
433
  if node.value:
@@ -457,12 +468,12 @@ class PysAnalyzer(Pys):
457
468
  return
458
469
 
459
470
  elif type is PysKeywordNode:
460
- self.throw(f"cannot delete {target.name.value}", target.position)
471
+ self.throw(f"cannot {KEYWORDS['delete']} {target.name.value}", target.position)
461
472
  return
462
473
 
463
474
  elif isinstance(target, PysNode):
464
475
  if type is not PysIdentifierNode:
465
- self.throw("cannot delete literal", target.position)
476
+ self.throw(f"cannot {KEYWORDS['delete']} literal", target.position)
466
477
  return
467
478
 
468
479
  else:
@@ -470,11 +481,11 @@ class PysAnalyzer(Pys):
470
481
 
471
482
  def visit_ContinueNode(self, node):
472
483
  if self.in_loop == 0:
473
- self.throw("continue outside of loop", node.position)
484
+ self.throw(f"{KEYWORDS['continue']} outside of loop", node.position)
474
485
 
475
486
  def visit_BreakNode(self, node):
476
487
  if self.in_loop == 0 and self.in_switch == 0:
477
- self.throw("break outside of loop or switch case", node.position)
488
+ self.throw(f"{KEYWORDS['break']} outside of loop or switch case", node.position)
478
489
 
479
490
  def visit_slice_SubscriptNode(self, nslice):
480
491
  type = nslice.__class__
@@ -517,7 +528,7 @@ class PysAnalyzer(Pys):
517
528
 
518
529
  self.visit_slice_SubscriptNode(node.slice)
519
530
 
520
- elif is_assign(type):
531
+ elif is_unpack_assignment(type):
521
532
  for element in node.elements:
522
533
  self.visit_declaration_AssignNode(element, message)
523
534
  if self.error:
@@ -4,6 +4,7 @@ from .utils.generic import setimuattr
4
4
  from .utils.string import normstr
5
5
 
6
6
  from io import IOBase
7
+ from typing import Callable, Iterable, Optional
7
8
 
8
9
  @immutable
9
10
  class PysBuffer(Pys):
@@ -13,7 +14,11 @@ class PysFileBuffer(PysBuffer):
13
14
 
14
15
  __slots__ = ('text', 'name')
15
16
 
16
- def __init__(self, text, name=None) -> None:
17
+ def __init__(
18
+ self,
19
+ text: str | bytes | bytearray | Iterable | Callable | IOBase | 'PysFileBuffer',
20
+ name: Optional[str | bytes] = None
21
+ ) -> None:
17
22
 
18
23
  if isinstance(text, PysFileBuffer):
19
24
  name = normstr(text.name if name is None else name)
@@ -1,10 +1,11 @@
1
1
  from .bases import Pys
2
2
  from .constants import LIBRARIES_PATH, SITE_PACKAGES_PATH
3
+ from .exceptions import PysTraceback
3
4
  from .utils.debug import print_display, print_traceback
4
5
  from .utils.decorators import inheritable, singleton
5
6
 
6
7
  from threading import RLock
7
- from typing import Literal
8
+ from typing import Any, Callable, Literal
8
9
 
9
10
  loading_modules = set()
10
11
  lock = RLock()
@@ -35,7 +36,7 @@ class PysHook(Pys):
35
36
 
36
37
  __slots__ = ()
37
38
 
38
- def __new_singleton__(cls):
39
+ def __new_singleton__(cls) -> 'PysHook':
39
40
  global hook
40
41
  hook = super(cls, cls).__new__(cls)
41
42
  hook.running_shell = False
@@ -46,61 +47,61 @@ class PysHook(Pys):
46
47
  hook.ps2 = '... '
47
48
  return hook
48
49
 
49
- def __repr__(self):
50
+ def __repr__(self) -> str:
50
51
  return f'<hook object at {id(self):016X}>'
51
52
 
52
53
  @property
53
- def running_shell(self):
54
+ def running_shell(self) -> bool:
54
55
  return singletons['hook.running_shell']
55
56
 
56
57
  @running_shell.setter
57
- def running_shell(self, value):
58
+ def running_shell(self, value: bool) -> None:
58
59
  singletons['hook.running_shell'] = bool(value)
59
60
 
60
61
  @property
61
- def running_breakpoint(self):
62
+ def running_breakpoint(self) -> bool:
62
63
  return singletons['hook.running_breakpoint']
63
64
 
64
65
  @running_breakpoint.setter
65
- def running_breakpoint(self, value):
66
+ def running_breakpoint(self, value: bool) -> None:
66
67
  singletons['hook.running_breakpoint'] = bool(value)
67
68
 
68
69
  @property
69
- def display(self):
70
+ def display(self) -> Callable[[Any], None]:
70
71
  return singletons['hook.display']
71
72
 
72
73
  @display.setter
73
- def display(self, value):
74
+ def display(self, value: Callable[[Any], None]) -> None:
74
75
  if value is not None and not callable(value):
75
76
  raise TypeError("hook.display: must be callable")
76
77
  singletons['hook.display'] = value
77
78
 
78
79
  @property
79
- def exception(self):
80
+ def exception(self) -> Callable[[type[BaseException], BaseException | None, PysTraceback], None]:
80
81
  return singletons['hook.exception']
81
82
 
82
83
  @exception.setter
83
- def exception(self, value):
84
+ def exception(self, value: Callable[[type[BaseException], BaseException | None, PysTraceback], None]) -> None:
84
85
  if value is not None and not callable(value):
85
86
  raise TypeError("hook.exception: must be callable")
86
87
  singletons['hook.exception'] = value
87
88
 
88
89
  @property
89
- def ps1(self):
90
+ def ps1(self) -> str:
90
91
  return singletons['hook.ps1']
91
92
 
92
93
  @ps1.setter
93
- def ps1(self, value):
94
+ def ps1(self, value: str) -> None:
94
95
  if not isinstance(value, str):
95
96
  raise TypeError("hook.ps1: must be a string")
96
97
  singletons['hook.ps1'] = value
97
98
 
98
99
  @property
99
- def ps2(self):
100
+ def ps2(self) -> str:
100
101
  return singletons['hook.ps2']
101
102
 
102
103
  @ps2.setter
103
- def ps2(self, value):
104
+ def ps2(self, value: str) -> None:
104
105
  if not isinstance(value, str):
105
106
  raise TypeError("hook.ps2: must be a string")
106
107
  singletons['hook.ps2'] = value
@@ -14,7 +14,7 @@ is_statement = frozenset([
14
14
  PysDeleteNode, PysContinueNode, PysBreakNode
15
15
  ]).__contains__
16
16
 
17
- is_assign = frozenset([
17
+ is_unpack_assignment = frozenset([
18
18
  PysSetNode, PysListNode, PysTupleNode
19
19
  ]).__contains__
20
20
 
@@ -102,6 +102,7 @@ KEYWORDS = MappingProxyType({
102
102
  'case': 'case',
103
103
  'catch': 'catch',
104
104
  'class': 'class',
105
+ 'constructor': 'constructor',
105
106
  'continue': 'continue',
106
107
  'default': 'default',
107
108
  'del': 'del',
@@ -137,15 +138,16 @@ KEYWORDS = MappingProxyType({
137
138
 
138
139
  CONSTANT_KEYWORDS = (
139
140
  KEYWORDS['__debug__'], KEYWORDS['False'], KEYWORDS['None'], KEYWORDS['True'], KEYWORDS['and'], KEYWORDS['class'],
140
- KEYWORDS['extends'], KEYWORDS['func'], KEYWORDS['function'], KEYWORDS['false'], KEYWORDS['global'], KEYWORDS['in'],
141
- KEYWORDS['is'], KEYWORDS['not'], KEYWORDS['none'], KEYWORDS['of'], KEYWORDS['or'], KEYWORDS['true']
141
+ KEYWORDS['constructor'], KEYWORDS['extends'], KEYWORDS['func'], KEYWORDS['function'], KEYWORDS['false'],
142
+ KEYWORDS['global'], KEYWORDS['in'], KEYWORDS['is'], KEYWORDS['not'], KEYWORDS['none'], KEYWORDS['of'],
143
+ KEYWORDS['or'], KEYWORDS['true']
142
144
  )
143
145
 
144
146
  # flags
145
147
  DEFAULT = 0
146
148
  DEBUG = 1 << 0
147
149
  SILENT = 1 << 1
148
- RETRES = 1 << 2
150
+ RETURN_RESULT = 1 << 2
149
151
  HIGHLIGHT = 1 << 3
150
152
  NO_COLOR = 1 << 4
151
153
  REVERSE_POW_XOR = 1 << 5
@@ -1,8 +1,13 @@
1
1
  from .bases import Pys
2
+ from .buffer import PysFileBuffer
2
3
  from .constants import DEFAULT
4
+ from .position import PysPosition
5
+ from .symtab import PysSymbolTable
3
6
  from .utils.decorators import immutable
4
7
  from .utils.generic import setimuattr
5
8
 
9
+ from typing import Optional
10
+
6
11
  @immutable
7
12
  class PysContext(Pys):
8
13
 
@@ -10,14 +15,15 @@ class PysContext(Pys):
10
15
 
11
16
  def __init__(
12
17
  self,
13
- file,
14
- name=None,
15
- qualname=None,
16
- flags=None,
17
- symbol_table=None,
18
- parent=None,
19
- parent_entry_position=None
20
- ):
18
+ *,
19
+ file: PysFileBuffer,
20
+ name: Optional[str] = None,
21
+ qualname: Optional[str] = None,
22
+ flags: Optional[int] = None,
23
+ symbol_table: Optional[PysSymbolTable] = None,
24
+ parent: Optional['PysContext'] = None,
25
+ parent_entry_position: Optional[PysPosition] = None
26
+ ) -> None:
21
27
  if flags is None and parent:
22
28
  flags = parent.flags
23
29
 
@@ -29,7 +35,7 @@ class PysContext(Pys):
29
35
  setimuattr(self, 'parent', parent)
30
36
  setimuattr(self, 'parent_entry_position', parent_entry_position)
31
37
 
32
- def __repr__(self):
38
+ def __repr__(self) -> str:
33
39
  return f'<Context {self.name!r}>'
34
40
 
35
41
  class PysClassContext(PysContext):
@@ -38,11 +44,12 @@ class PysClassContext(PysContext):
38
44
 
39
45
  def __init__(
40
46
  self,
41
- name,
42
- symbol_table,
43
- parent,
44
- parent_entry_position
45
- ):
47
+ *,
48
+ name: str,
49
+ symbol_table: PysSymbolTable,
50
+ parent: PysContext,
51
+ parent_entry_position: PysPosition
52
+ ) -> None:
46
53
  qualname = parent.qualname
47
54
  super().__init__(
48
55
  file=parent.file,
@@ -5,22 +5,37 @@ from .utils.decorators import immutable
5
5
  from .utils.generic import setimuattr
6
6
  from .utils.string import indent
7
7
 
8
+ from typing import TYPE_CHECKING, Optional
9
+
10
+ if TYPE_CHECKING:
11
+ from .context import PysContext
12
+ from .position import PysPosition
13
+ from .results import PysRunTimeResult
14
+
8
15
  @immutable
9
16
  class PysTraceback(Pys):
10
17
 
11
18
  __slots__ = ('exception', 'context', 'position', 'cause', 'directly')
12
19
 
13
- def __init__(self, exception, context, position, cause=None, directly=False):
20
+ def __init__(
21
+ self,
22
+ exception: BaseException | type[BaseException],
23
+ context: 'PysContext',
24
+ position: 'PysPosition',
25
+ cause: Optional['PysTraceback'] = None,
26
+ directly: bool = False
27
+ ) -> None:
28
+
14
29
  setimuattr(self, 'exception', exception)
15
30
  setimuattr(self, 'context', context)
16
31
  setimuattr(self, 'position', position)
17
32
  setimuattr(self, 'cause', cause)
18
33
  setimuattr(self, 'directly', directly)
19
34
 
20
- def __repr__(self):
35
+ def __repr__(self) -> str:
21
36
  return f'<traceback of exception {self.exception!r}>'
22
37
 
23
- def string_traceback(self):
38
+ def string_traceback(self) -> str:
24
39
  from .position import format_arrow # circular import problem solved
25
40
 
26
41
  context = self.context
@@ -95,11 +110,11 @@ class PysSignal(Pys, BaseException):
95
110
 
96
111
  __slots__ = ('result',)
97
112
 
98
- def __init__(self, result):
113
+ def __init__(self, result: 'PysRunTimeResult') -> None:
99
114
  super().__init__()
100
115
  self.result = result
101
116
 
102
- def __str__(self):
117
+ def __str__(self) -> str:
103
118
  if self.result.error is None:
104
119
  return '<signal>'
105
120
 
@@ -43,9 +43,9 @@ _builtin_functions = tuple(
43
43
  )
44
44
 
45
45
  try:
46
- # if pygments module exists
46
+ # if pygments module already exists
47
47
  from pygments.lexer import RegexLexer, include, bygroups
48
- from pygments.token import Comment, Keyword, Name, Number, String, Text
48
+ from pygments.token import Comment, Keyword, Name, Number, Punctuation, String, Whitespace
49
49
  from pygments.unistring import xid_start, xid_continue
50
50
 
51
51
  _keyword_definitions = (KEYWORDS['class'], KEYWORDS['func'], KEYWORDS['function'])
@@ -66,6 +66,12 @@ try:
66
66
  tokens = {
67
67
 
68
68
  'root': [
69
+ # Whitespaces
70
+ (r'\s+', Whitespace),
71
+
72
+ # Punctuation
73
+ (r'[!%&\(\)\*\+,\-\./:;<=>\?@\[\]^{\|}~\\]+', Punctuation),
74
+
69
75
  # Keywords
70
76
  (
71
77
  r'\b(' + '|'.join(filter(lambda k: not is_constant_keywords(k), KEYWORDS)) + r')\b',
@@ -121,11 +127,11 @@ try:
121
127
  # Numbers
122
128
  (
123
129
  r'0[bB][01](_?[01])*[jJiI]?',
124
- Number.Binary
130
+ Number.Bin
125
131
  ),
126
132
  (
127
133
  r'0[oO][0-7](_?[0-7])*[jJiI]?',
128
- Number.Octal
134
+ Number.Oct
129
135
  ),
130
136
  (
131
137
  r'0[xX][0-9a-fA-F](_?[0-9a-fA-F])*[jJiI]?',
@@ -142,20 +148,24 @@ try:
142
148
  ),
143
149
 
144
150
  # Comments
145
- (r'#.*$', Comment.Single),
151
+ (
152
+ r'#',
153
+ Comment.Single,
154
+ 'in-comment'
155
+ ),
146
156
 
147
157
  # Class definition
148
158
  (
149
159
  r'\b(' + KEYWORDS['class'] + r')\b'
150
160
  r'(\s*)((?:\$(?:[^\S\r\n]*))?\b' + _unicode_name + r'*)\b',
151
- bygroups(Keyword.Declaration, Text, Name.Class)
161
+ bygroups(Keyword.Constant, Whitespace, Name.Class)
152
162
  ),
153
163
 
154
164
  # Function definition
155
165
  (
156
166
  r'\b(' + KEYWORDS['func'] + '|' + KEYWORDS['function'] + r')\b' +
157
167
  r'(\s*)((?:\$(?:[^\S\r\n]*))?\b' + _unicode_name + r'*)\b',
158
- bygroups(Keyword.Declaration, Text, Name.Function)
168
+ bygroups(Keyword.Constant, Whitespace, Name.Function)
159
169
  ),
160
170
 
161
171
  # Keywords (if that definition is unmatched)
@@ -184,13 +194,17 @@ try:
184
194
  (r'(?:\$(?:[^\S\r\n]*))?\b' + _unicode_name + r'*\b', Name),
185
195
  ],
186
196
 
197
+ 'todo-keywords': [
198
+ (r'\b(TODO|NOTE|FIXME|BUG|HACK)\b', Keyword.Constant.Todo)
199
+ ],
200
+
187
201
  'string-escapes': [
188
202
  (r'\\([nrtbfav\'"\n\r])', String.Escape),
189
203
  (r'\\[0-7]{1,3}}', String.Escape.Octal),
190
204
  (r'\\x[0-9A-Fa-f]{2}', String.Escape.Hex),
191
205
  (r'\\u[0-9A-Fa-f]{4}', String.Escape.Unicode),
192
206
  (r'\\U[0-9A-Fa-f]{8}', String.Escape.Unicode),
193
- (r'\\N\{[^}]+\}', String.Escape.Unicode),
207
+ (r'\\N\{[^}]+\}', String.Escape.UnicodeName),
194
208
  (r'\\.', String.Escape.Invalid)
195
209
  ],
196
210
 
@@ -214,12 +228,14 @@ try:
214
228
  'string-apostrophe-triple': [
215
229
  (r"'''", String.Delimiter, '#pop'),
216
230
  include('string-escapes'),
231
+ include('todo-keywords'),
217
232
  (r'.', String)
218
233
  ],
219
234
 
220
235
  'string-quotation-triple': [
221
236
  (r'"""', String.Delimiter, '#pop'),
222
237
  include('string-escapes'),
238
+ include('todo-keywords'),
223
239
  (r'.', String)
224
240
  ],
225
241
 
@@ -238,23 +254,31 @@ try:
238
254
  'string-apostrophe-single': [
239
255
  (r"'", String.Delimiter, '#pop'),
240
256
  include('string-escapes'),
257
+ include('todo-keywords'),
241
258
  (r'.', String)
242
259
  ],
243
260
 
244
261
  'string-quotation-single': [
245
262
  (r'"', String.Delimiter, '#pop'),
246
263
  include('string-escapes'),
264
+ include('todo-keywords'),
247
265
  (r'.', String)
248
266
  ],
249
267
 
268
+ 'in-comment': [
269
+ (r'$', Comment.Single, '#pop'),
270
+ include('todo-keywords'),
271
+ (r'.', Comment.Single),
272
+ ]
273
+
250
274
  }
251
275
 
252
- except ImportError:
276
+ except ImportError as e:
253
277
 
254
278
  class PygmentsPyScriptLexer(Pys):
255
279
 
256
280
  def __new__(cls, *args, **kwargs):
257
- raise ModuleNotFoundError("module pygments is not found")
281
+ raise ModuleNotFoundError(f"cannot import module pygments: {e}")
258
282
 
259
283
  @typechecked
260
284
  class _PysHighlightFormatter(Pys):
@@ -1,6 +1,6 @@
1
1
  from .constants import TOKENS, KEYWORDS, DEBUG
2
2
  from .cache import undefined
3
- from .checks import is_assign, is_equals, is_incremental, is_public_attribute
3
+ from .checks import is_unpack_assignment, is_equals, is_incremental, is_public_attribute
4
4
  from .context import PysClassContext
5
5
  from .exceptions import PysTraceback
6
6
  from .handlers import handle_call
@@ -477,8 +477,7 @@ def visit_ImportNode(node, context):
477
477
  return result.failure(
478
478
  PysTraceback(
479
479
  TypeError(
480
- f"Item in {module.__name__}.{exported_from} must be str, "
481
- f"not {type(package).__name__}"
480
+ f"Item in {module.__name__}.{exported_from} must be str, not {type(package).__name__}"
482
481
  ),
483
482
  context,
484
483
  name_position
@@ -1397,7 +1396,7 @@ def visit_declaration_AssignNode(node, context, value, operand=TOKENS['EQUAL']):
1397
1396
  if should_return():
1398
1397
  return result
1399
1398
 
1400
- elif is_assign(ntype):
1399
+ elif is_unpack_assignment(ntype):
1401
1400
  position = node.position
1402
1401
 
1403
1402
  if not isinstance(value, Iterable):