pyscript-programming-language 1.4.0__tar.gz → 1.5.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 (65) hide show
  1. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/PKG-INFO +5 -2
  2. pyscript_programming_language-1.5.0/pyscript/__init__.py +34 -0
  3. pyscript_programming_language-1.5.0/pyscript/__init__.pyi +73 -0
  4. pyscript_programming_language-1.5.0/pyscript/__main__.py +172 -0
  5. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/__init__.py +1 -1
  6. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/analyzer.py +66 -41
  7. pyscript_programming_language-1.5.0/pyscript/core/bases.py +2 -0
  8. pyscript_programming_language-1.5.0/pyscript/core/buffer.py +33 -0
  9. pyscript_programming_language-1.5.0/pyscript/core/cache.py +96 -0
  10. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/constants.py +38 -30
  11. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/context.py +13 -9
  12. pyscript_programming_language-1.5.0/pyscript/core/exceptions.py +110 -0
  13. pyscript_programming_language-1.5.0/pyscript/core/handlers.py +82 -0
  14. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/highlight.py +36 -31
  15. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/interpreter.py +128 -151
  16. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/lexer.py +44 -19
  17. pyscript_programming_language-1.5.0/pyscript/core/nodes.py +503 -0
  18. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/objects.py +35 -44
  19. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/parser.py +383 -240
  20. pyscript_programming_language-1.5.0/pyscript/core/position.py +97 -0
  21. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/pysbuiltins.py +60 -41
  22. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/results.py +1 -1
  23. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/runner.py +100 -67
  24. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/core/symtab.py +24 -11
  25. pyscript_programming_language-1.5.0/pyscript/core/token.py +39 -0
  26. pyscript_programming_language-1.5.0/pyscript/core/utils/__init__.py +13 -0
  27. pyscript_programming_language-1.5.0/pyscript/core/utils/constants.py +151 -0
  28. pyscript_programming_language-1.5.0/pyscript/core/utils/debug.py +35 -0
  29. pyscript_programming_language-1.5.0/pyscript/core/utils/decorators.py +44 -0
  30. pyscript_programming_language-1.5.0/pyscript/core/utils/general.py +139 -0
  31. pyscript_programming_language-1.5.0/pyscript/core/version.py +36 -0
  32. pyscript_programming_language-1.5.0/pyscript/lib/67.pys +1 -0
  33. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/brainfuck.pys +5 -5
  34. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/getch.pys +2 -1
  35. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/jsdict.pys +1 -9
  36. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/parser.pys +33 -12
  37. pyscript_programming_language-1.5.0/pyscript/lib/this.pys +19 -0
  38. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript_programming_language.egg-info/PKG-INFO +5 -2
  39. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript_programming_language.egg-info/SOURCES.txt +7 -2
  40. pyscript_programming_language-1.5.0/pyscript_programming_language.egg-info/requires.txt +3 -0
  41. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/setup.py +5 -2
  42. pyscript_programming_language-1.4.0/pyscript/__init__.py +0 -33
  43. pyscript_programming_language-1.4.0/pyscript/__init__.pyi +0 -54
  44. pyscript_programming_language-1.4.0/pyscript/__main__.py +0 -142
  45. pyscript_programming_language-1.4.0/pyscript/core/bases.py +0 -2
  46. pyscript_programming_language-1.4.0/pyscript/core/buffer.py +0 -26
  47. pyscript_programming_language-1.4.0/pyscript/core/cache.py +0 -16
  48. pyscript_programming_language-1.4.0/pyscript/core/exceptions.py +0 -91
  49. pyscript_programming_language-1.4.0/pyscript/core/handlers.py +0 -74
  50. pyscript_programming_language-1.4.0/pyscript/core/nodes.py +0 -326
  51. pyscript_programming_language-1.4.0/pyscript/core/position.py +0 -92
  52. pyscript_programming_language-1.4.0/pyscript/core/singletons.py +0 -124
  53. pyscript_programming_language-1.4.0/pyscript/core/token.py +0 -25
  54. pyscript_programming_language-1.4.0/pyscript/core/utils.py +0 -174
  55. pyscript_programming_language-1.4.0/pyscript/core/version.py +0 -5
  56. pyscript_programming_language-1.4.0/pyscript/lib/this.pys +0 -19
  57. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/MANIFEST.in +0 -0
  58. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/README.md +0 -0
  59. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/__hello__.pys +0 -0
  60. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/clock.pys +0 -0
  61. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/lib/sys.pys +0 -0
  62. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript/this.py +0 -0
  63. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript_programming_language.egg-info/dependency_links.txt +0 -0
  64. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/pyscript_programming_language.egg-info/top_level.txt +0 -0
  65. {pyscript_programming_language-1.4.0 → pyscript_programming_language-1.5.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyscript-programming-language
3
- Version: 1.4.0
3
+ Version: 1.5.0
4
4
  Summary: PyScript Programming Language
5
5
  Home-page: https://github.com/azzammuhyala/pyscript
6
6
  Author: azzammuhyala
@@ -15,8 +15,10 @@ Classifier: Intended Audience :: Developers
15
15
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
16
  Classifier: Topic :: Software Development :: Interpreters
17
17
  Classifier: Topic :: Software Development :: Compilers
18
- Requires-Python: >=3.5
18
+ Requires-Python: >=3.10
19
19
  Description-Content-Type: text/markdown
20
+ Provides-Extra: typecheck
21
+ Requires-Dist: beartype; extra == "typecheck"
20
22
  Dynamic: author
21
23
  Dynamic: author-email
22
24
  Dynamic: classifier
@@ -26,6 +28,7 @@ Dynamic: home-page
26
28
  Dynamic: keywords
27
29
  Dynamic: license
28
30
  Dynamic: project-url
31
+ Dynamic: provides-extra
29
32
  Dynamic: requires-python
30
33
  Dynamic: summary
31
34
 
@@ -0,0 +1,34 @@
1
+ """
2
+ PyScript is a programming language written in Python. \
3
+ This language is not isolated and is directly integrated with the Python's library and namespace levels.
4
+ """
5
+
6
+ if __import__('sys').version_info < (3, 10):
7
+ raise ImportError("Python version 3.10 and above is required to run PyScript")
8
+
9
+ from . import core
10
+
11
+ from .core.constants import DEFAULT, DEBUG, SILENT, RETRES, COMMENT, NO_COLOR, REVERSE_POW_XOR
12
+ from .core.cache import undefined
13
+ from .core.highlight import HLFMT_HTML, HLFMT_ANSI, pys_highlight
14
+ from .core.runner import pys_exec, pys_eval, pys_shell
15
+ from .core.version import version_info, __version__, __date__
16
+
17
+ __all__ = (
18
+ 'core',
19
+ 'DEFAULT',
20
+ 'DEBUG',
21
+ 'SILENT',
22
+ 'RETRES',
23
+ 'COMMENT',
24
+ 'NO_COLOR',
25
+ 'REVERSE_POW_XOR',
26
+ 'HLFMT_HTML',
27
+ 'HLFMT_ANSI',
28
+ 'undefined',
29
+ 'version_info',
30
+ 'pys_highlight',
31
+ 'pys_exec',
32
+ 'pys_eval',
33
+ 'pys_shell'
34
+ )
@@ -0,0 +1,73 @@
1
+ from typing import TYPE_CHECKING, Any, Callable, Iterator, Literal, Optional
2
+
3
+ if TYPE_CHECKING:
4
+ from .core.buffer import PysFileBuffer
5
+ from .core.cache import PysUndefined
6
+ from .core.highlight import _HighlightFormatter
7
+ from .core.position import PysPosition
8
+ from .core.results import PysExecuteResult
9
+ from .core.symtab import PysSymbolTable
10
+ from .core.version import PysVersionInfo
11
+
12
+ from io import IOBase
13
+
14
+ from . import core as core
15
+
16
+ DEFAULT: int
17
+ DEBUG: int
18
+ SILENT: int
19
+ RETRES: int
20
+ COMMENT: int
21
+ NO_COLOR: int
22
+ REVERSE_POW_XOR: int
23
+
24
+ HLFMT_HTML: _HighlightFormatter
25
+ HLFMT_ANSI: _HighlightFormatter
26
+
27
+ undefined: PysUndefined
28
+ version_info: PysVersionInfo
29
+
30
+ def pys_highlight(
31
+ source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
32
+ format: Optional[
33
+ Callable[
34
+ [
35
+ str | Literal[
36
+ 'start',
37
+ 'bracket-unmatch',
38
+ 'identifier', 'identifier-const', 'identifier-call', 'identifier-class',
39
+ 'keyword', 'keyword-identifier',
40
+ 'number', 'string', 'comment', 'newline',
41
+ 'default',
42
+ 'end'
43
+ ],
44
+ PysPosition,
45
+ str
46
+ ],
47
+ str
48
+ ]
49
+ ] = None,
50
+ max_parenthesis_level: int = 3,
51
+ flags: int = DEFAULT
52
+ ) -> str: ...
53
+
54
+ def pys_exec(
55
+ source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
56
+ globals: Optional[dict[str, Any] | PysSymbolTable | PysUndefined] = None,
57
+ flags: int = DEFAULT
58
+ ) -> None | PysExecuteResult: ...
59
+
60
+ def pys_eval(
61
+ source: str | bytes | bytearray | Iterator | Callable | IOBase | PysFileBuffer,
62
+ globals: Optional[dict[str, Any] | PysSymbolTable | PysUndefined] = None,
63
+ flags: int = DEFAULT
64
+ ) -> Any | PysExecuteResult: ...
65
+
66
+ def pys_shell(
67
+ globals: Optional[dict[str, Any] | PysSymbolTable | PysUndefined] = None,
68
+ flags: int = DEFAULT
69
+ ) -> int | Any: ...
70
+
71
+ __version__: str
72
+ __date__: str
73
+ __all__: tuple[str]
@@ -0,0 +1,172 @@
1
+ from .core.buffer import PysFileBuffer
2
+ from .core.cache import undefined
3
+ from .core.constants import DEFAULT, DEBUG, NO_COLOR
4
+ from .core.handlers import handle_execute
5
+ from .core.highlight import HLFMT_HTML, HLFMT_ANSI, pys_highlight
6
+ from .core.runner import pys_runner, pys_shell
7
+ from .core.symtab import build_symbol_table
8
+ from .core.utils.general import normalize_path
9
+ from .core.version import __version__
10
+
11
+ from argparse import ArgumentParser
12
+
13
+ from sys import executable, version_info, exit, setrecursionlimit
14
+ from os.path import basename, splitext
15
+
16
+ parser = ArgumentParser(
17
+ prog=splitext(basename(executable))[0] + ' -m pyscript',
18
+ description='PyScript Launcher for Python Version ' + '.'.join(map(str, version_info))
19
+ )
20
+
21
+ parser.add_argument(
22
+ 'file',
23
+ type=str,
24
+ nargs='?',
25
+ default=None,
26
+ help="file path"
27
+ )
28
+
29
+ parser.add_argument(
30
+ '-v', '--version',
31
+ action='version',
32
+ version=f"PyScript {__version__}",
33
+ )
34
+
35
+ parser.add_argument(
36
+ '-c', '--command',
37
+ type=str,
38
+ default=None,
39
+ help="execute PyScript from argument",
40
+ )
41
+
42
+ parser.add_argument(
43
+ '-d', '--debug',
44
+ action='store_true',
45
+ help="set a debug flag, this will remove the assert statement"
46
+ )
47
+
48
+ parser.add_argument(
49
+ '-i', '--inspect',
50
+ action='store_true',
51
+ help="inspect interactively after running a file",
52
+ )
53
+
54
+ parser.add_argument(
55
+ '-l', '--highlight',
56
+ choices=('html', 'ansi'),
57
+ default=None,
58
+ help='generate PyScript highlight code from a file'
59
+ )
60
+
61
+ parser.add_argument(
62
+ '-n', '--no-color',
63
+ action='store_true',
64
+ help="no colorful traceback"
65
+ )
66
+
67
+ parser.add_argument(
68
+ '-r', '--py-recursion',
69
+ type=int,
70
+ default=None,
71
+ help="set a python recursion limit"
72
+ )
73
+
74
+ args = parser.parse_args()
75
+
76
+ if args.highlight and args.file is None:
77
+ parser.error("-l, --highlight: file path require")
78
+
79
+ if args.py_recursion is not None:
80
+ try:
81
+ setrecursionlimit(args.py_recursion)
82
+ except BaseException as e:
83
+ parser.error(f"-r, --py-recursion: {e}")
84
+
85
+ code = 0
86
+ flags = DEFAULT
87
+
88
+ if args.debug:
89
+ flags |= DEBUG
90
+ if args.no_color:
91
+ flags |= NO_COLOR
92
+
93
+ if args.file is not None:
94
+ path = normalize_path(args.file)
95
+
96
+ try:
97
+ with open(path, 'r') as file:
98
+ file = PysFileBuffer(file, path)
99
+
100
+ except FileNotFoundError:
101
+ parser.error(f"can't open file {path!r}: No such file or directory")
102
+
103
+ except PermissionError:
104
+ parser.error(f"can't open file {path!r}: Permission denied.")
105
+
106
+ except IsADirectoryError:
107
+ parser.error(f"can't open file {path!r}: Path is not a file.")
108
+
109
+ except NotADirectoryError:
110
+ parser.error(f"can't open file {path!r}: Attempting to access directory from file.")
111
+
112
+ except (OSError, IOError):
113
+ parser.error(f"can't open file {path!r}: Attempting to access a system directory or file.")
114
+
115
+ except UnicodeDecodeError:
116
+ parser.error(f"can't read file {path!r}: Bad file.")
117
+
118
+ except BaseException as e:
119
+ parser.error(f"file {path!r}: Unexpected error: {e}")
120
+
121
+ if args.highlight:
122
+ try:
123
+ print(
124
+ pys_highlight(
125
+ file,
126
+ HLFMT_HTML if args.highlight == 'html' else HLFMT_ANSI
127
+ )
128
+ )
129
+ except BaseException as e:
130
+ parser.error(f"file {path!r}: Tokenize error: {e}")
131
+
132
+ else:
133
+ symtab = build_symbol_table(file)
134
+ symtab.set('__name__', '__main__')
135
+
136
+ result = pys_runner(
137
+ file=file,
138
+ mode='exec',
139
+ symbol_table=symtab,
140
+ flags=flags
141
+ )
142
+
143
+ code = handle_execute(result)
144
+
145
+ if args.inspect:
146
+ code = pys_shell(
147
+ globals=result.context.symbol_table,
148
+ flags=result.context.flags
149
+ )
150
+
151
+ elif args.command is not None:
152
+ file = PysFileBuffer(args.command)
153
+
154
+ symtab = build_symbol_table(file)
155
+ symtab.set('__name__', '__main__')
156
+
157
+ code = handle_execute(
158
+ pys_runner(
159
+ file=file,
160
+ mode='exec',
161
+ symbol_table=symtab,
162
+ flags=flags
163
+ )
164
+ )
165
+
166
+ else:
167
+ code = pys_shell(
168
+ globals=undefined,
169
+ flags=flags
170
+ )
171
+
172
+ exit(code)
@@ -21,7 +21,6 @@ from . import (
21
21
  pysbuiltins,
22
22
  results,
23
23
  runner,
24
- singletons,
25
24
  symtab,
26
25
  token,
27
26
  utils,
@@ -38,6 +37,7 @@ __all__ = (
38
37
  'exceptions',
39
38
  'handlers',
40
39
  'highlight',
40
+ 'immutables',
41
41
  'interpreter',
42
42
  'lexer',
43
43
  'nodes',
@@ -1,13 +1,25 @@
1
1
  from .bases import Pys
2
- from .constants import TOKENS, DEFAULT
2
+ from .constants import TOKENS, DEFAULT, NSEQ_GLOBAL, NSEQ_DEL, NSEQ_DICT, NTER_GENERAL
3
3
  from .context import PysContext
4
4
  from .exceptions import PysException
5
- from .nodes import PysSequenceNode, PysIdentifierNode, PysKeywordNode, PysAttributeNode, PysSubscriptNode
5
+ from .nodes import PysNode, PysKeywordNode, PysIdentifierNode, PysSequenceNode, PysAttributeNode, PysSubscriptNode
6
+ from .position import PysPosition
7
+ from .utils.decorators import typechecked
8
+
9
+ from typing import Optional
6
10
 
7
11
  class PysAnalyzer(Pys):
8
12
 
9
- def __init__(self, file, flags=DEFAULT, context_parent=None, context_parent_entry_position=None):
10
- self.file = file
13
+ @typechecked
14
+ def __init__(
15
+ self,
16
+ node: PysNode,
17
+ flags: int = DEFAULT,
18
+ context_parent: Optional[PysContext] = None,
19
+ context_parent_entry_position: Optional[PysPosition] = None
20
+ ) -> None:
21
+
22
+ self.node = node
11
23
  self.flags = flags
12
24
  self.context = context_parent
13
25
  self.context_parent_entry_position = context_parent_entry_position
@@ -17,7 +29,7 @@ class PysAnalyzer(Pys):
17
29
  self.error = PysException(
18
30
  SyntaxError(message),
19
31
  PysContext(
20
- file=self.file,
32
+ file=self.node.position.file,
21
33
  flags=self.flags,
22
34
  parent=self.context,
23
35
  parent_entry_position=self.context_parent_entry_position
@@ -25,15 +37,14 @@ class PysAnalyzer(Pys):
25
37
  position
26
38
  )
27
39
 
28
- def analyze(self, node):
40
+ @typechecked
41
+ def analyze(self) -> PysException | None:
29
42
  self.in_loop = 0
30
43
  self.in_function = 0
31
44
  self.in_switch = 0
32
-
33
45
  self.error = None
34
46
 
35
- self.visit(node)
36
-
47
+ self.visit(self.node)
37
48
  return self.error
38
49
 
39
50
  def visit(self, node):
@@ -43,37 +54,38 @@ class PysAnalyzer(Pys):
43
54
 
44
55
  def visit_SequenceNode(self, node):
45
56
 
46
- if node.type == 'del':
57
+ if node.type == NSEQ_DEL:
47
58
 
48
59
  for element in node.elements:
49
60
 
50
61
  if isinstance(element, PysSubscriptNode):
51
- self.visit(element.object)
62
+ self.visit(element.target)
52
63
  if self.error:
53
64
  return
54
65
 
55
- self.check_valid_slice_from_SubscriptNode(element.slice)
66
+ self.visit_slice_SubscriptNode(element.slice)
56
67
  if self.error:
57
68
  return
58
69
 
59
70
  elif isinstance(element, PysAttributeNode):
60
- self.visit(element.object)
71
+ self.visit(element.target)
61
72
  if self.error:
62
73
  return
63
74
 
64
75
  elif isinstance(element, PysKeywordNode):
65
- self.throw("cannot delete {}".format(element.token.value), element.position)
76
+ self.throw(f"cannot delete {element.token.value}", element.position)
66
77
  return
67
78
 
68
79
  elif not isinstance(element, PysIdentifierNode):
69
80
  self.throw("cannot delete literal", element.position)
70
81
  return
71
82
 
72
- elif node.type == 'global':
83
+ elif node.type == NSEQ_GLOBAL:
84
+
73
85
  if self.in_function == 0:
74
86
  self.throw("global outside of function", node.position)
75
87
 
76
- elif node.type == 'dict':
88
+ elif node.type == NSEQ_DICT:
77
89
 
78
90
  for key, value in node.elements:
79
91
 
@@ -86,20 +98,21 @@ class PysAnalyzer(Pys):
86
98
  return
87
99
 
88
100
  else:
101
+
89
102
  for element in node.elements:
90
103
  self.visit(element)
91
104
  if self.error:
92
105
  return
93
106
 
94
107
  def visit_AttributeNode(self, node):
95
- self.visit(node.object)
108
+ self.visit(node.target)
96
109
 
97
110
  def visit_SubscriptNode(self, node):
98
- self.visit(node.object)
111
+ self.visit(node.target)
99
112
  if self.error:
100
113
  return
101
114
 
102
- self.check_valid_slice_from_SubscriptNode(node.slice)
115
+ self.visit_slice_SubscriptNode(node.slice)
103
116
 
104
117
  def visit_ChainOperatorNode(self, node):
105
118
  for expression in node.expressions:
@@ -108,7 +121,7 @@ class PysAnalyzer(Pys):
108
121
  return
109
122
 
110
123
  def visit_TernaryOperatorNode(self, node):
111
- if node.style == 'general':
124
+ if node.style == NTER_GENERAL:
112
125
  self.visit(node.condition)
113
126
  if self.error:
114
127
  return
@@ -140,17 +153,17 @@ class PysAnalyzer(Pys):
140
153
  operator = 'increase' if node.operand.type == TOKENS['INCREMENT'] else 'decrease'
141
154
 
142
155
  if isinstance(node.value, PysKeywordNode):
143
- self.throw("cannot {} {}".format(operator, node.value.token.value), node.value.position)
156
+ self.throw(f"cannot {operator} {node.value.token.value}", node.value.position)
144
157
  return
145
158
 
146
159
  elif not isinstance(node.value, (PysIdentifierNode, PysAttributeNode, PysSubscriptNode)):
147
- self.throw("cannot {} literal".format(operator), node.value.position)
160
+ self.throw(f"cannot {operator} literal", node.value.position)
148
161
  return
149
162
 
150
163
  self.visit(node.value)
151
164
 
152
165
  def visit_AssignNode(self, node):
153
- self.check_valid_AssignNode(
166
+ self.visit_declaration_AssignNode(
154
167
  node.target,
155
168
  "cannot assign to expression here. Maybe you meant '==' instead of '='?"
156
169
  )
@@ -225,7 +238,7 @@ class PysAnalyzer(Pys):
225
238
  if len(node.header) == 2:
226
239
  declaration, iterable = node.header
227
240
 
228
- self.check_valid_AssignNode(declaration, "cannot assign to expression")
241
+ self.visit_declaration_AssignNode(declaration, "cannot assign to expression")
229
242
  if self.error:
230
243
  return
231
244
 
@@ -323,7 +336,7 @@ class PysAnalyzer(Pys):
323
336
  name = token.value
324
337
 
325
338
  if name in parameter_names:
326
- return self.throw("duplicate argument {!r} in function definition".format(name), token.position)
339
+ return self.throw(f"duplicate argument {name!r} in function definition", token.position)
327
340
 
328
341
  parameter_names.add(name)
329
342
 
@@ -356,18 +369,20 @@ class PysAnalyzer(Pys):
356
369
  keyword_argument_names = set()
357
370
 
358
371
  for element in node.arguments:
359
- value = element
360
372
 
361
373
  if isinstance(element, tuple):
362
374
  token, value = element
363
375
  name = token.value
364
376
 
365
377
  if name in keyword_argument_names:
366
- self.throw("duplicate argument {!r} in call definition".format(name), token.position)
378
+ self.throw(f"duplicate argument {name!r} in call definition", token.position)
367
379
  return
368
380
 
369
381
  keyword_argument_names.add(name)
370
382
 
383
+ else:
384
+ value = element
385
+
371
386
  self.visit(value)
372
387
  if self.error:
373
388
  return
@@ -399,41 +414,51 @@ class PysAnalyzer(Pys):
399
414
  if self.in_loop == 0 and self.in_switch == 0:
400
415
  self.throw("break outside of loop or switch case", node.position)
401
416
 
402
- def check_valid_slice_from_SubscriptNode(self, slice):
403
- if isinstance(slice, list):
404
- for element in slice:
405
- self.check_valid_slice_from_SubscriptNode(element)
417
+ def visit_slice_SubscriptNode(self, nslice):
418
+ if isinstance(nslice, tuple):
419
+ for element in nslice:
420
+ self.visit_slice_SubscriptNode(element)
406
421
  if self.error:
407
422
  return
408
423
 
409
- elif isinstance(slice, tuple):
410
- for element in slice:
411
- self.visit(element)
424
+ elif isinstance(nslice, slice):
425
+ if nslice.start is not None:
426
+ self.visit(nslice.start)
427
+ if self.error:
428
+ return
429
+
430
+ if nslice.stop is not None:
431
+ self.visit(nslice.stop)
432
+ if self.error:
433
+ return
434
+
435
+ if nslice.step is not None:
436
+ self.visit(nslice.step)
412
437
  if self.error:
413
438
  return
414
439
 
415
440
  else:
416
- self.visit(slice)
441
+ self.visit(nslice)
417
442
 
418
- def check_valid_AssignNode(self, node, message):
443
+ def visit_declaration_AssignNode(self, node, message):
419
444
  if isinstance(node, PysSequenceNode):
420
445
  for element in node.elements:
421
- self.check_valid_AssignNode(element, message)
446
+ self.visit_declaration_AssignNode(element, message)
422
447
  if self.error:
423
448
  return
424
449
 
425
450
  elif isinstance(node, PysSubscriptNode):
426
- self.visit(node.object)
451
+ self.visit(node.target)
427
452
  if self.error:
428
453
  return
429
454
 
430
- self.check_valid_slice_from_SubscriptNode(node.slice)
455
+ self.visit_slice_SubscriptNode(node.slice)
431
456
 
432
457
  elif isinstance(node, PysAttributeNode):
433
- self.visit(node.object)
458
+ self.visit(node.target)
434
459
 
435
460
  elif isinstance(node, PysKeywordNode):
436
- self.throw("cannot assign to {}".format(node.token.value), node.position)
461
+ self.throw(f"cannot assign to {node.token.value}", node.position)
437
462
 
438
463
  elif not isinstance(node, PysIdentifierNode):
439
464
  self.throw(message, node.position)
@@ -0,0 +1,2 @@
1
+ class Pys:
2
+ __slots__ = ()
@@ -0,0 +1,33 @@
1
+ from .bases import Pys
2
+ from .utils.decorators import immutable
3
+ from .utils.general import setimuattr, tostr
4
+
5
+ from io import IOBase
6
+
7
+ @immutable
8
+ class PysBuffer(Pys):
9
+ __slots__ = ()
10
+
11
+ class PysFileBuffer(PysBuffer):
12
+
13
+ __slots__ = ('text', 'name')
14
+
15
+ def __init__(self, text, name=None):
16
+
17
+ if isinstance(text, PysFileBuffer):
18
+ name = tostr(text.name if name is None else name)
19
+ text = tostr(text.text)
20
+
21
+ elif isinstance(text, IOBase):
22
+ name = tostr(text.name if name is None else name)
23
+ text = tostr(text)
24
+
25
+ else:
26
+ name = '<string>' if name is None else tostr(name)
27
+ text = tostr(text)
28
+
29
+ setimuattr(self, 'text', text)
30
+ setimuattr(self, 'name', name)
31
+
32
+ def __repr__(self):
33
+ return f'<FileBuffer from {self.name!r}>'