RemoteRF 2.5.0__tar.gz → 2.5.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.5.0/src/remoterf.egg-info → remoterf-2.5.1}/PKG-INFO +1 -1
- {remoterf-2.5.0 → remoterf-2.5.1}/pyproject.toml +1 -1
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/direct_path.py +40 -17
- {remoterf-2.5.0 → remoterf-2.5.1/src/remoterf.egg-info}/PKG-INFO +1 -1
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_direct_path_partner.py +65 -3
- {remoterf-2.5.0 → remoterf-2.5.1}/LICENSE +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/README.md +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/setup.cfg +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/grpc/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/grpc/deployment_capabilities.proto +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/grpc/deployment_capabilities_pb2.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/grpc/deployment_capabilities_pb2_grpc.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/grpc/grpc.proto +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/grpc/grpc_pb2.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/grpc/grpc_pb2_grpc.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/grpc/v2_codec.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/tos_notice.txt +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/utils/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/utils/ansi_codes.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/utils/api_token.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/utils/banner.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/utils/list_string.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/common/utils/process_arg.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/config/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/config/cert_fetcher.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/config/config.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/acc_login.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/app.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/banner_note.txt +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/dynamic_v2_transport.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/grpc_acc.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/grpc_client.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/secure_channel.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/core/v2_errors.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/deployment/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/deployment/backend.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/deployment/direct.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/deployment/homes.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/deployment/http.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/deployment/state.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/_virtual.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/adalm_pluto/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/adalm_pluto/adalm_pluto_remote.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/dynamic_device.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/dynamic_v2.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/hackrf/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/hackrf/hackrf_remote.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/rtl_sdr/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/rtl_sdr/rtl_sdr_remote.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/sim_sdr/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/sim_sdr/sim_sdr_remote.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/support/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/support/ti_mmwave.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/support/uhd.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/support/uhd_dsp.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/support/uhd_v2.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/ti_mmwave/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/ti_mmwave/ti_mmwave_remote.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/usrp/__init__.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/usrp/usrp_remote.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/drivers/usrp/usrp_remote.pyi +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/remoterf_cli.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf/version.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf.egg-info/SOURCES.txt +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf.egg-info/dependency_links.txt +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf.egg-info/entry_points.txt +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf.egg-info/requires.txt +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf.egg-info/top_level.txt +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/src/remoterf.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_banner.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_batch.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_cli_login_fresh.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_config_address.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_deployment_accounts.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_device_routes.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_direct_path_fixed.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_direct_path_global.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_direct_path_race.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_dynamic_device_codegen.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_dynamic_v2.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_federated_devices.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_fetch_idl_fallback.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_finish_prompt.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_gate_i_direct_path.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_grpc_client_target.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_homes.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_native_account_credentials.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_native_devices.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_partner_dynamic_v2.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_pluto_virtual.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_process_arg.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_remoterf_cli.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_rx_readahead.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.1}/tests/test_ti_mmwave.py +0 -0
- {remoterf-2.5.0 → remoterf-2.5.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.5.
|
|
3
|
+
Version: 2.5.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.5.
|
|
7
|
+
version = "2.5.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"
|
|
@@ -691,17 +691,25 @@ _partners: dict[str, DirectPath] = {} # device token -> the path to the lab tha
|
|
|
691
691
|
_partner_owners: dict[str, str] = {} # device token -> owner deployment id
|
|
692
692
|
|
|
693
693
|
|
|
694
|
-
def _offer_rpc(username: str, secret: str, token: Optional[str] = None) -> Callable[[dict], dict]:
|
|
695
|
-
"""The offer RPC; with ``token`` the home has the partner lab answer instead.
|
|
694
|
+
def _offer_rpc(username: Optional[str], secret: Optional[str], token: Optional[str] = None) -> Callable[[dict], dict]:
|
|
695
|
+
"""The offer RPC; with ``token`` the home has the partner lab answer instead.
|
|
696
|
+
|
|
697
|
+
Without a login (``username`` None) the partner token alone authorizes it."""
|
|
696
698
|
def send(offer: dict) -> dict:
|
|
697
699
|
from .grpc_client import rpc_client
|
|
698
700
|
|
|
699
|
-
args = {"
|
|
701
|
+
args = {"ice": map_arg(json.dumps(offer))}
|
|
702
|
+
if username is not None:
|
|
703
|
+
args.update(un=map_arg(username), pw=map_arg(secret))
|
|
700
704
|
if token is not None:
|
|
701
705
|
args["a"] = map_arg(token)
|
|
702
706
|
response = rpc_client(function_name="ACC:direct_offer", args=args)
|
|
703
707
|
if "ace" in response.results:
|
|
704
|
-
|
|
708
|
+
reason = unmap_arg(response.results["ace"])
|
|
709
|
+
if username is None and reason.startswith("Internal server error"):
|
|
710
|
+
# A home Server that predates token offers fails on the missing login.
|
|
711
|
+
raise PathUnavailable("the home's Server needs a login for a direct path")
|
|
712
|
+
raise PathError(reason)
|
|
705
713
|
answer = json.loads(unmap_arg(response.results["ice"]))
|
|
706
714
|
for key in ("server_name", "ca_pem"):
|
|
707
715
|
if key in response.results:
|
|
@@ -811,12 +819,18 @@ def _side_path(key: str, make: Callable[[], Optional[DirectPath]]) -> Optional[D
|
|
|
811
819
|
def _partner(token: str) -> Optional[DirectPath]:
|
|
812
820
|
"""The path to the lab owning the device behind ``token``, punched on first use."""
|
|
813
821
|
def make() -> Optional[DirectPath]:
|
|
822
|
+
owner = _partner_owners.get(token)
|
|
814
823
|
credentials = _credentials()
|
|
815
824
|
if credentials is None:
|
|
816
|
-
|
|
825
|
+
# No login (a token-only script): the token is its own credential.
|
|
826
|
+
# Its own memo, so an old home refusing it cannot hold back a
|
|
827
|
+
# logged-in process's path to the same lab.
|
|
828
|
+
return DirectPath(
|
|
829
|
+
offer=_offer_rpc(None, None, token=token), server_name="", ca_pem=b"",
|
|
830
|
+
memo=owner and f"{owner}|token",
|
|
831
|
+
)
|
|
817
832
|
return DirectPath(
|
|
818
|
-
offer=_offer_rpc(*credentials, token=token), server_name="", ca_pem=b"",
|
|
819
|
-
memo=_partner_owners.get(token),
|
|
833
|
+
offer=_offer_rpc(*credentials, token=token), server_name="", ca_pem=b"", memo=owner,
|
|
820
834
|
)
|
|
821
835
|
|
|
822
836
|
return _side_path(token, make)
|
|
@@ -890,18 +904,27 @@ def describe() -> str:
|
|
|
890
904
|
return f"relay (direct path unavailable: {_BROKEN}; fix: pip install --force-reinstall remoterf)"
|
|
891
905
|
if not enabled():
|
|
892
906
|
return "relay (direct path disabled: REMOTERF_DIRECT=0)"
|
|
907
|
+
partners = "; ".join(
|
|
908
|
+
f"partner {_partner_owners[key]}: "
|
|
909
|
+
+ (path.describe() if path.ready else path.describe().replace("relay", "via HOME", 1))
|
|
910
|
+
for key, path in list(_partners.items()) if key in _partner_owners
|
|
911
|
+
)
|
|
893
912
|
path = _path
|
|
894
913
|
if path is not None:
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
914
|
+
home = path.describe()
|
|
915
|
+
else:
|
|
916
|
+
try:
|
|
917
|
+
from .grpc_client import _current_profile
|
|
918
|
+
|
|
919
|
+
route = _active_route(_current_profile())
|
|
920
|
+
except Exception: # noqa: BLE001 - not configured, no home: nothing to add
|
|
921
|
+
route = None
|
|
922
|
+
if route is None or route["kind"] == "relay":
|
|
923
|
+
if partners: # the home path is not what these device calls take
|
|
924
|
+
return partners
|
|
925
|
+
return "relay (direct path off)"
|
|
926
|
+
home = "LAN (direct)" if route["kind"] == "lan" else str(route["kind"])
|
|
927
|
+
return f"{home}; {partners}" if partners else home
|
|
905
928
|
|
|
906
929
|
|
|
907
930
|
def stop() -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.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
|
|
@@ -51,6 +51,9 @@ def setup_function(function):
|
|
|
51
51
|
FakePath.instances.clear()
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
teardown_function = setup_function # no fake path outlives its test
|
|
55
|
+
|
|
56
|
+
|
|
54
57
|
def test_a_marked_token_gets_its_own_path_and_other_tokens_do_not(monkeypatch):
|
|
55
58
|
monkeypatch.setenv("REMOTERF_DIRECT", "1")
|
|
56
59
|
monkeypatch.setattr(direct_path, "DirectPath", FakePath)
|
|
@@ -105,21 +108,80 @@ def test_rpc_client_routes_by_the_token_the_call_carries(monkeypatch):
|
|
|
105
108
|
assert routed[-1] is None # only a string token can name a partner path
|
|
106
109
|
|
|
107
110
|
|
|
108
|
-
def
|
|
111
|
+
def test_no_login_offers_with_the_token_alone_and_disabled_means_none(monkeypatch):
|
|
109
112
|
monkeypatch.setattr(direct_path, "DirectPath", FakePath)
|
|
110
113
|
monkeypatch.setattr(direct_path, "_from_stored_login", lambda: None)
|
|
111
114
|
monkeypatch.setattr(direct_path, "_stored_login", lambda: None)
|
|
112
115
|
direct_path._login = None
|
|
113
116
|
monkeypatch.setenv("REMOTERF_DIRECT", "1")
|
|
114
117
|
direct_path.mark_partner("tok", "owner-uuid")
|
|
115
|
-
|
|
118
|
+
path = direct_path.current(token="tok")
|
|
119
|
+
assert path is FakePath.instances[0] and path.memo == "owner-uuid|token" # its own memo scope
|
|
120
|
+
seen = {}
|
|
121
|
+
|
|
122
|
+
def fake_rpc(*, function_name, args, connection=None):
|
|
123
|
+
seen.update(function_name=function_name, args={k: unmap_arg(v) for k, v in args.items()})
|
|
124
|
+
return grpc_pb2.GenericRPCResponse(results={"ice": map_arg("{}")})
|
|
125
|
+
|
|
126
|
+
monkeypatch.setattr(grpc_client, "rpc_client", fake_rpc)
|
|
127
|
+
path.offer({"id": "x"})
|
|
128
|
+
assert seen["function_name"] == "ACC:direct_offer" and sorted(seen["args"]) == ["a", "ice"]
|
|
129
|
+
assert seen["args"]["a"] == "tok"
|
|
130
|
+
direct_path.stop()
|
|
116
131
|
direct_path._login = ("alice", "secret")
|
|
117
|
-
assert direct_path.current(token="tok")
|
|
132
|
+
assert direct_path.current(token="tok").memo == "owner-uuid" # a login signs as before
|
|
118
133
|
monkeypatch.setenv("REMOTERF_DIRECT", "0")
|
|
119
134
|
assert direct_path.current(token="tok") is None # disabled: nothing, however marked
|
|
120
135
|
direct_path._login = None
|
|
121
136
|
|
|
122
137
|
|
|
138
|
+
def test_an_old_home_refusing_a_token_offer_means_no_direct_path(monkeypatch):
|
|
139
|
+
replies = []
|
|
140
|
+
monkeypatch.setattr(grpc_client, "rpc_client", lambda **k: grpc_pb2.GenericRPCResponse(
|
|
141
|
+
results={"ace": map_arg(replies.pop())}))
|
|
142
|
+
send = direct_path._offer_rpc(None, None, token="tok")
|
|
143
|
+
# A Server older than token offers fails reading the missing login.
|
|
144
|
+
replies.append("Internal server error; please try again or contact your instructor.")
|
|
145
|
+
try:
|
|
146
|
+
send({})
|
|
147
|
+
except direct_path.PathUnavailable as exc:
|
|
148
|
+
assert "needs a login" in str(exc)
|
|
149
|
+
else:
|
|
150
|
+
raise AssertionError("an old home must stop the path")
|
|
151
|
+
replies.append("That reservation is not active now.") # a new home's refusal: retried later
|
|
152
|
+
try:
|
|
153
|
+
send({})
|
|
154
|
+
except direct_path.PathError as exc:
|
|
155
|
+
assert not isinstance(exc, direct_path.PathUnavailable)
|
|
156
|
+
else:
|
|
157
|
+
raise AssertionError("a refusal is no answer")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_describe_reports_partner_paths(monkeypatch):
|
|
161
|
+
monkeypatch.setattr(direct_path, "DirectPath", FakePath)
|
|
162
|
+
monkeypatch.setattr(direct_path, "_from_stored_login", lambda: None)
|
|
163
|
+
monkeypatch.setattr(grpc_client, "_current_profile", lambda: None)
|
|
164
|
+
monkeypatch.setattr(direct_path, "_active_route", lambda profile: None)
|
|
165
|
+
monkeypatch.setattr(direct_path, "_credentials", lambda: None)
|
|
166
|
+
monkeypatch.setenv("REMOTERF_DIRECT", "1")
|
|
167
|
+
assert direct_path.describe() == "relay (direct path off)" # nothing partnered yet
|
|
168
|
+
direct_path.mark_partner("tok", "lab-b")
|
|
169
|
+
path = direct_path.current(token="tok")
|
|
170
|
+
path.describe = lambda: "direct 192.0.2.7:4433 (3 calls)"
|
|
171
|
+
assert direct_path.describe() == "partner lab-b: direct 192.0.2.7:4433 (3 calls)"
|
|
172
|
+
path.state = "down"
|
|
173
|
+
path.describe = lambda: "relay (direct path down: timed out; retrying)"
|
|
174
|
+
assert direct_path.describe() == "partner lab-b: via HOME (direct path down: timed out; retrying)"
|
|
175
|
+
direct_path._path = home = FakePath(offer=None, server_name="", ca_pem=b"")
|
|
176
|
+
home.describe = lambda: "direct 192.0.2.1:4433"
|
|
177
|
+
assert direct_path.describe() == (
|
|
178
|
+
"direct 192.0.2.1:4433; partner lab-b: via HOME (direct path down: timed out; retrying)"
|
|
179
|
+
)
|
|
180
|
+
direct_path._path = None
|
|
181
|
+
monkeypatch.setattr(direct_path, "_active_route", lambda profile: {"kind": "lan"})
|
|
182
|
+
assert direct_path.describe().startswith("LAN (direct); partner lab-b: via HOME")
|
|
183
|
+
|
|
184
|
+
|
|
123
185
|
def test_a_partner_path_that_is_down_sends_the_call_to_the_home(monkeypatch):
|
|
124
186
|
monkeypatch.setattr(direct_path, "DirectPath", FakePath)
|
|
125
187
|
direct_path._login = ("alice", "secret")
|
|
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.5.0 → remoterf-2.5.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|