omlish 0.0.0.dev104__py3-none-any.whl → 0.0.0.dev105__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,13 +5,18 @@ import json
5
5
  import typing as ta
6
6
 
7
7
  from ... import lang
8
+ from . import consts
8
9
 
9
10
 
10
11
  I = ta.TypeVar('I')
12
+ Scalar: ta.TypeAlias = bool | int | float | str | None
11
13
 
14
+ SCALAR_TYPES: tuple[type, ...] = (bool, int, float, str, type(None))
12
15
 
13
- class JsonRendererOut(ta.Protocol):
14
- def write(self, s: str) -> ta.Any: ...
16
+ MULTILINE_SEPARATORS = consts.Separators(',', ': ')
17
+
18
+
19
+ ##
15
20
 
16
21
 
17
22
  class AbstractJsonRenderer(lang.Abstract, ta.Generic[I]):
@@ -21,33 +26,33 @@ class AbstractJsonRenderer(lang.Abstract, ta.Generic[I]):
21
26
 
22
27
  def __init__(
23
28
  self,
24
- out: JsonRendererOut,
25
- *,
26
29
  indent: int | str | None = None,
27
30
  separators: tuple[str, str] | None = None,
28
31
  sort_keys: bool = False,
29
32
  style: ta.Callable[[ta.Any, State], tuple[str, str]] | None = None,
33
+ ensure_ascii: bool = True,
30
34
  ) -> None:
31
35
  super().__init__()
32
36
 
33
- self._out = out
34
37
  self._sort_keys = sort_keys
35
38
  self._style = style
39
+ self._ensure_ascii = ensure_ascii
36
40
 
37
41
  if isinstance(indent, (str, int)):
38
42
  self._indent = (' ' * indent) if isinstance(indent, int) else indent
39
43
  self._endl = '\n'
40
44
  if separators is None:
41
- separators = (',', ': ')
45
+ separators = MULTILINE_SEPARATORS
42
46
  elif indent is None:
43
47
  self._indent = self._endl = ''
44
48
  if separators is None:
45
- separators = (', ', ': ')
49
+ separators = consts.PRETTY_SEPARATORS
46
50
  else:
47
51
  raise TypeError(indent)
48
52
  self._comma, self._colon = separators
49
53
 
50
54
  self._level = 0
55
+ self._indent_cache: dict[int, str] = {}
51
56
 
52
57
  _literals: ta.ClassVar[ta.Mapping[ta.Any, str]] = {
53
58
  True: 'true',
@@ -55,28 +60,62 @@ class AbstractJsonRenderer(lang.Abstract, ta.Generic[I]):
55
60
  None: 'null',
56
61
  }
57
62
 
58
- def _write(self, s: str) -> None:
59
- if s:
60
- self._out.write(s)
63
+ def _get_indent(self) -> str:
64
+ if not self._indent:
65
+ return ''
61
66
 
62
- def _write_indent(self) -> None:
63
- if self._indent:
64
- self._write(self._endl)
65
- if self._level:
66
- self._write(self._indent * self._level)
67
+ if not self._level:
68
+ return self._endl
67
69
 
70
+ try:
71
+ return self._indent_cache[self._level]
72
+ except KeyError:
73
+ pass
74
+
75
+ ret = self._endl + (self._indent * self._level)
76
+ self._indent_cache[self._level] = ret
77
+ return ret
78
+
79
+ def _format_scalar(self, o: Scalar) -> str:
80
+ if o is None or isinstance(o, bool):
81
+ return self._literals[o]
82
+
83
+ elif isinstance(o, (str, int, float)):
84
+ return json.dumps(o, ensure_ascii=self._ensure_ascii)
85
+
86
+ else:
87
+ raise TypeError(o)
88
+
89
+ @classmethod
68
90
  @abc.abstractmethod
69
- def render(self, i: I) -> None:
91
+ def render_str(cls, i: I, /, **kwargs: ta.Any) -> str:
70
92
  raise NotImplementedError
71
93
 
72
- @classmethod
73
- def render_str(cls, i: I, **kwargs: ta.Any) -> str:
74
- out = io.StringIO()
75
- cls(out, **kwargs).render(i)
76
- return out.getvalue()
94
+
95
+ ##
96
+
97
+
98
+ class JsonRendererOut(ta.Protocol):
99
+ def write(self, s: str) -> ta.Any: ...
77
100
 
