Package: simple-dataclass-configuration
Simple ConfBasic UsageimportdataclassesfromtypingimportListfromuuidimportuuid4fromsimpleconf.configimportBaseJsonConfig@dataclasses.dataclassclassUserProfile(BaseJsonConfig):name:str=""uid:int|str=-1email:str=""password:str=""is_admin:bool=Falsetags:List[str]=dataclasses.field(default_factory=list)profile=UserProfile()profile.name="Tom"profile.uid=uuid4().hexprofile.email="tom@gmail.com"profile.tags.extend(("Engineer","Artist"))# 序列化serialized=profile.serialize(indent=2)print(serialized)# 保存到文件profile.save("demo_profile.json")# 反序列化profile2=UserProfile.deserialize(serialized)print(profile2)# 读取文件profile3=UserProfile.load("demo_profile.json")print(profile3)assertprofile.uid==profile2.uid==profile3.uidMultiple FormatsimportdataclassesfromtypingimportListfromsimpleconf.configimportBaseJsonConfig,BaseTomlConfig,BaseYamlConfig# 使用dataclass定义配置对象结构# 支持将一个dataclass嵌入到其他dataclass中# BaseAppConfig#  - environment#  - ServerConfig#  - RuntimeConfig#  - MySqlConfig@dataclasses.dataclassclassServerConfig(object):httpPort:int=8080websocketPort:int=8080domain:str="localhost"password:str=""bannedIps:List[str]=dataclasses.field(default_factory=list)bannedClientIds:List[str]=dataclasses.field(default_factory=list)bannedHostnames:List[str]=dataclasses.field(default_factory=list)@dataclasses.dataclassclassRuntimeConfig(object):debug:bool=TrueenableLogging:bool=False@dataclasses.dataclassclassMySqlConfig(object):host:str='localhost'user:str=''password:str=''database:str=''@dataclasses.dataclassclassBaseAppConfig(object):environment:str="local"server:ServerConfig=ServerConfig()mysql:MySqlConfig=MySqlConfig()runtime:RuntimeConfig=RuntimeConfig()# 提供继承@dataclasses.dataclassclassAppJsonConfig(BaseAppConfig,BaseJsonConfig):pass@dataclasses.dataclassclassAppTomlConfig(BaseAppConfig,BaseTomlConfig):pass@dataclasses.dataclassclassAppYamlConfig(BaseAppConfig,BaseYamlConfig):passdeftest_json_config():json_conf=AppJsonConfig()json_conf.runtime.debug=Truejson_conf.mysql.user="root"json_conf.mysql.password="password"json_conf.mysql.database="test_db"json_conf.server.bannedIps.append("999.999.999.999")json_conf.server.bannedClientIds.append("df3453rewr349543utff")serialized=json_conf.serialize(indent=2)print(serialized)json_conf2=AppJsonConfig.deserialize(serialized)print(json_conf2)json_conf.save("test.json",indent=4)json_conf3=AppJsonConfig.load("test.json")print(json_conf3)deftest_yaml_config():yaml_conf=AppYamlConfig()yaml_conf.runtime.debug=Trueyaml_conf.mysql.user="root"yaml_conf.mysql.password="password"yaml_conf.mysql.database="test_db"yaml_conf.server.bannedIps.append("999.999.999.999")yaml_conf.server.bannedClientIds.append("df3453rewr349543utff")print(yaml_conf.serialize())yaml_conf2=AppYamlConfig.deserialize(yaml_conf.serialize())print(yaml_conf2)yaml_conf2.save("test.yaml",indent=4)yaml_conf3=AppYamlConfig.load("test.yaml")print(yaml_conf3)deftest_toml_config():toml_conf=AppTomlConfig()toml_conf.runtime.debug=Truetoml_conf.mysql.user="root"toml_conf.mysql.password="password"toml_conf.mysql.database="test_db"toml_conf.server.bannedIps.append("999.999.999.999")toml_conf.server.bannedClientIds.append("df3453rewr349543utff")print(toml_conf.serialize())toml_conf2=AppTomlConfig.deserialize(toml_conf.serialize())print(toml_conf2)toml_conf2.save("test.toml")toml_conf3=AppTomlConfig.load("test.toml")print(toml_conf3)if__name__=='__main__':test_json_config()test_toml_config()test_yaml_config()Field ValidationimportdataclassesfromtypingimportListimportmarshmallow.validatefrommarshmallowimportValidationErrorfromsimpleconf.configimportBaseJsonConfig@dataclasses.dataclassclassProjectConfig(BaseJsonConfig):name:strdescription:str="<description>"author:str="<author>"author_email:str="<email>"license:str="MIT"version:str="0.1"install_requires:List[str]=dataclasses.field(default_factory=list)try:# 以下代码将引发异常，因为缺少必要字段"name"conf=ProjectConfig.deserialize("{}")exceptValidationErrorase:print(e)try:# 以下代码将引发异常，因为version字段不是字符串# 在上面的ProjectConfig类中，version的类型提示为str，若要其同时支持字符串和数字，可以使用 str|int作为其类型提示conf2=ProjectConfig.deserialize("""{"name": "demo","version": 1}""")exceptValidationErrorase:print(e)try:# 以下代码将引发异常，因为install_requires被定义为List[str]类型，但下面的install_requires中的第一个元素为int类型conf3=ProjectConfig.deserialize("""{"name": "demo","version": "1.0","install_requires": [1, "toml"]}""")exceptValidationErrorase:print(e)# 除了类型注释可以为验证器提供足够的信息外，还可以利用dataclass字段的metadata信息为字段提供更加精细的验证器# 做法是在metadata中添加一个validate属性，该属性的值为marshmallow.validate.Validator类的实例# 例如在下面的User类中，age字段的metadata中添加了validate属性，其值为marshmallow自带的一个Validator——Range# 作用是限制age字段的值必须在18~60之间@dataclasses.dataclassclassUser(BaseJsonConfig):name:strage:int=dataclasses.field(metadata={"validate":marshmallow.validate.Range(min=18,max=60)},default=18)try:# user1 okuser1=User.deserialize("""{"name": "tom", "age": 18}""")# user2 会抛出异常，因为age的值超出了18~60的范围user2=User.deserialize("""{"name": "tom", "age": 100}""")exceptValidationErrorase:print(e)