omlish 0.0.0.dev212__py3-none-any.whl → 0.0.0.dev214__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. omlish/.manifests.json +4 -4
  2. omlish/__about__.py +3 -5
  3. omlish/antlr/__init__.py +3 -0
  4. omlish/antlr/parsing.py +34 -2
  5. omlish/asyncs/asyncio/asyncio.py +34 -0
  6. omlish/asyncs/ioproxy/__init__.py +1 -0
  7. omlish/asyncs/ioproxy/all.py +32 -0
  8. omlish/asyncs/ioproxy/io.py +242 -0
  9. omlish/asyncs/ioproxy/proxier.py +154 -0
  10. omlish/asyncs/ioproxy/proxy.py +141 -0
  11. omlish/asyncs/ioproxy/typing.py +108 -0
  12. omlish/check.py +1 -0
  13. omlish/configs/processing/matching.py +9 -1
  14. omlish/formats/json/stream/lex.py +1 -0
  15. omlish/formats/json5/Json5.g4 +172 -0
  16. omlish/formats/json5/__init__.py +8 -0
  17. omlish/formats/json5/_antlr/Json5Lexer.py +353 -0
  18. omlish/formats/json5/_antlr/Json5Listener.py +78 -0
  19. omlish/formats/json5/_antlr/Json5Parser.py +616 -0
  20. omlish/formats/json5/_antlr/Json5Visitor.py +51 -0
  21. omlish/formats/json5/_antlr/__init__.py +0 -0
  22. omlish/formats/{json5.py → json5/codec.py} +6 -11
  23. omlish/formats/json5/errors.py +2 -0
  24. omlish/formats/json5/literals.py +130 -0
  25. omlish/formats/json5/parsing.py +79 -0
  26. omlish/io/abc.py +1 -0
  27. omlish/lang/__init__.py +2 -0
  28. omlish/lang/imports.py +4 -0
  29. omlish/lang/strings.py +33 -1
  30. omlish/lite/check.py +23 -0
  31. omlish/lite/contextmanagers.py +39 -0
  32. omlish/os/files.py +17 -30
  33. omlish/os/temp.py +50 -0
  34. {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/METADATA +5 -7
  35. {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/RECORD +39 -22
  36. {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/LICENSE +0 -0
  37. {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/WHEEL +0 -0
  38. {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/entry_points.txt +0 -0
  39. {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,141 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import functools
4
+ import inspect
5
+ import typing as ta
6
+
7
+ from ...lite.check import check
8
+
9
+
10
+ AsyncIoProxyRunner = ta.Callable[[ta.Callable], ta.Awaitable] # ta.TypeAlias
11
+
12
+
13
+ ##
14
+
15
+
16
+ _ASYNC_IO_PROXY_WRAPPER_NAME_ATTRS = ('__name__', '__qualname__')
17
+ _ASYNC_IO_PROXY_WRAPPER_ASSIGNMENTS = tuple(
18
+ a
19
+ for a in functools.WRAPPER_ASSIGNMENTS
20
+ if a not in _ASYNC_IO_PROXY_WRAPPER_NAME_ATTRS
21
+ )
22
+
23
+
24
+ def async_io_proxy_fn(fn, runner, *, result_wrapper=None):
25
+ @functools.wraps(fn, assigned=_ASYNC_IO_PROXY_WRAPPER_ASSIGNMENTS)
26
+ async def run(*args, **kwargs):
27
+ ret = await runner(functools.partial(fn, *args, **kwargs))
28
+ if result_wrapper is not None:
29
+ ret = result_wrapper(ret)
30
+ return ret
31
+
32
+ for na in _ASYNC_IO_PROXY_WRAPPER_NAME_ATTRS:
33
+ setattr(run, na, f'{getattr(run, na)}:{getattr(fn, na)}')
34
+
35
+ return run
36
+
37
+
38
+ ##
39
+
40
+
41
+ @dc.dataclass(frozen=True)
42
+ class AsyncIoProxyTarget:
43
+ obj: ta.Any
44
+ runner: AsyncIoProxyRunner
45
+
46
+
47
+ class AsyncIoProxy:
48
+ def __init__(self, target: AsyncIoProxyTarget) -> None:
49
+ super().__init__()
50
+
51
+ self._target = check.isinstance(target, AsyncIoProxyTarget)
52
+
53
+ #
54
+
55
+ class _Descriptor:
56
+ def __init__(self, name) -> None:
57
+ super().__init__()
58
+
59
+ self._name = name
60
+
61
+ def __get__(self, instance, owner=None):
62
+ if instance is None:
63
+ return self
64
+
65
+ target: AsyncIoProxyTarget = instance._target # noqa
66
+ v = self._get(target, instance)
67
+
68
+ setattr(instance, self._name, v)
69
+ return v
70
+
71
+ def _get(self, target: AsyncIoProxyTarget, instance: ta.Any) -> ta.Any:
72
+ raise NotImplementedError
73
+
74
+ class _Property(_Descriptor):
75
+ def _get(self, target: AsyncIoProxyTarget, instance: ta.Any) -> ta.Any:
76
+ return getattr(target.obj, self._name)
77
+
78
+ class _Method(_Descriptor):
79
+ def __call__(self, instance, *args, **kwargs):
80
+ return self.__get__(instance)(*args, **kwargs)
81
+
82
+ class _SyncMethod(_Method):
83
+ def _get(self, target: AsyncIoProxyTarget, instance: ta.Any) -> ta.Any:
84
+ return getattr(target.obj, self._name)
85
+
86
+ class _AsyncMethod(_Method):
87
+ SPECIAL_METHOD_NAMES: ta.ClassVar[ta.Mapping[str, str]] = {
88
+ '__aenter__': '__enter__',
89
+ '__aexit__': '__exit__',
90
+ }
91
+
92
+ def _get(self, target: AsyncIoProxyTarget, instance: ta.Any) -> ta.Any:
93
+ fa = self.SPECIAL_METHOD_NAMES.get(self._name, self._name)
94
+ fn = getattr(target.obj, fa)
95
+ if fa == '__enter__':
96
+ result_wrapper = lambda _: instance
97
+ else:
98
+ result_wrapper = None
99
+ run = async_io_proxy_fn(fn, target.runner, result_wrapper=result_wrapper)
100
+ return run
101
+
102
+ #
103
+
104
+ __proxied_cls__: ta.ClassVar[type]
105
+
106
+ def __init_subclass__(cls, *, proxied_cls=None, **kwargs): # noqa
107
+ super().__init_subclass__()
108
+
109
+ cls.__proxied_cls__ = check.isinstance(proxied_cls, (type, None))
110
+
111
+ for n, v in dict(cls.__dict__).items():
112
+ if n.startswith('_') and n not in cls._AsyncMethod.SPECIAL_METHOD_NAMES:
113
+ continue
114
+
115
+ if isinstance(v, property):
116
+ setattr(cls, n, cls._Property(n))
117
+
118
+ elif callable(v):
119
+ if inspect.iscoroutinefunction(v):
120
+ setattr(cls, n, cls._AsyncMethod(n))
121
+ else:
122
+ setattr(cls, n, cls._SyncMethod(n))
123
+
124
+ else:
125
+ raise TypeError(v)
126
+
127
+
128
+ ##
129
+
130
+
131
+ @functools.singledispatch
132
+ def async_io_proxy_cls_for(obj: ta.Any) -> ta.Optional[ta.Type[AsyncIoProxy]]:
133
+ return None
134
+
135
+
136
+ def _register_async_io_proxy_cls(cls):
137
+ async_io_proxy_cls_for.register(
138
+ check.isinstance(cls.__dict__['__proxied_cls__'], type),
139
+ lambda obj: cls,
140
+ )
141
+ return cls
@@ -0,0 +1,108 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from .proxy import AsyncIoProxy
5
+ from .proxy import _register_async_io_proxy_cls
6
+
7
+
8
+ SelfT = ta.TypeVar('SelfT')
9
+
10
+ AnyStrT = ta.TypeVar('AnyStrT', bytes, str)
11
+
12
+
13
+ ##
14
+
15
+
16
+ @_register_async_io_proxy_cls
17
+ class TypingIO_AsyncIoProxy(AsyncIoProxy, ta.Generic[AnyStrT], proxied_cls=ta.IO): # noqa
18
+ @property
19
+ def mode(self) -> str:
20
+ raise TypeError
21
+
22
+ @property
23
+ def name(self) -> str:
24
+ raise TypeError
25
+
26
+ async def close(self) -> None:
27
+ raise TypeError
28
+
29
+ @property
30
+ def closed(self) -> bool:
31
+ raise TypeError
32
+
33
+ def fileno(self) -> int:
34
+ raise TypeError
35
+
36
+ async def flush(self) -> None:
37
+ raise TypeError
38
+
39
+ def isatty(self) -> bool:
40
+ raise TypeError
41
+
42
+ async def read(self, n: int = -1) -> AnyStrT:
43
+ raise TypeError
44
+
45
+ def readable(self) -> bool:
46
+ raise TypeError
47
+
48
+ async def readline(self, limit: int = -1) -> AnyStrT:
49
+ raise TypeError
50
+
51
+ async def readlines(self, hint: int = -1) -> ta.List[AnyStrT]:
52
+ raise TypeError
53
+
54
+ async def seek(self, offset: int, whence: int = 0) -> int:
55
+ raise TypeError
56
+
57
+ def seekable(self) -> bool:
58
+ raise TypeError
59
+
60
+ async def tell(self) -> int:
61
+ raise TypeError
62
+
63
+ async def truncate(self, size: ta.Optional[int] = None) -> int:
64
+ raise TypeError
65
+
66
+ def writable(self) -> bool:
67
+ raise TypeError
68
+
69
+ async def write(self, s: AnyStrT) -> int:
70
+ raise TypeError
71
+
72
+ async def writelines(self, lines: ta.List[AnyStrT]) -> None:
73
+ raise TypeError
74
+
75
+ async def __aenter__(self: SelfT) -> SelfT:
76
+ raise TypeError
77
+
78
+ async def __aexit__(self, exc_type, exc_value, exc_tb):
79
+ raise TypeError
80
+
81
+
82
+ @_register_async_io_proxy_cls
83
+ class TypingBinaryIO_AsyncIoProxy(TypingIO_AsyncIoProxy[bytes], proxied_cls=ta.BinaryIO): # noqa
84
+ def write(self, s: ta.Union[bytes, bytearray]) -> int: # type: ignore[override]
85
+ raise TypeError
86
+
87
+
88
+ @_register_async_io_proxy_cls
89
+ class TypingTextIO_AsyncIoProxy(TypingIO_AsyncIoProxy[str], proxied_cls=ta.TextIO): # noqa
90
+ # @property
91
+ # def buffer(self) -> BinaryIO:
92
+ # pass
93
+
94
+ @property
95
+ def encoding(self) -> str:
96
+ raise TypeError
97
+
98
+ @property
99
+ def errors(self) -> ta.Optional[str]:
100
+ raise TypeError
101
+
102
+ @property
103
+ def line_buffering(self) -> bool:
104
+ raise TypeError
105
+
106
+ @property
107
+ def newlines(self) -> ta.Any:
108
+ raise TypeError
omlish/check.py CHANGED
@@ -85,6 +85,7 @@ not_none = check.not_none
85
85
  #
86
86
 
87
87
  equal = check.equal
88
+ not_equal = check.not_equal
88
89
  is_ = check.is_
89
90
  is_not = check.is_not
90
91
  callable = check.callable # noqa
@@ -29,8 +29,16 @@ class MatchingConfigRewriter(ConfigRewriter):
29
29
  self._paths = frozenset(check.isinstance(p, tuple) for p in paths)
30
30
  self._recurse = recurse
31
31
 
32
+ def match_path(self, path: ConfigRewriterPath) -> bool:
33
+ for test in self._paths:
34
+ if len(test) != len(path):
35
+ continue
36
+ if all(t is None or p == t for p, t in zip(path, test)):
37
+ return True
38
+ return False
39
+
32
40
  def rewrite(self, ctx: ConfigRewriter.Context[T]) -> T:
33
- if ctx.path in self._paths:
41
+ if self.match_path(ctx.path):
34
42
  no = self._fn(ctx.obj)
35
43
  if not self._recurse:
36
44
  return no
@@ -4,6 +4,7 @@ TODO:
4
4
  - max recursion depth
5
5
  - mark start pos of tokens, currently returning end
6
6
  - _do_string inner loop optimization somehow
7
+ - json5 mode
7
8
  """
8
9
  import dataclasses as dc
9
10
  import io
@@ -0,0 +1,172 @@
1
+ // Student Main
2
+ // 2020-07-22
3
+ // Public domain
4
+
5
+ // JSON5 is a superset of JSON, it included some feature from ES5.1
6
+ // See https://json5.org/
7
+ // Derived from ../json/JSON.g4 which original derived from http://json.org
8
+
9
+ // $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false
10
+ // $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging
11
+
12
+ grammar Json5;
13
+
14
+ json5
15
+ : value? EOF
16
+ ;
17
+
18
+ obj
19
+ : '{' pair (',' pair)* ','? '}'
20
+ | '{' '}'
21
+ ;
22
+
23
+ pair
24
+ : key ':' value
25
+ ;
26
+
27
+ key
28
+ : STRING
29
+ | IDENTIFIER
30
+ | LITERAL
31
+ | NUMERIC_LITERAL
32
+ ;
33
+
34
+ value
35
+ : STRING
36
+ | number
37
+ | obj
38
+ | arr
39
+ | LITERAL
40
+ ;
41
+
42
+ arr
43
+ : '[' value (',' value)* ','? ']'
44
+ | '[' ']'
45
+ ;
46
+
47
+ number
48
+ : SYMBOL? (NUMERIC_LITERAL | NUMBER)
49
+ ;
50
+
51
+ // Lexer
52
+
53
+ SINGLE_LINE_COMMENT
54
+ : '//' .*? (NEWLINE | EOF) -> skip
55
+ ;
56
+
57
+ MULTI_LINE_COMMENT
58
+ : '/*' .*? '*/' -> skip
59
+ ;
60
+
61
+ LITERAL
62
+ : 'true'
63
+ | 'false'
64
+ | 'null'
65
+ ;
66
+
67
+ STRING
68
+ : '"' DOUBLE_QUOTE_CHAR* '"'
69
+ | '\'' SINGLE_QUOTE_CHAR* '\''
70
+ ;
71
+
72
+ fragment DOUBLE_QUOTE_CHAR
73
+ : ~["\\\r\n]
74
+ | ESCAPE_SEQUENCE
75
+ ;
76
+
77
+ fragment SINGLE_QUOTE_CHAR
78
+ : ~['\\\r\n]
79
+ | ESCAPE_SEQUENCE
80
+ ;
81
+
82
+ fragment ESCAPE_SEQUENCE
83
+ : '\\' (
84
+ NEWLINE
85
+ | UNICODE_SEQUENCE // \u1234
86
+ | ['"\\/bfnrtv] // single escape char
87
+ | ~['"\\bfnrtv0-9xu\r\n] // non escape char
88
+ | '0' // \0
89
+ | 'x' HEX HEX // \x3a
90
+ )
91
+ ;
92
+
93
+ NUMBER
94
+ : INT ('.' [0-9]*)? EXP? // +1.e2, 1234, 1234.5
95
+ | '.' [0-9]+ EXP? // -.2e3
96
+ | '0' [xX] HEX+ // 0x12345678
97
+ ;
98
+
99
+ NUMERIC_LITERAL
100
+ : 'Infinity'
101
+ | 'NaN'
102
+ ;
103
+
104
+ SYMBOL
105
+ : '+'
106
+ | '-'
107
+ ;
108
+
109
+ fragment HEX
110
+ : [0-9a-fA-F]
111
+ ;
112
+
113
+ fragment INT
114
+ : '0'
115
+ | [1-9] [0-9]*
116
+ ;
117
+
118
+ fragment EXP
119
+ : [Ee] SYMBOL? [0-9]*
120
+ ;
121
+
122
+ IDENTIFIER
123
+ : IDENTIFIER_START IDENTIFIER_PART*
124
+ ;
125
+
126
+ fragment IDENTIFIER_START
127
+ : [\p{L}]
128
+ | '$'
129
+ | '_'
130
+ | '\\' UNICODE_SEQUENCE
131
+ ;
132
+
133
+ fragment IDENTIFIER_PART
134
+ : IDENTIFIER_START
135
+ | [\p{M}]
136
+ | [\p{N}]
137
+ | [\p{Pc}]
138
+ | '\u200C'
139
+ | '\u200D'
140
+ ;
141
+
142
+ fragment UNICODE_SEQUENCE
143
+ : 'u' HEX HEX HEX HEX
144
+ ;
145
+
146
+ fragment NEWLINE
147
+ : '\r\n'
148
+ | [\r\n\u2028\u2029]
149
+ ;
150
+
151
+ fragment WS1
152
+ : '\u0009'
153
+ | '\u000A'
154
+ | '\u000B'
155
+ | '\u000C'
156
+ | '\u000D'
157
+ | '\u0020'
158
+ | '\u00A0'
159
+ | '\u2028'
160
+ | '\u2029'
161
+ | '\uFEFF'
162
+
163
+ | '\u1680'
164
+ | '\u2000' ..'\u200A'
165
+ | '\u202F'
166
+ | '\u205F'
167
+ | '\u3000'
168
+ ;
169
+
170
+ WS
171
+ : WS1+ -> skip
172
+ ;
@@ -0,0 +1,8 @@
1
+ from .codec import ( # noqa
2
+ dumps,
3
+ loads,
4
+ )
5
+
6
+ from .errors import ( # noqa
7
+ Json5Error,
8
+ )