isolate 0.26.2__tar.gz → 0.26.3__tar.gz
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.
- {isolate-0.26.2/src/isolate.egg-info → isolate-0.26.3}/PKG-INFO +1 -1
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/_isolate_version.py +3 -3
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/agent.py +36 -6
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/server.py +40 -3
- {isolate-0.26.2 → isolate-0.26.3/src/isolate.egg-info}/PKG-INFO +1 -1
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_server.py +84 -0
- {isolate-0.26.2 → isolate-0.26.3}/.github/workflows/claude-code-review.yml +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/.github/workflows/claude.yml +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/.github/workflows/lint.yml +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/.github/workflows/release.yml +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/.github/workflows/test.yml +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/.gitignore +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/.pre-commit-config.yaml +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/LICENSE +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/README.md +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/pyproject.toml +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/setup.cfg +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/_version.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/_base.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/common.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/conda.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/container.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/local.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/pyenv.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/remote.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/settings.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/backends/virtualenv.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/common/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/common/timestamp.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/_local/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/_local/_base.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/_local/agent_startup.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/common.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/_base.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/configuration.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/agent.proto +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/agent_pb2.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/agent_pb2.pyi +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/common.proto +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/common_pb2.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/common_pb2.pyi +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/common_pb2_grpc.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/interface.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/ipc/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/ipc/_base.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/ipc/agent.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/logger.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/logs.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/py.typed +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/registry.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/definitions/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/definitions/server.proto +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/definitions/server_pb2.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/definitions/server_pb2.pyi +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/definitions/server_pb2_grpc.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/health/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/health/health.proto +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/health/health_pb2.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/health/health_pb2.pyi +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/health/health_pb2_grpc.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/health_server.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate/server/interface.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate.egg-info/SOURCES.txt +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate.egg-info/dependency_links.txt +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate.egg-info/entry_points.txt +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate.egg-info/requires.txt +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/src/isolate.egg-info/top_level.txt +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/__init__.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/conftest.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_agent_backward_compatibility.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_backends.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_concurrency.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_connections.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_connections_grpc_base.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_isolate.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_log.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_log_masking.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_logger.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_serialization.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tests/test_shutdown.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tools/Dockerfile +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tools/agent_requirements.txt +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tools/isolate_client.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tools/protobuf-requirements.txt +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tools/regen_grpc.py +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tools/requirements.txt +0 -0
- {isolate-0.26.2 → isolate-0.26.3}/tools/test_agent_requirements.txt +0 -0
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.26.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 26,
|
|
31
|
+
__version__ = version = '0.26.3'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 26, 3)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g4d299d23d'
|
|
@@ -196,6 +196,40 @@ def _resolve_entrypoint(entrypoint: str) -> Any:
|
|
|
196
196
|
return obj
|
|
197
197
|
|
|
198
198
|
|
|
199
|
+
def _get_callable_kind(message: Any) -> str | None:
|
|
200
|
+
"""Return the active callable field across recent proto variants."""
|
|
201
|
+
try:
|
|
202
|
+
return message.WhichOneof("callable")
|
|
203
|
+
except ValueError:
|
|
204
|
+
has_function = _has_field(message, "function")
|
|
205
|
+
has_entrypoint = _has_field(message, "entrypoint")
|
|
206
|
+
if has_function:
|
|
207
|
+
return "function"
|
|
208
|
+
if has_entrypoint:
|
|
209
|
+
return "entrypoint"
|
|
210
|
+
return None
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _has_field(message: Any, field_name: str) -> bool:
|
|
214
|
+
try:
|
|
215
|
+
return message.HasField(field_name)
|
|
216
|
+
except ValueError:
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _get_optional_bool_field(message: Any, field_name: str) -> Optional[bool]:
|
|
221
|
+
"""Read an optional bool field across proto variants.
|
|
222
|
+
|
|
223
|
+
Older generated protobuf modules may expose the field without presence
|
|
224
|
+
tracking. In that case, only ``True`` can be observed distinctly; ``False``
|
|
225
|
+
is treated like "unset" so legacy fallback behavior is preserved.
|
|
226
|
+
"""
|
|
227
|
+
try:
|
|
228
|
+
return getattr(message, field_name) if message.HasField(field_name) else None
|
|
229
|
+
except ValueError:
|
|
230
|
+
return True if getattr(message, field_name, False) else None
|
|
231
|
+
|
|
232
|
+
|
|
199
233
|
class AgentServicer(definitions.AgentServicer):
|
|
200
234
|
def __init__(self, log_file: TextIO | None = None):
|
|
201
235
|
super().__init__()
|
|
@@ -268,7 +302,7 @@ class AgentServicer(definitions.AgentServicer):
|
|
|
268
302
|
|
|
269
303
|
# The `callable` oneof enforces at-most-one on the wire; here we
|
|
270
304
|
# only need to reject the "neither set" case.
|
|
271
|
-
callable_kind = request
|
|
305
|
+
callable_kind = _get_callable_kind(request)
|
|
272
306
|
if callable_kind is None:
|
|
273
307
|
self.abort_with_msg(
|
|
274
308
|
context,
|
|
@@ -329,11 +363,7 @@ class AgentServicer(definitions.AgentServicer):
|
|
|
329
363
|
extra_args.append(self._run_cache[cache_key])
|
|
330
364
|
|
|
331
365
|
try:
|
|
332
|
-
run_on_main_thread = (
|
|
333
|
-
request.run_on_main_thread
|
|
334
|
-
if request.HasField("run_on_main_thread")
|
|
335
|
-
else None
|
|
336
|
-
)
|
|
366
|
+
run_on_main_thread = _get_optional_bool_field(request, "run_on_main_thread")
|
|
337
367
|
if has_entrypoint:
|
|
338
368
|
invocation = await self.execute_entrypoint(
|
|
339
369
|
request.entrypoint,
|
|
@@ -69,6 +69,40 @@ class GRPCException(Exception):
|
|
|
69
69
|
return f"{self.code.name}: {self.message}"
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
def _get_callable_kind(message: Any) -> str | None:
|
|
73
|
+
"""Return the active callable field across recent proto variants."""
|
|
74
|
+
try:
|
|
75
|
+
return message.WhichOneof("callable")
|
|
76
|
+
except ValueError:
|
|
77
|
+
has_function = _has_field(message, "function")
|
|
78
|
+
has_entrypoint = _has_field(message, "entrypoint")
|
|
79
|
+
if has_function:
|
|
80
|
+
return "function"
|
|
81
|
+
if has_entrypoint:
|
|
82
|
+
return "entrypoint"
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _has_field(message: Any, field_name: str) -> bool:
|
|
87
|
+
try:
|
|
88
|
+
return message.HasField(field_name)
|
|
89
|
+
except ValueError:
|
|
90
|
+
return False
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _get_optional_bool_field(message: Any, field_name: str) -> bool | None:
|
|
94
|
+
"""Read an optional bool field across proto variants.
|
|
95
|
+
|
|
96
|
+
Older generated protobuf modules may expose the field without presence
|
|
97
|
+
tracking. In that case, only ``True`` can be observed distinctly; ``False``
|
|
98
|
+
is treated like "unset" so legacy fallback behavior is preserved.
|
|
99
|
+
"""
|
|
100
|
+
try:
|
|
101
|
+
return getattr(message, field_name) if message.HasField(field_name) else None
|
|
102
|
+
except ValueError:
|
|
103
|
+
return True if getattr(message, field_name, False) else None
|
|
104
|
+
|
|
105
|
+
|
|
72
106
|
@dataclass
|
|
73
107
|
class RunnerAgent:
|
|
74
108
|
stub: definitions.AgentStub
|
|
@@ -250,7 +284,7 @@ class IsolateServicer(definitions.IsolateServicer):
|
|
|
250
284
|
|
|
251
285
|
# The `callable` oneof enforces at-most-one on the wire; here we
|
|
252
286
|
# only need to reject the "neither set" case.
|
|
253
|
-
callable_kind = task.request
|
|
287
|
+
callable_kind = _get_callable_kind(task.request)
|
|
254
288
|
if callable_kind is None:
|
|
255
289
|
raise GRPCException(
|
|
256
290
|
"One of 'function' or 'entrypoint' must be set.",
|
|
@@ -338,8 +372,11 @@ class IsolateServicer(definitions.IsolateServicer):
|
|
|
338
372
|
)
|
|
339
373
|
if not task.request.HasField("setup_func"):
|
|
340
374
|
function_call.ClearField("setup_func")
|
|
341
|
-
|
|
342
|
-
|
|
375
|
+
run_on_main_thread = _get_optional_bool_field(
|
|
376
|
+
task.request, "run_on_main_thread"
|
|
377
|
+
)
|
|
378
|
+
if run_on_main_thread is not None:
|
|
379
|
+
function_call.run_on_main_thread = run_on_main_thread
|
|
343
380
|
|
|
344
381
|
future = local_pool.submit(
|
|
345
382
|
_proxy_to_queue,
|
|
@@ -139,6 +139,42 @@ def define_environment(kind: str, **kwargs: Any) -> definitions.EnvironmentDefin
|
|
|
139
139
|
_NOT_SET = object()
|
|
140
140
|
|
|
141
141
|
|
|
142
|
+
class LegacyCallableProto:
|
|
143
|
+
"""Simulate the pre-oneof / pre-optional-bool generated protobuf API."""
|
|
144
|
+
|
|
145
|
+
def __init__(
|
|
146
|
+
self,
|
|
147
|
+
*,
|
|
148
|
+
function: bool = False,
|
|
149
|
+
entrypoint: bool = False,
|
|
150
|
+
run_on_main_thread: bool = False,
|
|
151
|
+
supports_entrypoint: bool = True,
|
|
152
|
+
) -> None:
|
|
153
|
+
self.run_on_main_thread = run_on_main_thread
|
|
154
|
+
self._has_field = {
|
|
155
|
+
"function": function,
|
|
156
|
+
"entrypoint": entrypoint,
|
|
157
|
+
}
|
|
158
|
+
self._supports_entrypoint = supports_entrypoint
|
|
159
|
+
|
|
160
|
+
def WhichOneof(self, name: str) -> Optional[str]:
|
|
161
|
+
raise ValueError(f'Protocol message FunctionCall has no "{name}" field.')
|
|
162
|
+
|
|
163
|
+
def HasField(self, name: str) -> bool:
|
|
164
|
+
if name == "run_on_main_thread":
|
|
165
|
+
raise ValueError(
|
|
166
|
+
"Field FunctionCall.run_on_main_thread does not have presence."
|
|
167
|
+
)
|
|
168
|
+
if name == "entrypoint" and not self._supports_entrypoint:
|
|
169
|
+
raise ValueError('Protocol message FunctionCall has no "entrypoint" field.')
|
|
170
|
+
try:
|
|
171
|
+
return self._has_field[name]
|
|
172
|
+
except KeyError as exc:
|
|
173
|
+
raise ValueError(
|
|
174
|
+
f'Protocol message FunctionCall has no "{name}" field.'
|
|
175
|
+
) from exc
|
|
176
|
+
|
|
177
|
+
|
|
142
178
|
def run_request(
|
|
143
179
|
stub: definitions.IsolateStub,
|
|
144
180
|
request: definitions.BoundFunction,
|
|
@@ -417,6 +453,54 @@ def test_agent_import_falls_back_when_common_validator_missing(
|
|
|
417
453
|
importlib.reload(agent_module)
|
|
418
454
|
|
|
419
455
|
|
|
456
|
+
@pytest.mark.parametrize(
|
|
457
|
+
"module_name",
|
|
458
|
+
[
|
|
459
|
+
"isolate.connections.grpc.agent",
|
|
460
|
+
"isolate.server.server",
|
|
461
|
+
],
|
|
462
|
+
)
|
|
463
|
+
def test_callable_kind_falls_back_when_proto_has_no_oneof(module_name: str) -> None:
|
|
464
|
+
module = importlib.import_module(module_name)
|
|
465
|
+
|
|
466
|
+
assert module._get_callable_kind(LegacyCallableProto(function=True)) == "function"
|
|
467
|
+
assert (
|
|
468
|
+
module._get_callable_kind(
|
|
469
|
+
LegacyCallableProto(function=True, supports_entrypoint=False)
|
|
470
|
+
)
|
|
471
|
+
== "function"
|
|
472
|
+
)
|
|
473
|
+
assert (
|
|
474
|
+
module._get_callable_kind(LegacyCallableProto(entrypoint=True)) == "entrypoint"
|
|
475
|
+
)
|
|
476
|
+
assert module._get_callable_kind(LegacyCallableProto()) is None
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
@pytest.mark.parametrize(
|
|
480
|
+
"module_name",
|
|
481
|
+
[
|
|
482
|
+
"isolate.connections.grpc.agent",
|
|
483
|
+
"isolate.server.server",
|
|
484
|
+
],
|
|
485
|
+
)
|
|
486
|
+
def test_optional_bool_field_falls_back_when_proto_has_no_presence(
|
|
487
|
+
module_name: str,
|
|
488
|
+
) -> None:
|
|
489
|
+
module = importlib.import_module(module_name)
|
|
490
|
+
|
|
491
|
+
assert (
|
|
492
|
+
module._get_optional_bool_field(
|
|
493
|
+
LegacyCallableProto(run_on_main_thread=False),
|
|
494
|
+
"run_on_main_thread",
|
|
495
|
+
)
|
|
496
|
+
is None
|
|
497
|
+
)
|
|
498
|
+
assert module._get_optional_bool_field(
|
|
499
|
+
LegacyCallableProto(run_on_main_thread=True),
|
|
500
|
+
"run_on_main_thread",
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
|
|
420
504
|
def test_server_entrypoint_module_not_found(
|
|
421
505
|
stub: definitions.IsolateStub, monkeypatch: Any
|
|
422
506
|
) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/agent_pb2_grpc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{isolate-0.26.2 → isolate-0.26.3}/src/isolate/connections/grpc/definitions/common_pb2_grpc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|