78
101
 
79
102
  class JsonRenderer(AbstractJsonRenderer[ta.Any]):
103
+ def __init__(
104
+ self,
105
+ out: JsonRendererOut,
106
+ **kwargs: ta.Any,
107
+ ) -> None:
108
+ super().__init__(**kwargs)
109
+
110
+ self._out = out
111
+
112
+ def _write(self, s: str) -> None:
113
+ if s:
114
+ self._out.write(s)
115
+
116
+ def _write_indent(self) -> None:
117
+ self._write(self._get_indent())
118
+
80
119
  def _render(
81
120
  self,
82
121
  o: ta.Any,
@@ -88,11 +127,8 @@ class JsonRenderer(AbstractJsonRenderer[ta.Any]):
88
127
  else:
89
128
  post = None
90
129
 
91
- if o is None or isinstance(o, bool):
92
- self._write(self._literals[o])
93
-
94
- elif isinstance(o, (str, int, float)):
95
- self._write(json.dumps(o))
130
+ if isinstance(o, SCALAR_TYPES):
131
+ self._write(self._format_scalar(o)) # type: ignore
96
132
 
97
133
  elif isinstance(o, ta.Mapping):
98
134
  self._write('{')
@@ -133,3 +169,9 @@ class JsonRenderer(AbstractJsonRenderer[ta.Any]):
133
169
 
134
170
  def render(self, o: ta.Any) -> None:
135
171
  self._render(o)
172
+
173
+ @classmethod
174
+ def render_str(cls, i: ta.Any, /, **kwargs: ta.Any) -> str:
175
+ out = io.StringIO()
176
+ cls(out, **kwargs).render(i)
177
+ return out.getvalue()
@@ -36,7 +36,7 @@ class JsonObjectBuilder:
36
36
  if self._stack:
37
37
  raise self.StateError
38
38
 
39
- def _emit_value(self, v):
39
+ def _emit_value(self, v: ta.Any) -> ta.Iterable[ta.Any]:
40
40
  if not (stk := self._stack):
41
41
  return (v,)
42
42
 
@@ -60,7 +60,7 @@ class JsonObjectBuilder:
60
60
  else:
61
61
  raise self.StateError
62
62
 
63
- def __call__(self, e: JsonStreamParserEvent) -> ta.Any:
63
+ def __call__(self, e: JsonStreamParserEvent) -> ta.Iterable[ta.Any]:
64
64
  stk = self._stack
65
65
 
66
66
  #
@@ -1,8 +1,8 @@
1
- import json
1
+ import io
2
2
  import typing as ta
3
3
 
4
+ from ..render import SCALAR_TYPES
4
5
  from ..render import AbstractJsonRenderer
5
- from ..render import JsonRendererOut
6
6
  from .parse import BeginArray
7
7
  from .parse import BeginObject
8
8
  from .parse import EndArray
@@ -17,7 +17,6 @@ from .parse import Key
17
17
  class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]]):
18
18
  def __init__(
19
19
  self,
20
- out: JsonRendererOut,
21
20
  *,
22
21
  delimiter: str = '',
23
22
  sort_keys: bool = False,
@@ -28,7 +27,7 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
28
27
 
29
28
  self._delimiter = delimiter
30
29
 
31
- super().__init__(out, **kwargs)
30
+ super().__init__(**kwargs)
32
31
 
33
32
  self._stack: list[tuple[ta.Literal['OBJECT', 'ARRAY'], int]] = []
34
33
  self._need_delimit = False
@@ -37,41 +36,38 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
37
36
  self,
38
37
  o: ta.Any,
39
38
  state: AbstractJsonRenderer.State = AbstractJsonRenderer.State.VALUE,
40
- ) -> None:
39
+ ) -> ta.Generator[str, None, None]:
41
40
  if self._style is not None:
42
41
  pre, post = self._style(o, state)
43
- self._write(pre)
42
+ yield pre
44
43
  else:
45
44
  post = None
46
45
 
47
- if o is None or isinstance(o, bool):
48
- self._write(self._literals[o])
49
-
50
- elif isinstance(o, (str, int, float)):
51
- self._write(json.dumps(o))
46
+ if isinstance(o, SCALAR_TYPES):
47
+ yield self._format_scalar(o) # type: ignore
52
48
 
