omlish 0.0.0.dev212__py3-none-any.whl → 0.0.0.dev214__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.
- omlish/.manifests.json +4 -4
- omlish/__about__.py +3 -5
- omlish/antlr/__init__.py +3 -0
- omlish/antlr/parsing.py +34 -2
- omlish/asyncs/asyncio/asyncio.py +34 -0
- omlish/asyncs/ioproxy/__init__.py +1 -0
- omlish/asyncs/ioproxy/all.py +32 -0
- omlish/asyncs/ioproxy/io.py +242 -0
- omlish/asyncs/ioproxy/proxier.py +154 -0
- omlish/asyncs/ioproxy/proxy.py +141 -0
- omlish/asyncs/ioproxy/typing.py +108 -0
- omlish/check.py +1 -0
- omlish/configs/processing/matching.py +9 -1
- omlish/formats/json/stream/lex.py +1 -0
- omlish/formats/json5/Json5.g4 +172 -0
- omlish/formats/json5/__init__.py +8 -0
- omlish/formats/json5/_antlr/Json5Lexer.py +353 -0
- omlish/formats/json5/_antlr/Json5Listener.py +78 -0
- omlish/formats/json5/_antlr/Json5Parser.py +616 -0
- omlish/formats/json5/_antlr/Json5Visitor.py +51 -0
- omlish/formats/json5/_antlr/__init__.py +0 -0
- omlish/formats/{json5.py → json5/codec.py} +6 -11
- omlish/formats/json5/errors.py +2 -0
- omlish/formats/json5/literals.py +130 -0
- omlish/formats/json5/parsing.py +79 -0
- omlish/io/abc.py +1 -0
- omlish/lang/__init__.py +2 -0
- omlish/lang/imports.py +4 -0
- omlish/lang/strings.py +33 -1
- omlish/lite/check.py +23 -0
- omlish/lite/contextmanagers.py +39 -0
- omlish/os/files.py +17 -30
- omlish/os/temp.py +50 -0
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/METADATA +5 -7
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/RECORD +39 -22
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev212.dist-info → omlish-0.0.0.dev214.dist-info}/entry_points.txt +0 -0
- {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
@@ -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
|
41
|
+
if self.match_path(ctx.path):
|
34
42
|
no = self._fn(ctx.obj)
|
35
43
|
if not self._recurse:
|
36
44
|
return no
|
@@ -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
|
+
;
|