1
+ from abc import (
2
+ ABC ,
3
+ abstractmethod ,
4
+ )
1
5
import argparse
2
6
from contextlib import contextmanager
3
7
import json
6
10
Any ,
7
11
cast ,
8
12
Dict ,
13
+ Iterable ,
9
14
TYPE_CHECKING ,
10
15
Tuple ,
11
16
Type ,
17
+ TypeVar ,
12
18
Union ,
13
19
)
14
20
@@ -185,6 +191,9 @@ def vm_configuration(self) -> VMConfiguration:
185
191
return self .genesis_data .vm_configuration
186
192
187
193
194
+ TAppConfig = TypeVar ('TAppConfig' , bound = 'BaseAppConfig' )
195
+
196
+
188
197
class TrinityConfig :
189
198
_trinity_root_dir : Path = None
190
199
@@ -203,6 +212,8 @@ class TrinityConfig:
203
212
204
213
_genesis_config : Dict [str , Any ] = None
205
214
215
+ _app_configs : Dict [Type ['BaseAppConfig' ], 'BaseAppConfig' ] = None
216
+
206
217
def __init__ (self ,
207
218
network_id : int ,
208
219
genesis_config : Dict [str , Any ]= None ,
@@ -222,6 +233,7 @@ def __init__(self,
222
233
self .sync_mode = sync_mode
223
234
self .port = port
224
235
self .use_discv5 = use_discv5
236
+ self ._app_configs = {}
225
237
226
238
if genesis_config is not None :
227
239
self .genesis_config = genesis_config
@@ -285,14 +297,6 @@ def sync_mode(self, value: str) -> None:
285
297
raise ValueError (f"Unknown sync mode: { value } " )
286
298
self ._sync_mode = value
287
299
288
- @property
289
- def is_light_mode (self ) -> bool :
290
- return self .sync_mode == SYNC_LIGHT
291
-
292
- @property
293
- def is_full_mode (self ) -> bool :
294
- return self .sync_mode == SYNC_FULL
295
-
296
300
@property
297
301
def logfile_path (self ) -> Path :
298
302
"""
@@ -440,14 +444,89 @@ def nodekey(self, value: Union[bytes, PrivateKey]) -> None:
440
444
f"`PrivateKey` instance: got { type (self ._nodekey )} "
441
445
)
442
446
447
+ @contextmanager
448
+ def process_id_file (self , process_name : str ): # type: ignore
449
+ with PidFile (process_name , self .data_dir ):
450
+ yield
451
+
443
452
@classmethod
444
- def from_parser_args (cls , parser_args : argparse .Namespace ) -> 'TrinityConfig' :
453
+ def from_parser_args (cls ,
454
+ parser_args : argparse .Namespace ,
455
+ app_config_types : Iterable [Type ['BaseAppConfig' ]]) -> 'TrinityConfig' :
445
456
"""
446
457
Helper function for initializing from the namespace object produced by
447
458
an ``argparse.ArgumentParser``
448
459
"""
449
460
constructor_kwargs = construct_trinity_config_params (parser_args )
450
- return cls (** constructor_kwargs )
461
+ trinity_config = cls (** constructor_kwargs )
462
+
463
+ trinity_config .initialize_app_configs (parser_args , app_config_types )
464
+
465
+ return trinity_config
466
+
467
+ def initialize_app_configs (self ,
468
+ parser_args : argparse .Namespace ,
469
+ app_config_types : Iterable [Type ['BaseAppConfig' ]]) -> None :
470
+ """
471
+ Initialize all available ``BaseAppConfig`` based on their concrete types,
472
+ the ``parser_args`` and the existing ``TrinityConfig`` instance.
473
+ """
474
+ for app_config_type in app_config_types :
475
+ self .add_app_config (app_config_type .from_parser_args (parser_args , self ))
476
+
477
+ def add_app_config (self , app_config : 'BaseAppConfig' ) -> None :
478
+ """
479
+ Register the given ``app_config``.
480
+ """
481
+ self ._app_configs [type (app_config )] = app_config
482
+
483
+ def has_app_config (self , app_config_type : Type ['BaseAppConfig' ]) -> bool :
484
+ """
485
+ Check if a ``BaseAppConfig`` exists based on the given ``app_config_type``.
486
+ """
487
+ return app_config_type in self ._app_configs .keys ()
488
+
489
+ def get_app_config (self , app_config_type : Type [TAppConfig ]) -> TAppConfig :
490
+ """
491
+ Return the ``BaseAppConfig`` derived instance based on the given ``app_config_type``.
492
+ """
493
+ # We want this API to return the specific type of the app config that is requested.
494
+ # Our backing field only knows that it is holding `BaseAppConfig`'s but not concrete types
495
+ return cast (TAppConfig , self ._app_configs [app_config_type ])
496
+
497
+
498
+ class BaseAppConfig (ABC ):
499
+
500
+ def __init__ (self , trinity_config : TrinityConfig ):
501
+ self .trinity_config = trinity_config
502
+
503
+ @classmethod
504
+ @abstractmethod
505
+ def from_parser_args (cls ,
506
+ args : argparse .Namespace ,
507
+ trinity_config : TrinityConfig ) -> 'BaseAppConfig' :
508
+ """
509
+ Initialize from the namespace object produced by
510
+ an ``argparse.ArgumentParser`` and the ``TrinityConfig``
511
+ """
512
+ pass
513
+
514
+
515
+ class Eth1AppConfig (BaseAppConfig ):
516
+
517
+ @classmethod
518
+ def from_parser_args (cls ,
519
+ args : argparse .Namespace ,
520
+ trinity_config : TrinityConfig ) -> 'BaseAppConfig' :
521
+ return cls (trinity_config )
522
+
523
+ @property
524
+ def is_light_mode (self ) -> bool :
525
+ return self .trinity_config .sync_mode == SYNC_LIGHT
526
+
527
+ @property
528
+ def is_full_mode (self ) -> bool :
529
+ return self .trinity_config .sync_mode == SYNC_FULL
451
530
452
531
@property
453
532
def node_class (self ) -> Type ['Node' ]:
@@ -464,7 +543,11 @@ def node_class(self) -> Type['Node']:
464
543
else :
465
544
raise NotImplementedError ("Only full and light sync modes are supported" )
466
545
467
- @contextmanager
468
- def process_id_file (self , process_name : str ): # type: ignore
469
- with PidFile (process_name , self .data_dir ):
470
- yield
546
+
547
+ class BeaconAppConfig (BaseAppConfig ):
548
+
549
+ @classmethod
550
+ def from_parser_args (cls ,
551
+ args : argparse .Namespace ,
552
+ trinity_config : TrinityConfig ) -> 'BaseAppConfig' :
553
+ return cls (trinity_config )
0 commit comments