53
49
  else:
54
50
  raise TypeError(o)
55
51
 
56
52
  if post:
57
- self._write(post)
53
+ yield post
58
54
 
59
- def _render(self, e: JsonStreamParserEvent) -> None:
55
+ def _render(self, e: JsonStreamParserEvent) -> ta.Generator[str, None, None]:
60
56
  if self._need_delimit:
61
- self._write(self._delimiter)
57
+ yield self._delimiter
62
58
  self._need_delimit = False
63
59
 
64
60
  if e != EndArray and self._stack and (tt := self._stack[-1])[0] == 'ARRAY':
65
61
  if tt[1]:
66
- self._write(self._comma)
67
- self._write_indent()
62
+ yield self._comma
63
+ yield self._get_indent()
68
64
 
69
65
  self._stack[-1] = ('ARRAY', tt[1] + 1)
70
66
 
71
67
  #
72
68
 
73
69
  if e is None or isinstance(e, (str, int, float, bool)):
74
- self._render_value(e)
70
+ yield from self._render_value(e)
75
71
  if not self._stack:
76
72
  self._need_delimit = True
77
73
 
@@ -79,7 +75,7 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
79
75
 
80
76
  elif e is BeginObject:
81
77
  self._stack.append(('OBJECT', 0))
82
- self._write('{')
78
+ yield '{'
83
79
  self._level += 1
84
80
 
85
81
  elif isinstance(e, Key):
@@ -87,10 +83,10 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
87
83
  raise Exception
88
84
 
89
85
  if tt[1]:
90
- self._write(self._comma)
91
- self._write_indent()
92
- self._render_value(e.key, AbstractJsonRenderer.State.KEY)
93
- self._write(self._colon)
86
+ yield self._comma
87
+ yield self._get_indent()
88
+ yield from self._render_value(e.key, AbstractJsonRenderer.State.KEY)
89
+ yield self._colon
94
90
 
95
91
  self._stack.append(('OBJECT', tt[1] + 1))
96
92
 
@@ -100,8 +96,8 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
100
96
 
101
97
  self._level -= 1
102
98
  if tt[1]:
103
- self._write_indent()
104
- self._write('}')
99
+ yield self._get_indent()
100
+ yield '}'
105
101
  if not self._stack:
106
102
  self._need_delimit = True
107
103
 
@@ -109,7 +105,7 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
109
105
 
110
106
  elif e is BeginArray:
111
107
  self._stack.append(('ARRAY', 0))
112
- self._write('[')
108
+ yield '['
113
109
  self._level += 1
114
110
 
115
111
  elif e is EndArray:
@@ -118,8 +114,8 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
118
114
 
119
115
  self._level -= 1
120
116
  if tt[1]:
121
- self._write_indent()
122
- self._write(']')
117
+ yield self._get_indent()
118
+ yield ']'
123
119
  if not self._stack:
124
120
  self._need_delimit = True
125
121
 
@@ -128,6 +124,13 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
128
124
  else:
129
125
  raise TypeError(e)
130
126
 
131
- def render(self, events: ta.Iterable[JsonStreamParserEvent]) -> None:
127
+ def render(self, events: ta.Iterable[JsonStreamParserEvent]) -> ta.Generator[str, None, None]:
132
128
  for e in events:
133
- self._render(e)
129
+ yield from self._render(e)
130
+
131
+ @classmethod
132
+ def render_str(cls, i: ta.Iterable[JsonStreamParserEvent], /, **kwargs: ta.Any) -> str:
133
+ out = io.StringIO()
134
+ for s in cls(**kwargs).render(i):
135
+ out.write(s)
136
+ return out.getvalue()
omlish/io/trampoline.py CHANGED
@@ -1,7 +1,3 @@
1
- """
2
- TODO:
3
- - https://docs.python.org/3/library/zlib.html#zlib.compressobj
4
- """
5
1
  import abc
6
2
  import contextlib
7
3
  import io
@@ -1,114 +1,119 @@
1
- # AST nodes have this structure:
2
- # {'type': <node type>', children: [], 'value': ''}
1
+ import typing as ta
3
2
 
4
3
 
