RemoteRF 2.2.0__tar.gz → 2.2.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.2.0/src/remoterf.egg-info → remoterf-2.2.1}/PKG-INFO +1 -1
- {remoterf-2.2.0 → remoterf-2.2.1}/pyproject.toml +1 -1
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/app.py +3 -4
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/direct_path.py +15 -6
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/grpc_client.py +4 -3
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/remoterf_cli.py +25 -11
- {remoterf-2.2.0 → remoterf-2.2.1/src/remoterf.egg-info}/PKG-INFO +1 -1
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_cli_login_fresh.py +28 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_gate_i_direct_path.py +32 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_homes.py +3 -2
- {remoterf-2.2.0 → remoterf-2.2.1}/LICENSE +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/README.md +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/setup.cfg +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/grpc/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/grpc/deployment_capabilities.proto +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/grpc/deployment_capabilities_pb2.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/grpc/deployment_capabilities_pb2_grpc.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/grpc/grpc.proto +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/grpc/grpc_pb2.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/grpc/grpc_pb2_grpc.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/grpc/v2_codec.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/tos_notice.txt +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/utils/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/utils/ansi_codes.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/utils/api_token.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/utils/banner.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/utils/list_string.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/common/utils/process_arg.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/config/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/config/cert_fetcher.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/config/config.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/acc_login.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/banner_note.txt +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/dynamic_v2_transport.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/grpc_acc.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/secure_channel.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/core/v2_errors.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/deployment/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/deployment/backend.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/deployment/direct.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/deployment/homes.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/deployment/http.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/deployment/state.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/_virtual.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/adalm_pluto/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/adalm_pluto/adalm_pluto_remote.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/dynamic_device.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/dynamic_v2.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/hackrf/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/hackrf/hackrf_remote.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/rtl_sdr/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/rtl_sdr/rtl_sdr_remote.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/sim_sdr/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/sim_sdr/sim_sdr_remote.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/support/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/support/ti_mmwave.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/support/uhd.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/support/uhd_dsp.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/support/uhd_v2.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/ti_mmwave/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/ti_mmwave/ti_mmwave_remote.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/usrp/__init__.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/usrp/usrp_remote.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/drivers/usrp/usrp_remote.pyi +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf/version.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf.egg-info/SOURCES.txt +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf.egg-info/dependency_links.txt +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf.egg-info/entry_points.txt +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf.egg-info/requires.txt +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf.egg-info/top_level.txt +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/src/remoterf.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_banner.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_config_address.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_deployment_accounts.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_direct_path_fixed.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_direct_path_partner.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_direct_path_race.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_dynamic_device_codegen.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_dynamic_v2.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_federated_devices.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_fetch_idl_fallback.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_finish_prompt.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_grpc_client_target.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_native_account_credentials.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_native_devices.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_partner_dynamic_v2.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_pluto_virtual.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_process_arg.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_remoterf_cli.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.1}/tests/test_ti_mmwave.py +0 -0
- {remoterf-2.2.0 → remoterf-2.2.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.2.
|
|
3
|
+
Version: 2.2.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.2.
|
|
7
|
+
version = "2.2.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"
|
|
@@ -536,10 +536,9 @@ def _federated_reservations_for_range(start_day, end_day):
|
|
|
536
536
|
|
|
537
537
|
def _federated_reserve_slot(device_id, chosen_day, chosen_slot, slot_start_str, slot_end_str):
|
|
538
538
|
handle = account.reserve_device(device_id, chosen_slot[0], chosen_slot[1])
|
|
539
|
-
|
|
540
|
-
printf("
|
|
541
|
-
printf("
|
|
542
|
-
printf("The first call can take ~20 s while the radio powers on.", Sty.GRAY)
|
|
539
|
+
# Worded as a lab account's reservation; the handle goes where a token goes.
|
|
540
|
+
printf("Reservation successful on device ", (Sty.BOLD, Sty.GREEN), f"{str(device_id).rsplit(':', 1)[-1]}", Sty.MAGENTA, " for ", Sty.DEFAULT, f"{chosen_day.strftime('%Y-%m-%d')} {slot_start_str}-{slot_end_str}.", Sty.CYAN)
|
|
541
|
+
printf("Your Token -> ", Sty.BOLD, f"{handle}", (Sty.BOLD, Sty.GREEN))
|
|
543
542
|
account.install_reserved_driver(handle, device_id)
|
|
544
543
|
|
|
545
544
|
|
|
@@ -50,11 +50,18 @@ import threading
|
|
|
50
50
|
import time
|
|
51
51
|
from typing import Callable, Optional
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
from
|
|
55
|
-
from aioquic.
|
|
56
|
-
from aioquic.quic
|
|
57
|
-
from aioquic.quic.
|
|
53
|
+
try:
|
|
54
|
+
from aioice import Candidate, Connection
|
|
55
|
+
from aioquic.asyncio.protocol import QuicConnectionProtocol
|
|
56
|
+
from aioquic.quic import events
|
|
57
|
+
from aioquic.quic.configuration import QuicConfiguration
|
|
58
|
+
from aioquic.quic.connection import QuicConnection
|
|
59
|
+
|
|
60
|
+
_BROKEN = None
|
|
61
|
+
except Exception as _exc: # noqa: BLE001 - e.g. conda swapped in a cryptography pip's pyOpenSSL cannot use
|
|
62
|
+
Candidate = Connection = QuicConnectionProtocol = QuicConfiguration = QuicConnection = object
|
|
63
|
+
events = None
|
|
64
|
+
_BROKEN = f"{type(_exc).__name__}: {_exc}"
|
|
58
65
|
|
|
59
66
|
from ..common.grpc import grpc_pb2
|
|
60
67
|
from ..common.utils import map_arg, unmap_arg
|
|
@@ -136,7 +143,7 @@ STUN_SECONDS = 1.5 # a STUN server answers in milliseconds or not at all
|
|
|
136
143
|
|
|
137
144
|
|
|
138
145
|
def enabled() -> bool:
|
|
139
|
-
return os.getenv("REMOTERF_DIRECT", "1").strip().lower() not in {"0", "off", "no", "false"}
|
|
146
|
+
return _BROKEN is None and os.getenv("REMOTERF_DIRECT", "1").strip().lower() not in {"0", "off", "no", "false"}
|
|
140
147
|
|
|
141
148
|
|
|
142
149
|
def wants(function_name: str) -> bool:
|
|
@@ -742,6 +749,8 @@ def current(token: Optional[str] = None) -> Optional[DirectPath]:
|
|
|
742
749
|
|
|
743
750
|
def describe() -> str:
|
|
744
751
|
"""What device calls use right now, for the shell."""
|
|
752
|
+
if _BROKEN is not None:
|
|
753
|
+
return f"relay (direct path unavailable: {_BROKEN}; fix: pip install --force-reinstall remoterf)"
|
|
745
754
|
if not enabled():
|
|
746
755
|
return "relay (direct path disabled: REMOTERF_DIRECT=0)"
|
|
747
756
|
path = _path
|
|
@@ -225,15 +225,16 @@ def _device_token(function_name, args):
|
|
|
225
225
|
def rpc_client(*, function_name, args, connection=None):
|
|
226
226
|
global tcp_calls
|
|
227
227
|
tcp_calls += 1
|
|
228
|
-
ref = _federated_ref(function_name, args) if connection is None else None
|
|
229
|
-
if ref is not None:
|
|
230
|
-
return _finish(_federated_call(ref, function_name, args))
|
|
231
228
|
wire = os.getenv("REMOTERF_RX_WIRE", "i16").strip().lower()
|
|
232
229
|
if wire and function_name.endswith(":rx:CALL0"):
|
|
233
230
|
# Gate I slice 3: c64 halves the samples on the wire, i16 (the default)
|
|
234
231
|
# quarters them when they are integer IQ; the driver still sees a complex
|
|
235
232
|
# array. REMOTERF_RX_WIRE="" or "c128" opts out (servers ignore unknown).
|
|
233
|
+
# Also through a HOME, whose relay caps each response at ~768 KiB.
|
|
236
234
|
args = {**args, "wire": map_arg(wire)}
|
|
235
|
+
ref = _federated_ref(function_name, args) if connection is None else None
|
|
236
|
+
if ref is not None:
|
|
237
|
+
return _finish(_federated_call(ref, function_name, args))
|
|
237
238
|
if connection is None and direct_path.wants(function_name):
|
|
238
239
|
path = direct_path.current(token=_device_token(function_name, args))
|
|
239
240
|
if path is not None:
|
|
@@ -312,25 +312,39 @@ def _use_home(name: str, *, register: bool, enrollment_code: str | None = None)
|
|
|
312
312
|
)
|
|
313
313
|
|
|
314
314
|
|
|
315
|
+
def _agree_to_tos() -> bool:
|
|
316
|
+
"""Every registration is a fresh agreement, whoever is at the keyboard --
|
|
317
|
+
and starting one forgets the old agreement, so backing out here means
|
|
318
|
+
the next login asks too."""
|
|
319
|
+
from remoterf.config.config import _confirm_tos, forget_tos_agreement, remember_tos_agreement
|
|
320
|
+
|
|
321
|
+
forget_tos_agreement()
|
|
322
|
+
if not _confirm_tos("Do you agree to the RemoteRF Terms of Service? [y/N]: ",
|
|
323
|
+
"Registration cancelled."):
|
|
324
|
+
return False
|
|
325
|
+
remember_tos_agreement()
|
|
326
|
+
return True
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def _register_global() -> int:
|
|
330
|
+
"""`remoterf -r global`: straight to a Global account, same agreement as -r."""
|
|
331
|
+
print_client_banner(_installed_version(), server="")
|
|
332
|
+
if not _agree_to_tos():
|
|
333
|
+
return 1
|
|
334
|
+
return _use_global(register=True, show_banner=False)
|
|
335
|
+
|
|
336
|
+
|
|
315
337
|
def _register() -> int:
|
|
316
338
|
"""`remoterf -r`: a deployment enrollment code, or a Global account."""
|
|
317
339
|
from remoterf_federation_core import ValidationError
|
|
318
340
|
|
|
319
341
|
from remoterf.deployment import homes
|
|
320
342
|
|
|
321
|
-
from remoterf.config.config import _confirm_tos, forget_tos_agreement, remember_tos_agreement
|
|
322
|
-
|
|
323
343
|
# The banner opens the session; the target is not known yet, so the shell
|
|
324
344
|
# below must not print it a second time.
|
|
325
345
|
print_client_banner(_installed_version(), server="")
|
|
326
|
-
|
|
327
|
-
# and starting one forgets the old agreement, so backing out here means
|
|
328
|
-
# the next login asks too.
|
|
329
|
-
forget_tos_agreement()
|
|
330
|
-
if not _confirm_tos("Do you agree to the RemoteRF Terms of Service? [y/N]: ",
|
|
331
|
-
"Registration cancelled."):
|
|
346
|
+
if not _agree_to_tos():
|
|
332
347
|
return 1
|
|
333
|
-
remember_tos_agreement()
|
|
334
348
|
try:
|
|
335
349
|
entered = input('Enrollment code (Enter for a RemoteRF Global account): ').strip()
|
|
336
350
|
except (EOFError, KeyboardInterrupt):
|
|
@@ -434,8 +448,8 @@ def main() -> int:
|
|
|
434
448
|
return 0
|
|
435
449
|
|
|
436
450
|
if argv[0] in ("--register", "-register", "-r"):
|
|
437
|
-
if len(argv) == 2 and argv[1] == "global":
|
|
438
|
-
return
|
|
451
|
+
if len(argv) == 2 and argv[1].lstrip("-") == "global":
|
|
452
|
+
return _register_global()
|
|
439
453
|
if len(argv) > 1:
|
|
440
454
|
print("ERROR: --register takes no arguments (or 'global')")
|
|
441
455
|
return 2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.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
|
|
@@ -52,3 +52,31 @@ def test_register_without_a_code_makes_a_global_account(monkeypatch):
|
|
|
52
52
|
assert remoterf_cli._register() == 0
|
|
53
53
|
use_global.assert_called_once_with(register=True, show_banner=False)
|
|
54
54
|
shell.assert_not_called()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_register_global_asks_for_the_tos_like_register(monkeypatch):
|
|
58
|
+
from remoterf import remoterf_cli
|
|
59
|
+
|
|
60
|
+
for arg in ("global", "-global"):
|
|
61
|
+
monkeypatch.setattr("sys.argv", ["remoterf", "-r", arg])
|
|
62
|
+
with mock.patch("remoterf.config.config._confirm_tos", return_value=True) as confirm, \
|
|
63
|
+
mock.patch("remoterf.config.config.forget_tos_agreement") as forget, \
|
|
64
|
+
mock.patch("remoterf.config.config.remember_tos_agreement") as remember, \
|
|
65
|
+
mock.patch.object(remoterf_cli, "print_client_banner"), \
|
|
66
|
+
mock.patch.object(remoterf_cli, "_use_global", return_value=0) as use_global:
|
|
67
|
+
assert remoterf_cli.main() == 0
|
|
68
|
+
forget.assert_called_once_with()
|
|
69
|
+
confirm.assert_called_once()
|
|
70
|
+
remember.assert_called_once_with()
|
|
71
|
+
use_global.assert_called_once_with(register=True, show_banner=False)
|
|
72
|
+
|
|
73
|
+
# Declining stops before any account is made.
|
|
74
|
+
monkeypatch.setattr("sys.argv", ["remoterf", "-r", "global"])
|
|
75
|
+
with mock.patch("remoterf.config.config._confirm_tos", return_value=False), \
|
|
76
|
+
mock.patch("remoterf.config.config.forget_tos_agreement"), \
|
|
77
|
+
mock.patch("remoterf.config.config.remember_tos_agreement") as remember, \
|
|
78
|
+
mock.patch.object(remoterf_cli, "print_client_banner"), \
|
|
79
|
+
mock.patch.object(remoterf_cli, "_use_global") as use_global:
|
|
80
|
+
assert remoterf_cli.main() == 1
|
|
81
|
+
remember.assert_not_called()
|
|
82
|
+
use_global.assert_not_called()
|
|
@@ -248,6 +248,20 @@ class RoutingTests(unittest.TestCase):
|
|
|
248
248
|
self.assertEqual(unmap_arg(seen[0][1]["wire"]), "c64")
|
|
249
249
|
self.assertEqual(unmap_arg(seen[3][1]["wire"]), "i16")
|
|
250
250
|
|
|
251
|
+
def test_rx_through_a_home_asks_for_i16_too(self):
|
|
252
|
+
# A Global handle's rx goes through the HOME relay, which caps a response
|
|
253
|
+
# at ~768 KiB: complex128 samples overflow it four times sooner.
|
|
254
|
+
from remoterf.core import grpc_client
|
|
255
|
+
|
|
256
|
+
seen = []
|
|
257
|
+
with mock.patch.object(grpc_client, "_federated_ref", return_value="dep:103"), \
|
|
258
|
+
mock.patch.object(grpc_client, "_federated_call",
|
|
259
|
+
side_effect=lambda ref, name, args: seen.append(dict(args)) or grpc_pb2.GenericRPCResponse()), \
|
|
260
|
+
mock.patch.dict("os.environ"):
|
|
261
|
+
os.environ.pop("REMOTERF_RX_WIRE", None)
|
|
262
|
+
grpc_client.rpc_client(function_name="adalm_pluto:rx:CALL0", args={"a": map_arg("dep:103")})
|
|
263
|
+
self.assertEqual(unmap_arg(seen[0]["wire"]), "i16")
|
|
264
|
+
|
|
251
265
|
def test_a_path_that_is_not_ready_is_skipped(self):
|
|
252
266
|
from remoterf.core.grpc_client import rpc_client
|
|
253
267
|
|
|
@@ -482,3 +496,21 @@ class QuietHandlerTests(unittest.TestCase):
|
|
|
482
496
|
finally:
|
|
483
497
|
loop.close()
|
|
484
498
|
self.assertEqual([type(c["exception"]) for c in seen], [ValueError])
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
class BrokenQuicStackTests(unittest.TestCase):
|
|
502
|
+
def test_a_broken_pyopenssl_turns_the_direct_path_off_not_the_client(self):
|
|
503
|
+
# conda can swap in a cryptography the pip-installed pyOpenSSL (aioquic's) cannot use.
|
|
504
|
+
import subprocess
|
|
505
|
+
import sys
|
|
506
|
+
import tempfile
|
|
507
|
+
|
|
508
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
509
|
+
(Path(tmp) / "OpenSSL").mkdir()
|
|
510
|
+
(Path(tmp) / "OpenSSL" / "__init__.py").write_text("raise AttributeError(\"module 'lib' has no attribute 'GEN_EMAIL'\")\n")
|
|
511
|
+
probe = ("from remoterf.core import direct_path, grpc_client; "
|
|
512
|
+
"print(direct_path.enabled(), direct_path.current(), direct_path.describe())")
|
|
513
|
+
result = subprocess.run([sys.executable, "-c", probe], env={**os.environ, "PYTHONPATH": tmp, "HOME": tmp},
|
|
514
|
+
capture_output=True, text=True, timeout=120, stdin=subprocess.DEVNULL)
|
|
515
|
+
self.assertTrue(result.stdout.startswith("False None relay (direct path unavailable: AttributeError"), result.stderr[-2000:])
|
|
516
|
+
|
|
@@ -315,14 +315,15 @@ def test_register_with_a_code_lands_in_the_home_shell(monkeypatch, reachable):
|
|
|
315
315
|
|
|
316
316
|
|
|
317
317
|
def test_a_blank_code_registers_on_global_and_global_has_its_own_spelling(monkeypatch):
|
|
318
|
-
answers = iter(["y", ""])
|
|
318
|
+
answers = iter(["y", "", "y"])
|
|
319
319
|
monkeypatch.setattr("builtins.input", lambda *_: next(answers, ""))
|
|
320
320
|
used_global = mock.Mock(return_value=0)
|
|
321
321
|
assert run_cli(["-r"], monkeypatch, _use_global=used_global) == 0
|
|
322
322
|
used_global.assert_called_once_with(register=True, show_banner=False) # no lab: the account lives on Global
|
|
323
323
|
used_global.reset_mock()
|
|
324
|
+
# `-r global` asks for the Terms too, then skips the code prompt.
|
|
324
325
|
assert run_cli(["-r", "global"], monkeypatch, _use_global=used_global) == 0
|
|
325
|
-
used_global.assert_called_once_with(register=True)
|
|
326
|
+
used_global.assert_called_once_with(register=True, show_banner=False)
|
|
326
327
|
|
|
327
328
|
|
|
328
329
|
def test_declining_the_terms_stops_registration_before_any_code(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.2.0 → remoterf-2.2.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
|