@@ -91,8 +91,10 @@ def jm_single() -> AttributeDict:
9191 'POLICY' : ['absurd_fee_per_kb' , 'taker_utxo_retries' ,
9292 'taker_utxo_age' , 'taker_utxo_amtpercent' ]}
9393
94- _DEFAULT_INTEREST_RATE = "0.015"
94+ _ENV_VAR_PREFIX = "JM_"
95+ _SECTIONS_WITH_SUBSECTIONS = {"MESSAGING" }
9596
97+ _DEFAULT_INTEREST_RATE = "0.015"
9698_DEFAULT_BONDLESS_MAKERS_ALLOWANCE = "0.125"
9799
98100defaultconfig = \
@@ -673,9 +675,8 @@ def _remove_unwanted_default_settings(config: ConfigParser) -> None:
673675 if section .startswith ('MESSAGING:' ):
674676 config .remove_section (section )
675677
676- def load_program_config (config_path : str = "" , bs : Optional [str ] = None ,
677- plugin_services : List [JMPluginService ] = []) -> None :
678- global_singleton .config .read_file (io .StringIO (defaultconfig ))
678+
679+ def set_paths (config_path : str = "" ) -> None :
679680 if not config_path :
680681 config_path = lookup_appdata_folder (global_singleton .APPNAME )
681682 # we set the global home directory, but keep the config_path variable
@@ -692,29 +693,70 @@ def load_program_config(config_path: str = "", bs: Optional[str] = None,
692693 if not os .path .exists (os .path .join (global_singleton .datadir , "cmtdata" )):
693694 os .makedirs (os .path .join (global_singleton .datadir , "cmtdata" ))
694695 global_singleton .config_location = os .path .join (
695- global_singleton .datadir , global_singleton .config_location )
696+ global_singleton .datadir , global_singleton .config_location
697+ )
696698
697- _remove_unwanted_default_settings (global_singleton .config )
699+
700+ def read_config_file () -> bool :
698701 try :
699- loadedFiles = global_singleton .config .read (
700- [global_singleton .config_location ])
702+ loaded = global_singleton .config .read ([global_singleton .config_location ])
701703 except UnicodeDecodeError :
702- jmprint ("Error loading `joinmarket.cfg`, invalid file format." ,
703- "info" )
704+ jmprint ("Error loading `joinmarket.cfg`, invalid file format." , "info" )
704705 sys .exit (EXIT_FAILURE )
706+ return len (loaded ) == 1
707+
705708
709+ def write_config_file (config : str = defaultconfig ) -> bool :
710+ with open (global_singleton .config_location , "w" ) as configfile :
711+ configfile .write (config )
712+ jmprint (
713+ "Created a new `joinmarket.cfg`. Please review and adopt the "
714+ "settings and restart joinmarket." ,
715+ "info" ,
716+ )
717+ sys .exit (EXIT_FAILURE )
718+
719+
720+ def override (config : ConfigParser , bs : Optional [str ] = None ) -> None :
721+ _remove_unwanted_default_settings (config )
706722 # Hack required for bitcoin-rpc-no-history and probably others
707723 # (historicaly electrum); must be able to enforce a different blockchain
708724 # interface even in default/new load.
709725 if bs :
710- global_singleton .config .set ("BLOCKCHAIN" , "blockchain_source" , bs )
711- # Create default config file if not found
712- if len (loadedFiles ) != 1 :
713- with open (global_singleton .config_location , "w" ) as configfile :
714- configfile .write (defaultconfig )
715- jmprint ("Created a new `joinmarket.cfg`. Please review and adopt the "
716- "settings and restart joinmarket." , "info" )
717- sys .exit (EXIT_FAILURE )
726+ config .set ("BLOCKCHAIN" , "blockchain_source" , bs )
727+
728+
729+ def override_from_environment (config : ConfigParser ) -> ConfigParser :
730+ for key , value in os .environ .items ():
731+ if key .startswith (_ENV_VAR_PREFIX ):
732+ key = key .removeprefix (_ENV_VAR_PREFIX )
733+ section , key = key .split ("_" , 1 )
734+ if section in _SECTIONS_WITH_SUBSECTIONS :
735+ sub , key = key .split ("_" , 1 )
736+ section = f"{ section } :{ sub .lower ()} "
737+ key = key .lower ()
738+ if not config .has_section (section ):
739+ config .add_section (section )
740+ log .info (f"Overriding [{ section } ] { key } ={ value } " )
741+ config .set (section , key , value )
742+ return config
743+
744+
745+ def load_program_config (
746+ config_path : str = "" ,
747+ bs : Optional [str ] = None ,
748+ plugin_services : List [JMPluginService ] = [],
749+ from_environment : bool = False ,
750+ ) -> None :
751+ set_paths (config_path )
752+ global_singleton .config .read_string (defaultconfig )
753+ if from_environment :
754+ override_from_environment (global_singleton .config )
755+ else :
756+ override (global_singleton .config , bs )
757+ # Create default config file if not found
758+ if not read_config_file ():
759+ write_config_file ()
718760
719761 loglevel = global_singleton .config .get ("LOGGING" , "console_log_level" )
720762 try :
0 commit comments