5
- def arithmetic_unary(operator, expression):
4
+ class Node(ta.TypedDict):
5
+ type: str
6
+ children: list['Node']
7
+ value: ta.NotRequired[ta.Any]
8
+
9
+
10
+ def arithmetic_unary(operator, expression) -> Node:
6
11
  return {'type': 'arithmetic_unary', 'children': [expression], 'value': operator}
7
12
 
8
13
 
9
- def arithmetic(operator, left, right):
14
+ def arithmetic(operator, left, right) -> Node:
10
15
  return {'type': 'arithmetic', 'children': [left, right], 'value': operator}
11
16
 
12
17
 
13
- def assign(name, expr):
18
+ def assign(name, expr) -> Node:
14
19
  return {'type': 'assign', 'children': [expr], 'value': name}
15
20
 
16
21
 
17
- def comparator(name, first, second):
22
+ def comparator(name, first, second) -> Node:
18
23
  return {'type': 'comparator', 'children': [first, second], 'value': name}
19
24
 
20
25
 
21
- def current_node():
26
+ def current_node() -> Node:
22
27
  return {'type': 'current', 'children': []}
23
28
 
24
29
 
25
- def root_node():
30
+ def root_node() -> Node:
26
31
  return {'type': 'root', 'children': []}
27
32
 
28
33
 
29
- def expref(expression):
34
+ def expref(expression) -> Node:
30
35
  return {'type': 'expref', 'children': [expression]}
31
36
 
32
37
 
33
- def function_expression(name, args):
38
+ def function_expression(name, args) -> Node:
34
39
  return {'type': 'function_expression', 'children': args, 'value': name}
35
40
 
36
41
 
37
- def field(name):
42
+ def field(name) -> Node:
38
43
  return {'type': 'field', 'children': [], 'value': name}
39
44
 
40
45
 
41
- def filter_projection(left, right, comparator):
46
+ def filter_projection(left, right, comparator) -> Node:
42
47
  return {'type': 'filter_projection', 'children': [left, right, comparator]}
43
48
 
44
49
 
45
- def flatten(node):
50
+ def flatten(node) -> Node:
46
51
  return {'type': 'flatten', 'children': [node]}
47
52
 
48
53
 
49
- def identity():
54
+ def identity() -> Node:
50
55
  return {'type': 'identity', 'children': []}
51
56
 
52
57
 
53
- def index(index):
58
+ def index(index) -> Node:
54
59
  return {'type': 'index', 'value': index, 'children': []}
55
60
 
56
61
 
57
- def index_expression(children):
62
+ def index_expression(children) -> Node:
58
63
  return {'type': 'index_expression', 'children': children}
59
64
 
60
65
 
61
- def key_val_pair(key_name, node):
66
+ def key_val_pair(key_name, node) -> Node:
62
67
  return {'type': 'key_val_pair', 'children': [node], 'value': key_name}
63
68
 
64
69
 
65
- def let_expression(bindings, expr):
70
+ def let_expression(bindings, expr) -> Node:
66
71
  return {'type': 'let_expression', 'children': [*bindings, expr]}
67
72
 
68
73
 
69
- def literal(literal_value):
74
+ def literal(literal_value) -> Node:
70
75
  return {'type': 'literal', 'value': literal_value, 'children': []}
71
76
 
72
77
 
73
- def multi_select_dict(nodes):
78
+ def multi_select_dict(nodes) -> Node:
74
79
  return {'type': 'multi_select_dict', 'children': nodes}
75
80
 
76
81
 
77
- def multi_select_list(nodes):
82
+ def multi_select_list(nodes) -> Node:
78
83
  return {'type': 'multi_select_list', 'children': nodes}
79
84
 
80
85
 
81
- def or_expression(left, right):
86
+ def or_expression(left, right) -> Node:
82
87
  return {'type': 'or_expression', 'children': [left, right]}
83
88
 
84
89
 
85
- def and_expression(left, right):
90
+ def and_expression(left, right) -> Node:
86
91
  return {'type': 'and_expression', 'children': [left, right]}
87
92
 
88
93
 
89
- def not_expression(expr):
94
+ def not_expression(expr) -> Node:
90
95
  return {'type': 'not_expression', 'children': [expr]}
91
96
 
92
97
 
