Package: yamldataclassconfig
YAML Data Class ConfigThis project helps you to import config file writen by YAML to
PythonData Classes.AdvantageType safe import from YAML to Data ClassesGlobal access and easy unit testing1. Type safe import from YAML to Data classesWhen using pyyaml to import YAML, values be dict and list objects.
Using dict or list object will cause such confuses:Reference non exist properties for unexpected instance typeTypo of index or key nameTo prevent these confuse, one of good way is to use object as model,
and python has a good moduleData Classesfor this purpose.2. Global access and easy unit testingYou will want to refer config as global
because it's troublesome to pass config value as argument over and over like a bucket brigade.However, when unit testing,
if YAML file was loaded automatically on importing global definition,
you will face problem that
you can't replace config YAML file with the one for unit testing.
YAML Data Class Config can divide timings between definition global instance and
loading YAML file so you can replace YAML file for unit testing.Quickstart1. Installpip install yamldataclassconfig2. Prepare config YAML filePutconfig.ymlYAML Data class Config loadsconfig.ymlon Python execution directory by default.property_a:1property_b:'2'part_config:property_c:'2019-06-2513:33:30'3. Create config classAnywhere is OK, for example, I prefer to place onmyproduct/config.pyfromdataclassesimportdataclass,fieldfromdatetimeimportdatetimefromdataclasses_jsonimportDataClassJsonMixinfrommarshmallowimportfieldsfromyamldataclassconfig.configimportYamlDataClassConfig@dataclassclassPartConfig(DataClassJsonMixin):property_c:datetime=field(metadata={'dataclasses_json':{'encoder':datetime.isoformat,'decoder':datetime.fromisoformat,'mm_field':fields.DateTime(format='iso')}})@dataclassclassConfig(YamlDataClassConfig):property_a:int=Noneproperty_b:str=Nonepart_config:PartConfig=field(default=None,metadata={'dataclasses_json':{'mm_field':PartConfig}})4. Define as globalAlso, anywhere is OK, for example, I prefer to place onmyproduct/__init__.pyfrommyproduct.configimportConfigCONFIG:Config=Config()5. Call load before reference config valuefrommyproductimportCONFIGdefmain():CONFIG.load()print(CONFIG.property_a)print(CONFIG.property_b)print(CONFIG.part_config.property_c)if__name__=='__main__':main()How do I...Fix path to yaml file independent on the Python execution directory?overrideFILE_PATHproperty.Ex:fromdataclassesimportdataclassfrompathlibimportPathfromyamldataclassconfigimportcreate_file_path_fieldfromyamldataclassconfig.configimportYamlDataClassConfig@dataclassclassConfig(YamlDataClassConfig):some_property:str=None# ...FILE_PATH:Path=create_file_path_field(Path(__file__).parent.parent/'config.yml')Switch target YAML config file to the one for unit testing?When setup on unit testing, you can callConfig.load()with argument.Case when unittest:frompathlibimportPathimportunittestfromyourproductimportCONFIGclassConfigurableTestCase(unittest.TestCase):defsetUp(self):CONFIG.load(Path('path/to/yaml'))Case when pytest:frompathlibimportPathimportpytestfromyourproductimportCONFIG@pytest.fixturedefyaml_config():CONFIG.load(Path('path/to/yaml'))yielddeftest_something(yaml_config):"""test something"""Use path to YAML config file as same as production when test?fixturefilehandlercan replace config.yml with tests/config.yml.dist easily.
Please call allDeployerFactory.createwithYamlConfigFilePathBuilderinstance argument
to create ConfigDeployer.
Then, set target directory which config.yml should be placed intopath_target_directory.Case when unittest:frompathlibimportPathimportunittestfromfixturefilehandler.factoriesimportDeployerFactoryfromfixturefilehandler.file_pathsimportYamlConfigFilePathBuilderfromyourproductimportCONFIGConfigDeployer=DeployerFactory.create(YamlConfigFilePathBuilder(path_target_directory=Path(__file__).parent.parent))classConfigurableTestCase(unittest.TestCase):defsetUp(self):ConfigDeployer.setup()CONFIG.load()defdoCleanups(self):ConfigDeployer.teardown()Case when pytest:frompathlibimportPathimportpytestfromfixturefilehandler.factoriesimportDeployerFactoryfromfixturefilehandler.file_pathsimportYamlConfigFilePathBuilderfromyourproductimportCONFIGConfigDeployer=DeployerFactory.create(YamlConfigFilePathBuilder(path_target_directory=Path(__file__).parent.parent))@pytest.fixturedefyaml_config():ConfigDeployer.setup()CONFIG.load()yieldConfigDeployer.teardown()deftest_something(yaml_config):"""test something"""