omlish 0.0.0.dev171__py3-none-any.whl → 0.0.0.dev173__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- omlish/.manifests.json +14 -0
- omlish/__about__.py +2 -2
- omlish/formats/repr.py +25 -0
- omlish/lite/dataclasses.py +10 -0
- omlish/reflect/__init__.py +2 -0
- omlish/reflect/subst.py +2 -1
- omlish/reflect/types.py +126 -44
- {omlish-0.0.0.dev171.dist-info → omlish-0.0.0.dev173.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev171.dist-info → omlish-0.0.0.dev173.dist-info}/RECORD +13 -12
- {omlish-0.0.0.dev171.dist-info → omlish-0.0.0.dev173.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev171.dist-info → omlish-0.0.0.dev173.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev171.dist-info → omlish-0.0.0.dev173.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev171.dist-info → omlish-0.0.0.dev173.dist-info}/top_level.txt +0 -0
omlish/.manifests.json
CHANGED
@@ -121,6 +121,20 @@
|
|
121
121
|
}
|
122
122
|
}
|
123
123
|
},
|
124
|
+
{
|
125
|
+
"module": ".formats.repr",
|
126
|
+
"attr": "_REPR_LAZY_CODEC",
|
127
|
+
"file": "omlish/formats/repr.py",
|
128
|
+
"line": 24,
|
129
|
+
"value": {
|
130
|
+
"$.codecs.base.LazyLoadedCodec": {
|
131
|
+
"mod_name": "omlish.formats.repr",
|
132
|
+
"attr_name": "REPR_CODEC",
|
133
|
+
"name": "repr",
|
134
|
+
"aliases": null
|
135
|
+
}
|
136
|
+
}
|
137
|
+
},
|
124
138
|
{
|
125
139
|
"module": ".formats.toml",
|
126
140
|
"attr": "_TOML_LAZY_CODEC",
|
omlish/__about__.py
CHANGED
omlish/formats/repr.py
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
import ast
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from .codecs import make_object_lazy_loaded_codec
|
5
|
+
from .codecs import make_str_object_codec
|
6
|
+
|
7
|
+
|
8
|
+
##
|
9
|
+
|
10
|
+
|
11
|
+
def dumps(obj: ta.Any) -> str:
|
12
|
+
return repr(obj)
|
13
|
+
|
14
|
+
|
15
|
+
def loads(s: str) -> ta.Any:
|
16
|
+
return ast.literal_eval(s)
|
17
|
+
|
18
|
+
|
19
|
+
##
|
20
|
+
|
21
|
+
|
22
|
+
REPR_CODEC = make_str_object_codec('repr', dumps, loads)
|
23
|
+
|
24
|
+
# @omlish-manifest
|
25
|
+
_REPR_LAZY_CODEC = make_object_lazy_loaded_codec(__name__, 'REPR_CODEC', REPR_CODEC)
|
omlish/lite/dataclasses.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
2
|
import dataclasses as dc
|
3
|
+
import typing as ta
|
3
4
|
|
4
5
|
|
5
6
|
def dataclass_cache_hash(
|
@@ -30,3 +31,12 @@ def dataclass_cache_hash(
|
|
30
31
|
return cls
|
31
32
|
|
32
33
|
return inner
|
34
|
+
|
35
|
+
|
36
|
+
def dataclass_maybe_post_init(sup: ta.Any) -> bool:
|
37
|
+
try:
|
38
|
+
fn = sup.__post_init__
|
39
|
+
except AttributeError:
|
40
|
+
return False
|
41
|
+
fn()
|
42
|
+
return True
|
omlish/reflect/__init__.py
CHANGED
omlish/reflect/subst.py
CHANGED
@@ -8,6 +8,7 @@ from .ops import get_concrete_type
|
|
8
8
|
from .ops import to_annotation
|
9
9
|
from .types import Any
|
10
10
|
from .types import Generic
|
11
|
+
from .types import Literal
|
11
12
|
from .types import NewType
|
12
13
|
from .types import Type
|
13
14
|
from .types import Union
|
@@ -35,7 +36,7 @@ def replace_type_vars(
|
|
35
36
|
update_aliases: bool = False,
|
36
37
|
) -> Type:
|
37
38
|
def rec(cur):
|
38
|
-
if isinstance(cur, (type, NewType, Any)):
|
39
|
+
if isinstance(cur, (type, NewType, Any, Literal)):
|
39
40
|
return cur
|
40
41
|
|
41
42
|
if isinstance(cur, Generic):
|
omlish/reflect/types.py
CHANGED
@@ -7,6 +7,7 @@ TODO:
|
|
7
7
|
- cache this shit, esp generic_mro shit
|
8
8
|
- cache __hash__ in Generic/Union
|
9
9
|
"""
|
10
|
+
import abc
|
10
11
|
import dataclasses as dc
|
11
12
|
import types
|
12
13
|
import typing as ta
|
@@ -17,11 +18,12 @@ _NoneType = types.NoneType # type: ignore
|
|
17
18
|
_NONE_TYPE_FROZENSET: frozenset['Type'] = frozenset([_NoneType])
|
18
19
|
|
19
20
|
|
20
|
-
|
21
|
+
_AnnotatedAlias = ta._AnnotatedAlias # type: ignore # noqa
|
21
22
|
_CallableGenericAlias = ta._CallableGenericAlias # type: ignore # noqa
|
23
|
+
_GenericAlias = ta._GenericAlias # type: ignore # noqa
|
24
|
+
_LiteralGenericAlias = ta._LiteralGenericAlias # type: ignore # noqa
|
22
25
|
_SpecialGenericAlias = ta._SpecialGenericAlias # type: ignore # noqa
|
23
26
|
_UnionGenericAlias = ta._UnionGenericAlias # type: ignore # noqa
|
24
|
-
_AnnotatedAlias = ta._AnnotatedAlias # type: ignore # noqa
|
25
27
|
|
26
28
|
|
27
29
|
##
|
@@ -116,19 +118,29 @@ def get_newtype_supertype(obj: ta.Any) -> ta.Any:
|
|
116
118
|
##
|
117
119
|
|
118
120
|
|
119
|
-
|
121
|
+
class TypeInfo(abc.ABC): # noqa
|
122
|
+
pass
|
123
|
+
|
124
|
+
|
125
|
+
Type: ta.TypeAlias = ta.Union[ # noqa
|
120
126
|
type,
|
121
127
|
ta.TypeVar,
|
122
|
-
|
123
|
-
'Generic',
|
124
|
-
'NewType',
|
125
|
-
'Annotated',
|
126
|
-
'Any',
|
128
|
+
TypeInfo,
|
127
129
|
]
|
128
130
|
|
129
131
|
|
132
|
+
TYPES: tuple[type, ...] = (
|
133
|
+
type,
|
134
|
+
ta.TypeVar,
|
135
|
+
TypeInfo,
|
136
|
+
)
|
137
|
+
|
138
|
+
|
139
|
+
##
|
140
|
+
|
141
|
+
|
130
142
|
@dc.dataclass(frozen=True)
|
131
|
-
class Union:
|
143
|
+
class Union(TypeInfo):
|
132
144
|
args: frozenset[Type]
|
133
145
|
|
134
146
|
@property
|
@@ -144,8 +156,11 @@ class Union:
|
|
144
156
|
return Union(rem)
|
145
157
|
|
146
158
|
|
159
|
+
#
|
160
|
+
|
161
|
+
|
147
162
|
@dc.dataclass(frozen=True)
|
148
|
-
class Generic:
|
163
|
+
class Generic(TypeInfo):
|
149
164
|
cls: type
|
150
165
|
args: tuple[Type, ...] # map[int, V] = (int, V) | map[T, T] = (T, T)
|
151
166
|
|
@@ -167,39 +182,51 @@ class Generic:
|
|
167
182
|
)
|
168
183
|
|
169
184
|
|
185
|
+
#
|
186
|
+
|
187
|
+
|
170
188
|
@dc.dataclass(frozen=True)
|
171
|
-
class NewType:
|
189
|
+
class NewType(TypeInfo):
|
172
190
|
obj: ta.Any
|
173
191
|
ty: Type
|
174
192
|
|
175
193
|
|
194
|
+
#
|
195
|
+
|
196
|
+
|
176
197
|
@dc.dataclass(frozen=True)
|
177
|
-
class Annotated:
|
198
|
+
class Annotated(TypeInfo):
|
178
199
|
ty: Type
|
179
200
|
md: ta.Sequence[ta.Any]
|
180
201
|
|
181
202
|
obj: ta.Any = dc.field(compare=False, repr=False)
|
182
203
|
|
183
204
|
|
184
|
-
|
205
|
+
#
|
206
|
+
|
207
|
+
|
208
|
+
@dc.dataclass(frozen=True)
|
209
|
+
class Literal(TypeInfo):
|
210
|
+
args: tuple[ta.Any, ...]
|
211
|
+
|
212
|
+
obj: ta.Any = dc.field(compare=False, repr=False)
|
213
|
+
|
214
|
+
|
215
|
+
#
|
216
|
+
|
217
|
+
|
218
|
+
class Any(TypeInfo):
|
185
219
|
pass
|
186
220
|
|
187
221
|
|
188
222
|
ANY = Any()
|
189
223
|
|
190
224
|
|
191
|
-
|
192
|
-
type,
|
193
|
-
ta.TypeVar,
|
194
|
-
Union,
|
195
|
-
Generic,
|
196
|
-
NewType,
|
197
|
-
Annotated,
|
198
|
-
Any,
|
199
|
-
)
|
225
|
+
##
|
200
226
|
|
201
227
|
|
202
|
-
|
228
|
+
class ReflectTypeError(TypeError):
|
229
|
+
pass
|
203
230
|
|
204
231
|
|
205
232
|
class Reflector:
|
@@ -212,57 +239,80 @@ class Reflector:
|
|
212
239
|
|
213
240
|
self._override = override
|
214
241
|
|
242
|
+
#
|
243
|
+
|
215
244
|
def is_type(self, obj: ta.Any) -> bool:
|
216
|
-
|
245
|
+
try:
|
246
|
+
self._type(obj, check_only=True)
|
247
|
+
except ReflectTypeError:
|
248
|
+
return False
|
249
|
+
else:
|
217
250
|
return True
|
218
251
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
isinstance(obj, ta.NewType) or # noqa
|
225
|
-
|
226
|
-
(
|
227
|
-
is_simple_generic_alias_type(oty) or
|
228
|
-
oty is _CallableGenericAlias
|
229
|
-
) or
|
252
|
+
def type(self, obj: ta.Any) -> Type:
|
253
|
+
if (ty := self._type(obj, check_only=False)) is None:
|
254
|
+
raise RuntimeError(obj)
|
255
|
+
return ty
|
230
256
|
|
231
|
-
|
257
|
+
#
|
232
258
|
|
233
|
-
|
234
|
-
|
259
|
+
def _type(self, obj: ta.Any, *, check_only: bool) -> Type | None:
|
260
|
+
##
|
261
|
+
# Overrides beat everything
|
235
262
|
|
236
|
-
def type(self, obj: ta.Any) -> Type:
|
237
263
|
if self._override is not None:
|
238
264
|
if (ovr := self._override(obj)) is not None:
|
239
265
|
return ovr
|
240
266
|
|
267
|
+
##
|
268
|
+
# Any
|
269
|
+
|
241
270
|
if obj is ta.Any:
|
242
271
|
return ANY
|
243
272
|
|
244
|
-
|
273
|
+
##
|
274
|
+
# Already a Type?
|
275
|
+
|
276
|
+
if isinstance(obj, (ta.TypeVar, TypeInfo)): # noqa
|
245
277
|
return obj
|
246
278
|
|
247
279
|
oty = type(obj)
|
248
280
|
|
281
|
+
##
|
282
|
+
# Union
|
283
|
+
|
249
284
|
if oty is _UnionGenericAlias or oty is types.UnionType:
|
285
|
+
if check_only:
|
286
|
+
return None
|
287
|
+
|
250
288
|
return Union(frozenset(self.type(a) for a in ta.get_args(obj)))
|
251
289
|
|
290
|
+
##
|
291
|
+
# NewType
|
292
|
+
|
252
293
|
if isinstance(obj, ta.NewType): # noqa
|
294
|
+
if check_only:
|
295
|
+
return None
|
296
|
+
|
253
297
|
return NewType(obj, get_newtype_supertype(obj))
|
254
298
|
|
299
|
+
##
|
300
|
+
# Simple Generic
|
301
|
+
|
255
302
|
if (
|
256
303
|
is_simple_generic_alias_type(oty) or
|
257
304
|
oty is _CallableGenericAlias
|
258
305
|
):
|
306
|
+
if check_only:
|
307
|
+
return None
|
308
|
+
|
259
309
|
origin = ta.get_origin(obj)
|
260
310
|
args = ta.get_args(obj)
|
261
311
|
|
262
312
|
if oty is _CallableGenericAlias:
|
263
313
|
p, r = args
|
264
314
|
if p is Ellipsis or isinstance(p, ta.ParamSpec):
|
265
|
-
raise
|
315
|
+
raise ReflectTypeError(f'Callable argument not yet supported for {obj=}')
|
266
316
|
args = (*p, r)
|
267
317
|
params = _KNOWN_SPECIAL_TYPE_VARS[:len(args)]
|
268
318
|
|
@@ -276,7 +326,7 @@ class Reflector:
|
|
276
326
|
params = get_params(origin)
|
277
327
|
|
278
328
|
if len(args) != len(params):
|
279
|
-
raise
|
329
|
+
raise ReflectTypeError(f'Mismatched {args=} and {params=} for {obj=}')
|
280
330
|
|
281
331
|
return Generic(
|
282
332
|
origin,
|
@@ -285,7 +335,13 @@ class Reflector:
|
|
285
335
|
obj,
|
286
336
|
)
|
287
337
|
|
338
|
+
##
|
339
|
+
# Full Generic
|
340
|
+
|
288
341
|
if isinstance(obj, type):
|
342
|
+
if check_only:
|
343
|
+
return None
|
344
|
+
|
289
345
|
if issubclass(obj, ta.Generic): # type: ignore
|
290
346
|
params = get_params(obj)
|
291
347
|
if params:
|
@@ -295,12 +351,20 @@ class Reflector:
|
|
295
351
|
params,
|
296
352
|
obj,
|
297
353
|
)
|
354
|
+
|
298
355
|
return obj
|
299
356
|
|
357
|
+
##
|
358
|
+
# Special Generic
|
359
|
+
|
300
360
|
if isinstance(obj, _SpecialGenericAlias):
|
301
361
|
if (ks := _KNOWN_SPECIALS_BY_ALIAS.get(obj)) is not None:
|
362
|
+
if check_only:
|
363
|
+
return None
|
364
|
+
|
302
365
|
if (np := ks.nparams) < 0:
|
303
|
-
raise
|
366
|
+
raise ReflectTypeError(obj)
|
367
|
+
|
304
368
|
params = _KNOWN_SPECIAL_TYPE_VARS[:np]
|
305
369
|
return Generic(
|
306
370
|
ks.origin,
|
@@ -309,11 +373,29 @@ class Reflector:
|
|
309
373
|
obj,
|
310
374
|
)
|
311
375
|
|
376
|
+
##
|
377
|
+
# Annotated
|
378
|
+
|
312
379
|
if isinstance(obj, _AnnotatedAlias):
|
380
|
+
if check_only:
|
381
|
+
return None
|
382
|
+
|
313
383
|
o = ta.get_args(obj)[0]
|
314
384
|
return Annotated(self.type(o), md=obj.__metadata__, obj=obj)
|
315
385
|
|
316
|
-
|
386
|
+
##
|
387
|
+
# Literal
|
388
|
+
|
389
|
+
if isinstance(obj, _LiteralGenericAlias):
|
390
|
+
if check_only:
|
391
|
+
return None
|
392
|
+
|
393
|
+
return Literal(ta.get_args(obj), obj=obj)
|
394
|
+
|
395
|
+
##
|
396
|
+
# Failure
|
397
|
+
|
398
|
+
raise ReflectTypeError(obj)
|
317
399
|
|
318
400
|
|
319
401
|
DEFAULT_REFLECTOR = Reflector()
|
@@ -1,5 +1,5 @@
|
|
1
|
-
omlish/.manifests.json,sha256=
|
2
|
-
omlish/__about__.py,sha256=
|
1
|
+
omlish/.manifests.json,sha256=lRkBDFxlAbf6lN5upo3WSf-owW8YG1T21dfpbQL-XHM,7598
|
2
|
+
omlish/__about__.py,sha256=lwpg2kAkCyobGpYChlHlrlHiyjWU48sngnP5x3kz8J8,3409
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
|
5
5
|
omlish/cached.py,sha256=UI-XTFBwA6YXWJJJeBn-WkwBkfzDjLBBaZf4nIJA9y0,510
|
@@ -217,6 +217,7 @@ omlish/formats/dotenv.py,sha256=qoDG4Ayu7B-8LjBBhcmNiLZW0_9LgCi3Ri2aPo9DEQ8,1931
|
|
217
217
|
omlish/formats/json5.py,sha256=odpZIShlUpv19aACWe58SoMPcv0AHKIa6zSMjlKgaMI,515
|
218
218
|
omlish/formats/pickle.py,sha256=jdp4E9WH9qVPBE3sSqbqDtUo18RbTSIiSpSzJ-IEVZw,529
|
219
219
|
omlish/formats/props.py,sha256=cek3JLFLIrpE76gvs8rs_B8yF4SpY8ooDH8apWsquwE,18953
|
220
|
+
omlish/formats/repr.py,sha256=kYrNs4o-ji8nOdp6u_L3aMgBMWN1ZAZJSAWgQQfStSQ,414
|
220
221
|
omlish/formats/toml.py,sha256=AhpVNAy87eBohBCsvIvwH2ucASWxnWXMEsMH8zB7rpI,340
|
221
222
|
omlish/formats/xml.py,sha256=ggiOwSERt4d9XmZwLZiDIh5qnFJS4jdmow9m9_9USps,1491
|
222
223
|
omlish/formats/yaml.py,sha256=ffOwGnLA6chdiFyaS7X0TBMGmHG9AoGudzKVWfQ1UOs,7389
|
@@ -377,7 +378,7 @@ omlish/lite/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
377
378
|
omlish/lite/cached.py,sha256=O7ozcoDNFm1Hg2wtpHEqYSp_i_nCLNOP6Ueq_Uk-7mU,1300
|
378
379
|
omlish/lite/check.py,sha256=0PD-GKtaDqDX6jU5KbzbMvH-vl6jH82xgYfplmfTQkg,12941
|
379
380
|
omlish/lite/contextmanagers.py,sha256=m9JO--p7L7mSl4cycXysH-1AO27weDKjP3DZG61cwwM,1683
|
380
|
-
omlish/lite/dataclasses.py,sha256=
|
381
|
+
omlish/lite/dataclasses.py,sha256=M6UD4VwGo0Ky7RNzKWbO0IOy7iBZVCIbTiC6EYbFnX8,1035
|
381
382
|
omlish/lite/inject.py,sha256=EEaioN9ESAveVCMe2s5osjwI97FPRUVoU8P95vGUiYo,23376
|
382
383
|
omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
|
383
384
|
omlish/lite/logs.py,sha256=CWFG0NKGhqNeEgryF5atN2gkPYbUdTINEw_s1phbINM,51
|
@@ -451,11 +452,11 @@ omlish/os/linux.py,sha256=whJ6scwMKSFBdXiVhJW0BCpJV4jOGMr-a_a3Bhwz6Ls,18938
|
|
451
452
|
omlish/os/paths.py,sha256=hqPiyg_eYaRoIVPdAeX4oeLEV4Kpln_XsH0tHvbOf8Q,844
|
452
453
|
omlish/os/pidfile.py,sha256=S4Nbe00oSxckY0qCC9AeTEZe7NSw4eJudnQX7wCXzks,1738
|
453
454
|
omlish/os/sizes.py,sha256=ohkALLvqSqBX4iR-7DMKJ4pfOCRdZXV8htH4QywUNM0,152
|
454
|
-
omlish/reflect/__init__.py,sha256=
|
455
|
+
omlish/reflect/__init__.py,sha256=5TAeB3SoPR8MgnkdyVMHpAoTtlQX0BWpQYV0yDaECuM,756
|
455
456
|
omlish/reflect/inspect.py,sha256=veJ424-9oZrqyvhVpvxOi7hcKW-PDBkdYL2yjrFlk4o,495
|
456
457
|
omlish/reflect/ops.py,sha256=RJ6jzrM4ieFsXzWyNXWV43O_WgzEaUvlHSc5N2ezW2A,2044
|
457
|
-
omlish/reflect/subst.py,sha256=
|
458
|
-
omlish/reflect/types.py,sha256=
|
458
|
+
omlish/reflect/subst.py,sha256=g3q7NmNWsmc67mcchmCE3WFPCMDSBq-FXn4ah-DWL_U,3622
|
459
|
+
omlish/reflect/types.py,sha256=lYxK_hlC4kVDMKeDYJp0mymSth21quwuFAMAEFBznyE,9151
|
459
460
|
omlish/secrets/__init__.py,sha256=SGB1KrlNrxlNpazEHYy95NTzteLi8ndoEgMhU7luBl8,420
|
460
461
|
omlish/secrets/crypto.py,sha256=6CsLy0UEqCrBK8Xx_3-iFF6SKtu2GlEqUQ8-MliY3tk,3709
|
461
462
|
omlish/secrets/marshal.py,sha256=U9uSRTWzZmumfNZeh_dROwVdGrARsp155TylRbjilP8,2048
|
@@ -568,9 +569,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329
|
|
568
569
|
omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
|
569
570
|
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
570
571
|
omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
|
571
|
-
omlish-0.0.0.
|
572
|
-
omlish-0.0.0.
|
573
|
-
omlish-0.0.0.
|
574
|
-
omlish-0.0.0.
|
575
|
-
omlish-0.0.0.
|
576
|
-
omlish-0.0.0.
|
572
|
+
omlish-0.0.0.dev173.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
573
|
+
omlish-0.0.0.dev173.dist-info/METADATA,sha256=aPEQU46sbHnNUIeFdMJpzGlI3UPn_pJED6zSN3odpiw,4264
|
574
|
+
omlish-0.0.0.dev173.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
575
|
+
omlish-0.0.0.dev173.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
576
|
+
omlish-0.0.0.dev173.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
577
|
+
omlish-0.0.0.dev173.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|