93
- def pipe(left, right):
98
+ def pipe(left: Node, right: Node) -> Node:
94
99
  return {'type': 'pipe', 'children': [left, right]}
95
100
 
96
101
 
97
- def projection(left, right):
102
+ def projection(left: Node, right: Node) -> Node:
98
103
  return {'type': 'projection', 'children': [left, right]}
99
104
 
100
105
 
101
- def subexpression(children):
106
+ def subexpression(children) -> Node:
102
107
  return {'type': 'subexpression', 'children': children}
103
108
 
104
109
 
105
- def slice(start, end, step): # noqa
110
+ def slice(start, end, step) -> Node: # noqa
106
111
  return {'type': 'slice', 'children': [start, end, step]}
107
112
 
108
113
 
109
- def value_projection(left, right):
114
+ def value_projection(left: Node, right: Node) -> Node:
110
115
  return {'type': 'value_projection', 'children': [left, right]}
111
116
 
112
117
 
113
- def variable_ref(name):
118
+ def variable_ref(name: str) -> Node:
114
119
  return {'type': 'variable_ref', 'children': [], 'value': name}
@@ -1,3 +1,6 @@
1
+ import typing as ta
2
+
3
+
1
4
  class JmespathError(ValueError):
2
5
  pass
3
6
 
@@ -10,15 +13,15 @@ class ParseError(JmespathError):
10
13
  lex_position,
11
14
  token_value,
12
15
  token_type,
13
- msg=_ERROR_MESSAGE,
14
- ):
16
+ msg: str = _ERROR_MESSAGE,
17
+ ) -> None:
15
18
  super().__init__(lex_position, token_value, token_type)
16
19
  self.lex_position = lex_position
17
20
  self.token_value = token_value
18
21
  self.token_type = token_type.upper()
19
22
  self.msg = msg
20
23
  # Whatever catches the ParseError can fill in the full expression
21
- self.expression = None
24
+ self.expression: ta.Any = None
22
25
 
23
26
  def __str__(self):
24
27
  # self.lex_position +1 to account for the starting double quote char.
@@ -46,7 +49,7 @@ class IncompleteExpressionError(ParseError):
46
49
 
47
50
 
48
51
  class LexerError(ParseError):
49
- def __init__(self, lexer_position, lexer_value, message, expression=None):
52
+ def __init__(self, lexer_position, lexer_value, message, expression: ta.Any | None = None):
50
53
  self.lexer_position = lexer_position
51
54
  self.lexer_value = lexer_value
52
55
  self.message = message
@@ -44,6 +44,7 @@ def signature(*arguments):
44
44
  class FunctionRegistry(type):
45
45
  def __init__(cls, name, bases, attrs):
46
46
  cls._populate_function_table()
47
+
47
48
  super().__init__(name, bases, attrs)
48
49
 
49
50
  def _populate_function_table(cls):
@@ -3,8 +3,17 @@ import string
3
3
  import typing as ta
4
4
  import warnings
5
5
 
6
+ from ... import check
6
7
  from .exceptions import EmptyExpressionError
7
8
  from .exceptions import LexerError
9
+ from .visitor import Options
10
+
11
+
12
+ class Token(ta.TypedDict):
13
+ type: str
14
+ value: ta.Any
15
+ start: int
16
+ end: int
8
17
 
9
18
 
10
19
  class Lexer:
@@ -33,10 +42,13 @@ class Lexer:
33
42
  '\u00f7': 'divide',
34
43
  }
35
44
 
36
- def __init__(self):
45
+ def __init__(self) -> None:
46
+ super().__init__()
47
+
37
48
  self._enable_legacy_literals = False
49
+ self._current: str | None = None
38
50
 
39
- def tokenize(self, expression, options=None):
51
+ def tokenize(self, expression: str, options: Options | None = None) -> ta.Generator[Token, None, None]:
40
52
  if options is not None:
41
53
  self._enable_legacy_literals = options.enable_legacy_literals
42
54
 
@@ -205,18 +217,18 @@ class Lexer:
205
217
  'end': self._length,
206
218
  }
207
219
 
208
- def _consume_number(self):
220
+ def _consume_number(self) -> str:
209
221
  start = self._position # noqa
210
222
 
211
- buff = self._current
223
+ buff = check.not_none(self._current)
212
224
  while self._next() in self.VALID_NUMBER:
