| | | |
Offset 64, 197 lines modified | Offset 64, 1122 lines modified |
64 | ······)·->·Optional[importlib.machinery.ModuleSpec]: | 64 | ······)·->·Optional[importlib.machinery.ModuleSpec]: |
65 | ········if·fullname·not·in·self.modules: | 65 | ········if·fullname·not·in·self.modules: |
66 | ············return·None | 66 | ············return·None |
67 | ········return·importlib.util.spec_from_loader(fullname,·self) | 67 | ········return·importlib.util.spec_from_loader(fullname,·self) |
| |
68 | import·sys | 68 | import·sys |
69 | sys.meta_path.insert(0,·BeipackLoader({ | 69 | sys.meta_path.insert(0,·BeipackLoader({ |
70 | ··'cockpit/_version.py':·br'''__version__·=·'311' | |
71 | ''', | |
72 | ··'cockpit/jsonutil.py':·r'''#·This·file·is·part·of·Cockpit. | 70 | ··'cockpit/peer.py':·r'''#·This·file·is·part·of·Cockpit. |
73 | # | 71 | # |
74 | #·Copyright·(C)·2023·Red·Hat,·Inc. | 72 | #·Copyright·(C)·2022·Red·Hat,·Inc. |
75 | # | 73 | # |
76 | #·This·program·is·free·software:·you·can·redistribute·it·and/or·modify | 74 | #·This·program·is·free·software:·you·can·redistribute·it·and/or·modify |
77 | #·it·under·the·terms·of·the·GNU·General·Public·License·as·published·by | 75 | #·it·under·the·terms·of·the·GNU·General·Public·License·as·published·by |
78 | #·the·Free·Software·Foundation,·either·version·3·of·the·License,·or | 76 | #·the·Free·Software·Foundation,·either·version·3·of·the·License,·or |
79 | #·(at·your·option)·any·later·version. | 77 | #·(at·your·option)·any·later·version. |
80 | # | 78 | # |
81 | #·This·program·is·distributed·in·the·hope·that·it·will·be·useful, | 79 | #·This·program·is·distributed·in·the·hope·that·it·will·be·useful, |
82 | #·but·WITHOUT·ANY·WARRANTY;·without·even·the·implied·warranty·of | 80 | #·but·WITHOUT·ANY·WARRANTY;·without·even·the·implied·warranty·of |
83 | #·MERCHANTABILITY·or·FITNESS·FOR·A·PARTICULAR·PURPOSE.··See·the | 81 | #·MERCHANTABILITY·or·FITNESS·FOR·A·PARTICULAR·PURPOSE.··See·the |
84 | #·GNU·General·Public·License·for·more·details. | 82 | #·GNU·General·Public·License·for·more·details. |
85 | # | 83 | # |
86 | #·You·should·have·received·a·copy·of·the·GNU·General·Public·License | 84 | #·You·should·have·received·a·copy·of·the·GNU·General·Public·License |
87 | #·along·with·this·program.··If·not,·see·<https://www.gnu.org/licenses/>. | 85 | #·along·with·this·program.··If·not,·see·<https://www.gnu.org/licenses/>. |
| |
88 | from·enum·import·Enum | |
89 | from·typing·import·Callable,·Dict,·List,·Mapping,·Optional,·Sequence,·Type,·TypeVar,·Union | 86 | import·asyncio |
| 87 | import·logging |
| 88 | import·os |
| 89 | from·typing·import·Callable,·List,·Optional,·Sequence |
| |
90 | JsonLiteral·=·Union[str,·float,·bool,·None] | 90 | from·.jsonutil·import·JsonObject,·JsonValue |
| 91 | from·.packages·import·BridgeConfig |
| 92 | from·.protocol·import·CockpitProblem,·CockpitProtocol,·CockpitProtocolError |
| 93 | from·.router·import·Endpoint,·Router,·RoutingRule |
| 94 | from·.transports·import·SubprocessProtocol,·SubprocessTransport |
| |
| 95 | logger·=·logging.getLogger(__name__) |
91 | #·immutable | |
92 | JsonValue·=·Union['JsonObject',·Sequence['JsonValue'],·JsonLiteral] | |
93 | JsonObject·=·Mapping[str,·JsonValue] | |
| |
94 | #·mutable | |
95 | JsonDocument·=·Union['JsonDict',·'JsonList',·JsonLiteral] | |
96 | JsonDict·=·Dict[str,·JsonDocument] | |
97 | JsonList·=·List[JsonDocument] | |
| |
| 96 | class·PeerError(CockpitProblem): |
| 97 | ····pass |
| |
98 | DT·=·TypeVar('DT') | |
99 | T·=·TypeVar('T') | |
| |
| 98 | class·PeerExited(Exception): |
| 99 | ····def·__init__(self,·exit_code:·int): |
| 100 | ········self.exit_code·=·exit_code |
| |
100 | class·JsonError(Exception): | |
101 | ····value:·object | |
| |
102 | ····def·__init__(self,·value:·object,·msg:·str): | |
103 | ········super().__init__(msg) | |
104 | ········self.value·=·value | 101 | class·Peer(CockpitProtocol,·SubprocessProtocol,·Endpoint): |
| 102 | ····done_callbacks:·List[Callable[[],·None]] |
| 103 | ····init_future:·Optional[asyncio.Future] |
| |
| 104 | ····def·__init__(self,·router:·Router): |
| 105 | ········super().__init__(router) |
| |
| 106 | ········#·All·Peers·start·out·frozen·—·we·only·unfreeze·after·we·see·the·first·'init'·message |
| 107 | ········self.freeze_endpoint() |
105 | def·typechecked(value:·JsonValue,·expected_type:·Type[T])·->·T: | |
106 | ····"""Ensure·a·JSON·value·has·the·expected·type,·returning·it·if·so.""" | |
107 | ····if·not·isinstance(value,·expected_type): | |
108 | ········raise·JsonError(value,·f'must·have·type·{expected_type.__name__}') | |
109 | ····return·value | |
| |
| 108 | ········self.init_future·=·asyncio.get_running_loop().create_future() |
| 109 | ········self.done_callbacks·=·[] |
| |
| 110 | ····#·Initialization |
| 111 | ····async·def·do_connect_transport(self)·->·None: |
| 112 | ········raise·NotImplementedError |
110 | #·We·can't·use·None·as·a·sentinel·because·it's·often·the·actual·default·value | |
111 | #·EllipsisType·is·difficult·because·it's·not·available·before·3.10. | |
112 | #·See·https://peps.python.org/pep-0484/#support-for-singleton-types-in-unions | |
113 | class·_Empty(Enum): | |
114 | ····TOKEN·=·0 | |
| |
| 113 | ····async·def·spawn(self,·argv:·Sequence[str],·env:·Sequence[str],·**kwargs)·->·asyncio.Transport: |
| 114 | ········#·Not·actually·async... |
| 115 | ········loop·=·asyncio.get_running_loop() |
| 116 | ········user_env·=·dict(e.split('=',·1)·for·e·in·env) |
| 117 | ········return·SubprocessTransport(loop,·self,·argv,·env=dict(os.environ,·**user_env),·**kwargs) |
| |
115 | _empty·=·_Empty.TOKEN | 118 | ····async·def·start(self,·init_host:·Optional[str]·=·None,·**kwargs:·JsonValue)·->·JsonObject: |
| 119 | ········"""Request·that·the·Peer·is·started·and·connected·to·the·router. |
| |
| 120 | ········Creates·the·transport,·connects·it·to·the·protocol,·and·participates·in |
| 121 | ········exchanging·of·init·messages.··If·anything·goes·wrong,·the·connection |
| 122 | ········will·be·closed·and·an·exception·will·be·raised. |
| |
| 123 | ········The·Peer·starts·out·in·a·frozen·state·(ie:·attempts·to·send·messages·to |
| 124 | ········it·will·initially·be·queued).·If·init_host·is·not·None·then·an·init |
| 125 | ········message·is·sent·with·the·given·'host'·field,·plus·any·extra·kwargs,·and |
| 126 | ········the·queue·is·thawed.·Otherwise,·the·caller·is·responsible·for·sending |
| 127 | ········the·init·message·and·thawing·the·peer. |
116 | def·_get(obj:·JsonObject,·cast:·Callable[[JsonValue],·T],·key:·str,·default:·Union[DT,·_Empty])·->·Union[T,·DT]: | |
117 | ····try: | |
118 | ········return·cast(obj[key]) | |
119 | ····except·KeyError: | |
120 | ········if·default·is·not·_empty: | |
121 | ············return·default | |
122 | ········raise·JsonError(obj,·f"attribute·'{key}'·required")·from·None | |
123 | ····except·JsonError·as·exc: | |
124 | ········target·=·f"attribute·'{key}'"·+·('·elements:'·if·exc.value·is·not·obj[key]·else·':') | |
125 | ········raise·JsonError(obj,·f"{target}·{exc!s}")·from·exc | |
| |
| 128 | ········In·any·case,·the·return·value·is·the·init·message·from·the·peer. |
| 129 | ········""" |
| 130 | ········assert·self.init_future·is·not·None |
| |
126 | def·get_bool(obj:·JsonObject,·key:·str,·default:·Union[DT,·_Empty]·=·_empty)·->·Union[DT,·bool]: | |
127 | ····return·_get(obj,·lambda·v:·typechecked(v,·bool),·key,·default) | 131 | ········def·_connect_task_done(task:·asyncio.Task)·->·None: |
| 132 | ············assert·task·is·connect_task |
| 133 | ············try: |
Max diff block lines reached; 493572/499310 bytes (98.85%) of diff not shown.
|