Package: pipcs
PIPCS: PIPCS is Python Configuration Systempipcs is an experimental library to create configuration files for Python.Installationpipinstallpipcs--userDocumentationhttps://pipcs.readthedocs.io/Examplehttps://github.com/goktug97/nes-torch/blob/master/nes/config.pyExample ScenarioIn some_program.py:fromdataclassesimportfieldfromtypingimportDict,Type,Callable,Union,ListimporttorchimportnumpyasnpimportgymfrompipcsimportConfig,Choices,Condition,Required,requireddefault_config=Config()@default_config('optimizer')classOptimizerConfig():optim_type:Choices[Type[torch.optim.Optimizer]]=Choices([torch.optim.Adam,torch.optim.SGD],default=torch.optim.Adam)weight_decay:float=0.0lr:float=0.001betas:Condition[Tuple[float,float]]=Condition((0.9,0.999),optim_type==torch.optim.Adam)eps:Condition[float]=Condition(1e-08,optim_type==torch.optim.Adam)momentum:Condition[float]=Condition(0.0,optim_type==torch.optim.SGD)dampening:Condition[float]=Condition(0.0,optim_type==torch.optim.SGD)@default_config('environment')classEnvironmentConfig():env_id:Required[str]=required@default_config('policy')classPolicyConfig():input_size:Required[int]=requiredhidden_layers:List[int]=field(default_factory=lambda:[])output_size:Required[int]=requiredoutput_func:Required[Callable[[torch.Tensor],Union[int,np.ndarray]]]=requiredactivation:torch.nn.Module=torch.nn.ReLUclassPolicy(torch.nn.Module):def__init__(self,input_size,hidden_layers,output_size,activation,output_func):super().__init__()self.seq=torch.nn.Sequential(torch.nn.Linear(input_size,64),activation(),torch.nn.Linear(64,64),activation(),torch.nn.Linear(64,output_size))classReinforcementLearning():def__init__(self,config:Config=default_config):self.config=configself.policy=Policy(**config.policy.to_dict())self.optim=self.make_optimizer(parameters=self.policy.parameters(),**config.optimizer.to_dict())self.env=gym.make(config.environment.env_id)defmake_optimizer(self,optim_type,parameters,**kwargs):returnoptim_type(parameters,**kwargs)In user file:frompipcsimportConfig,Conditionimportgymimporttorchfromdataclassesimportfieldfromsome_programimportdefault_config,ReinforcementLearninguser_config=Config(default_config)@user_config('optimizer')classUserOptimizerConfig():optim_type=torch.optim.Adam# Users can add their own variables tooamsgrad:Condition[bool]=Condition(False,default_config.optimizer.optim_type==torch.optim.Adam)nesterov:Condition[bool]=Condition(False,default_config.optimizer.optim_type==torch.optim.SGD)@user_config('environment')classUserEnvironmentConfig():env_id='CartPole-v1'@user_config('policy')classUserPolicyConfig():env=gym.make(user_config.environment.env_id)input_size=env.observation_space.shape[0]hidden_layers=field(default_factory=lambda:[64,32])ifisinstance(env.action_space,gym.spaces.Discrete):output_size=env.action_space.noutput_func=lambdax:x.argmax().item()else:output_size=env.action_space.shape[0]output_func=lambdax:x.detach().numpy()ReinforcementLearning(user_config)Note: If a config is not inherited,typingis necessary. Also, if you are adding your own variable to the inherited config and want it to be register, you need to specify the type. Putting the correct type is not necessary.'typing.Any'can be used if you don't want to bother withtypingbut they are important if you are using a static type checking tool such asmypy.Accessing Variables>>>frompipcsimportConfig>>>>>>config=Config()>>>>>>@config.add('configuration')...classFoo():...bar:str='bar'...baz:int=1...>>>print(config.configuration.bar)bar>>>print(config.configuration.baz)1>>>print(config['configuration']['bar'])bar