213
- buff += self._current
225
+ buff += check.not_none(self._current)
214
226
  return buff
215
227
 
216
- def _consume_variable(self):
228
+ def _consume_variable(self) -> Token:
217
229
  start = self._position
218
230
 
219
- buff = self._current
231
+ buff = check.not_none(self._current)
220
232
  self._next()
221
233
  if self._current not in self.START_IDENTIFIER:
222
234
  raise LexerError(
@@ -225,9 +237,9 @@ class Lexer:
225
237
  message=f'Invalid variable starting character {self._current}',
226
238
  )
227
239
 
228
- buff += self._current
240
+ buff += check.not_none(self._current)
229
241
  while self._next() in self.VALID_IDENTIFIER:
230
- buff += self._current
242
+ buff += check.not_none(self._current)
231
243
 
232
244
  return {
233
245
  'type': 'variable',
@@ -236,21 +248,21 @@ class Lexer:
236
248
  'end': start + len(buff),
237
249
  }
238
250
 
239
- def _peek_may_be_valid_unquoted_identifier(self):
251
+ def _peek_may_be_valid_unquoted_identifier(self) -> bool:
240
252
  if (self._position == self._length - 1):
241
253
  return False
242
254
  else:
243
255
  nxt = self._chars[self._position + 1]
244
256
  return nxt in self.START_IDENTIFIER
245
257
 
246
- def _peek_is_next_digit(self):
258
+ def _peek_is_next_digit(self) -> bool:
247
259
  if (self._position == self._length - 1):
248
260
  return False
249
261
  else:
250
262
  nxt = self._chars[self._position + 1]
251
263
  return nxt in self.VALID_NUMBER
252
264
 
253
- def _initialize_for_expression(self, expression):
265
+ def _initialize_for_expression(self, expression: str) -> None:
254
266
  if not expression:
255
267
  raise EmptyExpressionError
256
268
  self._position = 0
@@ -259,7 +271,7 @@ class Lexer:
259
271
  self._current = self._chars[self._position]
260
272
  self._length = len(self._expression)
261
273
 
262
- def _next(self):
274
+ def _next(self) -> str | None:
263
275
  if self._position == self._length - 1:
264
276
  self._current = None
265
277
  else:
@@ -267,7 +279,7 @@ class Lexer:
267
279
  self._current = self._chars[self._position]
268
280
  return self._current
269
281
 
270
- def _consume_until(self, delimiter):
282
+ def _consume_until(self, delimiter: str) -> str:
271
283
  # Consume until the delimiter is reached, allowing for the delimiter to be escaped with "\".
272
284
  start = self._position
273
285
 
@@ -293,12 +305,11 @@ class Lexer:
293
305
  self._next()
294
306
  return buff
295
307
 
296
- def _consume_literal(self):
308
+ def _consume_literal(self) -> Token:
297
309
  start = self._position
298
310
 
299
311
  token = self._consume_until('`')
300
312
  lexeme = token.replace('\\`', '`')
301
- parsed_json = None
302
313
  try:
303
314
  # Assume it is valid JSON and attempt to parse.
304
315
  parsed_json = json.loads(lexeme)
@@ -331,7 +342,7 @@ class Lexer:
331
342
  'end': token_len,
332
343
  }
333
344
 
334
- def _consume_quoted_identifier(self):
345
+ def _consume_quoted_identifier(self) -> Token:
335
346
  start = self._position
336
347
 
337
348
  lexeme = '"' + self._consume_until('"') + '"'
@@ -352,7 +363,7 @@ class Lexer:
352
363
  message=error_message,
353
364
  )
354
365
 
355
- def _consume_raw_string_literal(self):
366
+ def _consume_raw_string_literal(self) -> Token:
356
367
  start = self._position
357
368
 
358
369
  lexeme = self._consume_until("'") \
@@ -367,10 +378,10 @@ class Lexer:
367
378
  'end': token_len,
368
379
  }
369
380
 
370
- def _match_or_else(self, expected, match_type, else_type):
381
+ def _match_or_else(self, expected: str, match_type: str, else_type: str) -> Token:
371
382
  start = self._position
372
383
 
373
- current = self._current
384
+ current = check.not_none(self._current)
374
385
  next_char = self._next()
375
386
  if next_char == expected:
376
387
  self._next()