RemoteRF 2.3.0__tar.gz → 2.3.1__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.
- {remoterf-2.3.0/src/remoterf.egg-info → remoterf-2.3.1}/PKG-INFO +1 -1
- {remoterf-2.3.0 → remoterf-2.3.1}/pyproject.toml +1 -1
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/app.py +13 -4
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/grpc_client.py +9 -1
- {remoterf-2.3.0 → remoterf-2.3.1/src/remoterf.egg-info}/PKG-INFO +1 -1
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_device_routes.py +16 -6
- {remoterf-2.3.0 → remoterf-2.3.1}/LICENSE +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/README.md +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/setup.cfg +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/deployment_capabilities.proto +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/deployment_capabilities_pb2.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/deployment_capabilities_pb2_grpc.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/grpc.proto +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/grpc_pb2.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/grpc_pb2_grpc.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/v2_codec.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/tos_notice.txt +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/utils/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/utils/ansi_codes.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/utils/api_token.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/utils/banner.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/utils/list_string.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/utils/process_arg.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/config/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/config/cert_fetcher.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/config/config.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/acc_login.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/banner_note.txt +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/direct_path.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/dynamic_v2_transport.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/grpc_acc.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/secure_channel.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/core/v2_errors.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/deployment/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/deployment/backend.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/deployment/direct.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/deployment/homes.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/deployment/http.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/deployment/state.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/_virtual.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/adalm_pluto/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/adalm_pluto/adalm_pluto_remote.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/dynamic_device.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/dynamic_v2.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/hackrf/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/hackrf/hackrf_remote.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/rtl_sdr/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/rtl_sdr/rtl_sdr_remote.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/sim_sdr/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/sim_sdr/sim_sdr_remote.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/support/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/support/ti_mmwave.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/support/uhd.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/support/uhd_dsp.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/support/uhd_v2.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/ti_mmwave/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/ti_mmwave/ti_mmwave_remote.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/usrp/__init__.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/usrp/usrp_remote.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/drivers/usrp/usrp_remote.pyi +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/remoterf_cli.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/version.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf.egg-info/SOURCES.txt +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf.egg-info/dependency_links.txt +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf.egg-info/entry_points.txt +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf.egg-info/requires.txt +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf.egg-info/top_level.txt +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_banner.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_cli_login_fresh.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_config_address.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_deployment_accounts.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_direct_path_fixed.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_direct_path_partner.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_direct_path_race.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_dynamic_device_codegen.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_dynamic_v2.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_federated_devices.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_fetch_idl_fallback.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_finish_prompt.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_gate_i_direct_path.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_grpc_client_target.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_homes.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_native_account_credentials.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_native_devices.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_partner_dynamic_v2.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_pluto_virtual.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_process_arg.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_remoterf_cli.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_ti_mmwave.py +0 -0
- {remoterf-2.3.0 → remoterf-2.3.1}/tests/test_upgrade_rescue.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
|
|
5
5
|
Author-email: Ethan Ge <ethoGalaxy@gmail.com>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "remoterf"
|
|
7
|
-
version = "2.3.
|
|
7
|
+
version = "2.3.1"
|
|
8
8
|
description = "A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "GPL-3.0-or-later"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
|
-
from remoterf.core.grpc_client import addr as server_addr, handle_admin_command
|
|
16
|
+
from remoterf.core.grpc_client import addr as server_addr, handle_admin_command, _key
|
|
17
17
|
from . import *
|
|
18
18
|
from ..common.utils import *
|
|
19
19
|
|
|
@@ -146,9 +146,16 @@ def _routable(token):
|
|
|
146
146
|
|
|
147
147
|
|
|
148
148
|
def _name_and_handle(name):
|
|
149
|
-
"""A listed device name,
|
|
149
|
+
"""A listed device name -> (name, handle). The handle is the name keyed,
|
|
150
|
+
'Pluto SDR' -> 'Pluto_SDR' (None when the lab can't address it), unless a
|
|
151
|
+
1.2.0 lab tags it: 'Pluto SDR [PlutoA]'."""
|
|
150
152
|
m = _HANDLE_TAG.match(name)
|
|
151
|
-
|
|
153
|
+
if m:
|
|
154
|
+
return m["name"], m["handle"]
|
|
155
|
+
h = _key(name)
|
|
156
|
+
# The lab's is_device_handle (core 0.19.0; this client pins 0.16.0).
|
|
157
|
+
ok = h and not h.startswith(("rfg_", "bridge-")) and not any(c in "@:" or c.isspace() or not c.isprintable() for c in h)
|
|
158
|
+
return name, h if ok else None
|
|
152
159
|
|
|
153
160
|
|
|
154
161
|
def _print_reserved(where, when, token, handle, logged_in_to, install, no_handle=_NO_HANDLE):
|
|
@@ -519,7 +526,9 @@ def _render_destinations(entries):
|
|
|
519
526
|
|
|
520
527
|
|
|
521
528
|
def _handle_tag(dev):
|
|
522
|
-
|
|
529
|
+
"""' [handle]' only when it isn't just the name."""
|
|
530
|
+
h = dev.get("handle")
|
|
531
|
+
return f" [{h}]" if h and _key(dev.get("display_name") or "") != _key(h) else ""
|
|
523
532
|
|
|
524
533
|
|
|
525
534
|
def _federated_devices():
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
16
|
import os
|
|
17
|
+
import re
|
|
17
18
|
import sys
|
|
18
19
|
import threading
|
|
19
20
|
from dataclasses import dataclass
|
|
@@ -421,8 +422,15 @@ def _lab(t, x, dep, connection):
|
|
|
421
422
|
return DeviceRoute(unmap_arg(results["Token"]), kind, connection, res_id=res_id)
|
|
422
423
|
|
|
423
424
|
|
|
425
|
+
def _key(s):
|
|
426
|
+
"""A device name as a handle: 'pluto A', 'pluto_A' and 'pluto__A' are one.
|
|
427
|
+
Only for comparing names; never rewrite a string that may be a token."""
|
|
428
|
+
return re.sub(r"[\s_]+", "_", s).strip("_")
|
|
429
|
+
|
|
430
|
+
|
|
424
431
|
def _global_handle(x, dep):
|
|
425
432
|
"""A handle on a device Global lists for this user, as its ref (None: no match)."""
|
|
433
|
+
key = _key(x)
|
|
426
434
|
try:
|
|
427
435
|
backend = federated_backend()
|
|
428
436
|
dep_id = _deployment_id(dep)
|
|
@@ -430,7 +438,7 @@ def _global_handle(x, dep):
|
|
|
430
438
|
return None
|
|
431
439
|
matches = [
|
|
432
440
|
d for d in backend.devices()["devices"]
|
|
433
|
-
if d.get("deployment_id") == dep_id and d.get("handle") ==
|
|
441
|
+
if key and d.get("deployment_id") == dep_id and _key(d.get("handle") or "") == key
|
|
434
442
|
]
|
|
435
443
|
if len(matches) > 1:
|
|
436
444
|
raise RuntimeError(f"{x}@{dep}: more than one device has that handle")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
|
|
5
5
|
Author-email: Ethan Ge <ethoGalaxy@gmail.com>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -182,6 +182,7 @@ def test_a_handle_is_exchanged_once_at_the_active_lab(monkeypatch, routes):
|
|
|
182
182
|
@pytest.mark.parametrize("reply, wire, printed", [
|
|
183
183
|
({"Token": "Zm9vYmFy"}, "Zm9vYmFy", False), # not a handle: the lab hands it back
|
|
184
184
|
({"Token": "SuperTok_3_force"}, "SuperTok_3_force", False), # <super token>@<lab>: same path
|
|
185
|
+
({"Token": "Zm9v__YmFy"}, "Zm9v__YmFy", False), # a token is never keyed
|
|
185
186
|
({"Token": "PlutoA", "why": "no active reservation of yours on PlutoA right now"}, "PlutoA", True),
|
|
186
187
|
({"ace": "No matching server function to call: device_token"}, "PlutoA", False), # old server
|
|
187
188
|
])
|
|
@@ -191,6 +192,7 @@ def test_the_lab_decides_handle_or_token(monkeypatch, routes, capsys, reply, wir
|
|
|
191
192
|
t = f"{reply.get('Token', 'PlutoA')}@ucla" if "why" not in reply else "PlutoA@ucla"
|
|
192
193
|
for _ in range(2):
|
|
193
194
|
grpc_client.rpc_client(function_name=GET, args={"a": map_arg(t)})
|
|
195
|
+
assert routes.calls[0] == ("ACC:device_token", {"un": "jdoe", "pw": "s3cret", "h": t[:-len("@ucla")]})
|
|
194
196
|
assert [c for c in routes.calls if c[0] == GET] == [(GET, {"a": wire})] * 2
|
|
195
197
|
err = capsys.readouterr().err
|
|
196
198
|
if printed:
|
|
@@ -338,6 +340,12 @@ def test_a_global_user_handle_maps_to_the_listed_device(monkeypatch, routes):
|
|
|
338
340
|
monkeypatch.setattr(grpc_client, "federated_backend", lambda: SimpleNamespace(devices=lambda: listing))
|
|
339
341
|
monkeypatch.setattr(homes, "discover", lambda host: {"deployment_id": DEST})
|
|
340
342
|
assert grpc_client.device_route("PlutoA@ucla") == grpc_client.DeviceRoute(REF, "global")
|
|
343
|
+
# The handle is the name: spaces and underscores are one.
|
|
344
|
+
assert grpc_client._key("pluto A") == grpc_client._key("pluto_A") == grpc_client._key(" pluto\tA ") \
|
|
345
|
+
== grpc_client._key("pluto__A") == "pluto_A"
|
|
346
|
+
listing["devices"][1]["handle"] = "pluto_A"
|
|
347
|
+
for typed in ("pluto A@ucla", "pluto__A@ucla"):
|
|
348
|
+
assert grpc_client.device_route(typed) == grpc_client.DeviceRoute(REF, "global")
|
|
341
349
|
with pytest.raises(RuntimeError) as exc:
|
|
342
350
|
grpc_client.device_route("PlutoB@ucla")
|
|
343
351
|
assert str(exc.value) == _unreachable("ucla")
|
|
@@ -436,7 +444,7 @@ def test_a_lab_reservation_shows_the_token_and_the_handle(monkeypatch):
|
|
|
436
444
|
account.install_reserved_driver.assert_called_once_with("Zm9vYmFy", 3)
|
|
437
445
|
|
|
438
446
|
|
|
439
|
-
def
|
|
447
|
+
def test_an_untagged_device_is_reached_by_its_name(monkeypatch):
|
|
440
448
|
import datetime
|
|
441
449
|
import remoterf.core.app as client_app
|
|
442
450
|
|
|
@@ -448,10 +456,9 @@ def test_a_device_without_a_handle_shows_only_the_token(monkeypatch):
|
|
|
448
456
|
monkeypatch.setattr(client_app, "home_name", "ucla")
|
|
449
457
|
client_app._native_reserve_slot(4, datetime.date(2026, 1, 1), (0, 1), "10:00", "11:00",
|
|
450
458
|
device_label="USRP B210 (online)")
|
|
451
|
-
assert "Reservation successful on
|
|
452
|
-
assert _row(lines, "Token", "Zm9vYmFy@ucla") and
|
|
453
|
-
assert
|
|
454
|
-
assert ' sdr = uhd.usrp.MultiUSRP(token="Zm9vYmFy@ucla")' in lines
|
|
459
|
+
assert "Reservation successful on USRP_B210 @ucla for 2026-01-01 10:00-11:00." in lines
|
|
460
|
+
assert _row(lines, "Token", "Zm9vYmFy@ucla") and _row(lines, "Device", "handle", "USRP_B210@ucla")
|
|
461
|
+
assert ' sdr = uhd.usrp.MultiUSRP(token="USRP_B210@ucla")' in lines
|
|
455
462
|
# A failed driver install: the token is still shown, just no usage lines.
|
|
456
463
|
lines.clear()
|
|
457
464
|
account.install_reserved_driver.return_value = None
|
|
@@ -514,6 +521,7 @@ def test_a_global_listing_shows_the_handle():
|
|
|
514
521
|
|
|
515
522
|
assert client_app._handle_tag({"handle": "PlutoA"}) == " [PlutoA]"
|
|
516
523
|
assert client_app._handle_tag({}) == ""
|
|
524
|
+
assert client_app._handle_tag({"display_name": "pluto A", "handle": "pluto_A"}) == ""
|
|
517
525
|
|
|
518
526
|
|
|
519
527
|
def test_install_after_a_global_reservation_uses_the_ref():
|
|
@@ -598,7 +606,9 @@ def test_a_handle_is_the_last_bracketed_word():
|
|
|
598
606
|
|
|
599
607
|
assert client_app._name_and_handle("SimSDR-0 [Lab]A]") == ("SimSDR-0", "Lab]A")
|
|
600
608
|
assert client_app._name_and_handle("Bench [x] [B1]") == ("Bench [x]", "B1")
|
|
601
|
-
assert client_app._name_and_handle("Bench [a b]") == ("Bench [a b]",
|
|
609
|
+
assert client_app._name_and_handle("Bench [a b]") == ("Bench [a b]", "Bench_[a_b]")
|
|
610
|
+
assert client_app._name_and_handle("pluto A") == ("pluto A", "pluto_A")
|
|
611
|
+
assert [client_app._name_and_handle(n)[1] for n in ("a@b", "rfg_x", "bridge-x", " _ ")] == [None] * 4
|
|
602
612
|
|
|
603
613
|
|
|
604
614
|
def test_a_shell_without_a_home_shows_the_profiles_lab(monkeypatch):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remoterf-2.3.0 → remoterf-2.3.1}/src/remoterf/common/grpc/deployment_capabilities_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
|
|
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
|