omextra 0.0.0.dev424__py3-none-any.whl → 0.0.0.dev426__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.
Files changed (68) hide show
  1. omextra/.omlish-manifests.json +14 -0
  2. omextra/__about__.py +3 -1
  3. omextra/defs.py +216 -0
  4. omextra/dynamic.py +219 -0
  5. omextra/formats/__init__.py +0 -0
  6. omextra/formats/json/Json.g4 +77 -0
  7. omextra/formats/json/__init__.py +0 -0
  8. omextra/formats/json/_antlr/JsonLexer.py +109 -0
  9. omextra/formats/json/_antlr/JsonListener.py +61 -0
  10. omextra/formats/json/_antlr/JsonParser.py +457 -0
  11. omextra/formats/json/_antlr/JsonVisitor.py +42 -0
  12. omextra/formats/json/_antlr/__init__.py +0 -0
  13. omextra/io/__init__.py +0 -0
  14. omextra/io/trampoline.py +289 -0
  15. omextra/specs/__init__.py +0 -0
  16. omextra/specs/irc/__init__.py +0 -0
  17. omextra/specs/irc/messages/__init__.py +0 -0
  18. omextra/specs/irc/messages/base.py +50 -0
  19. omextra/specs/irc/messages/formats.py +92 -0
  20. omextra/specs/irc/messages/messages.py +775 -0
  21. omextra/specs/irc/messages/parsing.py +99 -0
  22. omextra/specs/irc/numerics/__init__.py +0 -0
  23. omextra/specs/irc/numerics/formats.py +97 -0
  24. omextra/specs/irc/numerics/numerics.py +865 -0
  25. omextra/specs/irc/numerics/types.py +59 -0
  26. omextra/specs/irc/protocol/LICENSE +11 -0
  27. omextra/specs/irc/protocol/__init__.py +61 -0
  28. omextra/specs/irc/protocol/consts.py +6 -0
  29. omextra/specs/irc/protocol/errors.py +30 -0
  30. omextra/specs/irc/protocol/message.py +21 -0
  31. omextra/specs/irc/protocol/nuh.py +55 -0
  32. omextra/specs/irc/protocol/parsing.py +158 -0
  33. omextra/specs/irc/protocol/rendering.py +153 -0
  34. omextra/specs/irc/protocol/tags.py +102 -0
  35. omextra/specs/irc/protocol/utils.py +30 -0
  36. omextra/specs/proto/Protobuf3.g4 +396 -0
  37. omextra/specs/proto/__init__.py +0 -0
  38. omextra/specs/proto/_antlr/Protobuf3Lexer.py +340 -0
  39. omextra/specs/proto/_antlr/Protobuf3Listener.py +448 -0
  40. omextra/specs/proto/_antlr/Protobuf3Parser.py +3909 -0
  41. omextra/specs/proto/_antlr/Protobuf3Visitor.py +257 -0
  42. omextra/specs/proto/_antlr/__init__.py +0 -0
  43. omextra/specs/proto/nodes.py +54 -0
  44. omextra/specs/proto/parsing.py +98 -0
  45. omextra/sql/__init__.py +0 -0
  46. omextra/sql/parsing/Minisql.g4 +292 -0
  47. omextra/sql/parsing/__init__.py +0 -0
  48. omextra/sql/parsing/_antlr/MinisqlLexer.py +322 -0
  49. omextra/sql/parsing/_antlr/MinisqlListener.py +511 -0
  50. omextra/sql/parsing/_antlr/MinisqlParser.py +3763 -0
  51. omextra/sql/parsing/_antlr/MinisqlVisitor.py +292 -0
  52. omextra/sql/parsing/_antlr/__init__.py +0 -0
  53. omextra/sql/parsing/parsing.py +120 -0
  54. omextra/text/__init__.py +0 -0
  55. omextra/text/antlr/__init__.py +0 -0
  56. omextra/text/antlr/cli/__init__.py +0 -0
  57. omextra/text/antlr/cli/__main__.py +11 -0
  58. omextra/text/antlr/cli/cli.py +62 -0
  59. omextra/text/antlr/cli/consts.py +7 -0
  60. omextra/text/antlr/cli/gen.py +193 -0
  61. {omextra-0.0.0.dev424.dist-info → omextra-0.0.0.dev426.dist-info}/METADATA +2 -3
  62. omextra-0.0.0.dev426.dist-info/RECORD +67 -0
  63. omextra/.manifests.json +0 -1
  64. omextra-0.0.0.dev424.dist-info/RECORD +0 -9
  65. {omextra-0.0.0.dev424.dist-info → omextra-0.0.0.dev426.dist-info}/WHEEL +0 -0
  66. {omextra-0.0.0.dev424.dist-info → omextra-0.0.0.dev426.dist-info}/entry_points.txt +0 -0
  67. {omextra-0.0.0.dev424.dist-info → omextra-0.0.0.dev426.dist-info}/licenses/LICENSE +0 -0
  68. {omextra-0.0.0.dev424.dist-info → omextra-0.0.0.dev426.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,99 @@
1
+ import typing as ta
2
+
3
+ from omlish import dataclasses as dc
4
+
5
+ from .base import Message
6
+ from .formats import MessageFormat
7
+
8
+
9
+ ##
10
+
11
+
12
+ class ParseError(Exception):
13
+ pass
14
+
15
+
16
+ def parse_message(cls: type[Message], params: ta.Sequence[str]) -> Message:
17
+ mf = cls.FORMAT
18
+
19
+ kws: dict = {}
20
+ i = 0
21
+ for fp in mf.params:
22
+ if isinstance(fp, MessageFormat.KwargParam):
23
+ if i >= len(params):
24
+ if not fp.optional:
25
+ raise ParseError(f'Missing param: {fp.name}')
26
+ continue
27
+
28
+ kv: ta.Any
29
+ if (ar := fp.arity) is MessageFormat.KwargParam.Arity.SINGLE:
30
+ kv = params[i]
31
+ i += 1
32
+
33
+ elif ar is MessageFormat.KwargParam.Arity.VARIADIC:
34
+ kv = params[i:]
35
+ i = len(params)
36
+
37
+ elif ar is MessageFormat.KwargParam.Arity.COMMA_LIST:
38
+ kv = params[i].split(',')
39
+ i += 1
40
+
41
+ else:
42
+ raise TypeError(ar)
43
+
44
+ kws[fp.name] = kv
45
+
46
+ elif isinstance(fp, MessageFormat.LiteralParam):
47
+ if i >= len(params):
48
+ raise ParseError('Missing literal param')
49
+
50
+ pv = params[i]
51
+ if fp.text != pv:
52
+ raise ParseError(f'Unexpected literal: {pv}')
53
+ i += 1
54
+
55
+ else:
56
+ raise TypeError(fp)
57
+
58
+ if i != len(params):
59
+ raise ParseError('Unconsumed params')
60
+
61
+ if (up := mf.unpack_params) is not None:
62
+ kws = dict(up(kws))
63
+
64
+ return cls(**kws)
65
+
66
+
67
+ ##
68
+
69
+
70
+ class UnparsedMessage(ta.NamedTuple):
71
+ name: str
72
+ params: ta.Sequence[str]
73
+
74
+
75
+ def unparse_message(msg: Message) -> UnparsedMessage:
76
+ mf = msg.FORMAT
77
+
78
+ kws = {k: v for k, v in dc.asdict(msg).items() if v is not None}
79
+
80
+ if (up := mf.unpack_params) is not None:
81
+ kws = dict(up.backward(kws))
82
+
83
+ params = []
84
+
85
+ for fp in mf.params:
86
+ if isinstance(fp, MessageFormat.KwargParam):
87
+ # FIXME
88
+ raise NotImplementedError
89
+
90
+ elif isinstance(fp, MessageFormat.LiteralParam):
91
+ params.append(fp.text)
92
+
93
+ else:
94
+ raise TypeError(fp)
95
+
96
+ return UnparsedMessage(
97
+ name=mf.name,
98
+ params=params,
99
+ )
File without changes
@@ -0,0 +1,97 @@
1
+ import dataclasses as dc
2
+ import typing as ta
3
+
4
+ from omlish import check
5
+ from omlish import lang
6
+
7
+
8
+ FormatPart: ta.TypeAlias = ta.Union[str, 'Formats.Optional', 'Formats.Variadic']
9
+ FormatParts: ta.TypeAlias = ta.Sequence[FormatPart]
10
+
11
+
12
+ ##
13
+
14
+
15
+ class Formats(lang.Namespace):
16
+ @dc.dataclass(frozen=True)
17
+ class Name:
18
+ name: str
19
+
20
+ @dc.dataclass(frozen=True)
21
+ class Optional:
22
+ body: FormatParts
23
+
24
+ @dc.dataclass(frozen=True)
25
+ class Variadic:
26
+ body: FormatParts
27
+
28
+ #
29
+
30
+ _PARTS_BY_DELIMITERS: ta.Mapping[tuple[str, str], type] = {
31
+ ('[', ']'): Optional,
32
+ ('{', '}'): Variadic,
33
+ }
34
+
35
+ _DELIMITERS_BY_PARTS: ta.Mapping[type, tuple[str, str]] = {v: k for k, v in _PARTS_BY_DELIMITERS.items()}
36
+
37
+ #
38
+
39
+ @staticmethod
40
+ def split_parts(s: str) -> FormatParts:
41
+ stk: list[tuple[str, list]] = [('', [])]
42
+
43
+ p = 0
44
+ while p < len(s):
45
+ n = lang.find_any(s, '{}[]<', p)
46
+
47
+ if n < 0:
48
+ check.state(not stk[-1][0])
49
+ stk[-1][1].append(s[p:])
50
+ break
51
+
52
+ if n != p:
53
+ stk[-1][1].append(s[p:n])
54
+
55
+ d = s[n]
56
+ if d == '<':
57
+ e = s.index('>', n)
58
+ stk[-1][1].append(Formats.Name(s[n + 1:e]))
59
+ p = e + 1
60
+
61
+ elif d in '{[':
62
+ stk.append((d, []))
63
+ p = n + 1
64
+
65
+ elif d in '}]':
66
+ x, l = stk.pop()
67
+ pc = Formats._PARTS_BY_DELIMITERS[(x, d)]
68
+ stk[-1][1].append(pc(l))
69
+ p = n + 1
70
+
71
+ else:
72
+ raise RuntimeError
73
+
74
+ _, ret = check.single(stk)
75
+ return ret
76
+
77
+ #
78
+
79
+ @staticmethod
80
+ def render_parts(p: FormatPart | FormatParts) -> ta.Iterator[str]:
81
+ if isinstance(p, str):
82
+ yield p
83
+
84
+ elif isinstance(p, Formats.Name):
85
+ yield '<'
86
+ yield p.name
87
+ yield '>'
88
+
89
+ elif isinstance(p, (Formats.Optional, Formats.Variadic)):
90
+ l, r = Formats._DELIMITERS_BY_PARTS[type(p)]
91
+ yield l
92
+ yield from Formats.render_parts(p.body)
93
+ yield r
94
+
95
+ else:
96
+ for c in p:
97
+ yield from Formats.render_parts(c)