Package: cock
CockCock stands for «configuration file with click». It is a configuration aggregator, which stands on shinyclicklibrary.ReasonNo module for click with flat configuration file, which will mimic actual click options. There areclick-configandclick-config-file, but they targets another goals.FeaturesAggregate configuration file and cli options into flat configuration object.Respect all click checks and conversions (requiredattribute forbidden, since it breaks internal logic).dict-like, flat, sorted, dot-accessed configuration object.Entrypoint builder.Licensecockis offered under MIT license.Requirementspython 3.7+Usagefromcockimportbuild_entrypoint,Config,Optiondefmain(config:Config):print(config)options=[Option("a_b_c",default="foo"),Option("b_c_d",default="bar"),]entrypoint=build_entrypoint(main,options,auto_envvar_prefix="EXAMPLE",show_default=True)if__name__=="__main__":entrypoint(prog_name="example")This is almost pure click setup:$ python example.py --help
Usage: example [OPTIONS] [CONFIGURATION_FILE]

Options:
  --a-b-c TEXT  [default: foo]
  --b-c-d TEXT  [default: bar]
  --help        Show this message and exit.  [default: False]But there is aCONFIGURATION_FILEargument. Lets see use cases.All deafults$ python example.py
{'configuration_file': None, 'a_b_c': 'foo', 'b_c_d': 'bar'}From environment variable$ EXAMPLE_A_B_C=foo-env python example.py
{'configuration_file': None, 'a_b_c': 'foo-env', 'b_c_d': 'bar'}From cli arguments$ EXAMPLE_A_B_C=foo-env python example.py --a-b-c foo-cli
{'a_b_c': 'foo-cli', 'configuration_file': None, 'b_c_d': 'bar'}From configuration yaml filea-b-c:foo-file$ EXAMPLE_A_B_C=foo-env python example.py --a-b-c foo-cli config-example.yml
{'a_b_c': 'foo-file', 'configuration_file': '/absolute/path/to/config-example.yml', 'b_c_d': 'bar'}Priority is obvious:file > cli arguments > env variablesNote: for filea-b-cis the same asa_b_cora-b_c. Use whatever you prefer.As described in features paragraph, configuration is flattened before chaining with click options. So all configuration files listed below are equal:a_b_c:foo-filea:b:c:foo-filea-b:c:foo-fileIf provided file have key crossings:a-b_c:foo-file1a:b-c:foo-file2ThenRuntimeErrorwill be raised.cockusespyyamllibrary for config loading, so it supportsyamlandjsonformats, but this can be improved later if someone will need more configuration file types.Configuration can be defined as dictionary too:fromcockimportbuild_entrypoint,Option,Configdefmain(config:Config):print(config)options={"a":{"b":{"c":Option(default="foo"),},},"a-b_d":Option(default="bar"),}entrypoint=build_entrypoint(main,options,auto_envvar_prefix="EXAMPLE",show_default=True)if__name__=="__main__":entrypoint(prog_name="example")Note: for dictionaries you can use same rules in naming and structure as for files.Configuration can be defined as multiple sources:fromcockimportbuild_entrypoint,Option,Configdefmain(config:Config):print(config)dict_options={"a-b-c":Option(default="foo")}list_options=[Option("b_c-d",default="bar")]entrypoint=build_entrypoint(main,dict_options,list_options,auto_envvar_prefix="EXAMPLE",show_default=True)if__name__=="__main__":entrypoint(prog_name="example")You can also gather all defaults from options as aConfig:fromcockimportget_options_defaults,Optionoptions={"a":{"b":{"c":Option(default="foo"),},},}config=get_options_defaults(options)assertconfig=={"a_b_c":"foo"}assertconfig.a_b_c=="foo"Configis an extended (with dot-access) version ofsortedcontainers.SortedDict:>>>fromcockimportConfig>>>c=Config(b=1,a=2)Config({'a':2,'b':1})>>>c["a"],c.b(2,1)>>>c.z...KeyError:'z'>>>c.items()SortedItemsView(Config({'a':2,'b':1}))>>>c["0"]=0>>>cConfig({'0':0,'a':2,'b':1})APIdefbuild_entrypoint(main:Callable[[Config],Any],*options_stack:Union[dict,List[Union[Option,click.option]]],**context_settings)->Callable[...,Any]:mainis a user-space function of exactly one argument, a dot-accessed config wrapper.*options_stackis a sequence of dicts and/or lists described above.**context_settingspropagated toclick.commanddecorator.defget_options_defaults(*options_stack:Union[dict,List[Union[Option,click.option]]])->Config:*options_stackis a sequence of dicts and/or lists described above.classOption(name:Optional[str]=None,**attributes)nameis a name in resultingConfigobject, which passed tomain.namecan be set only once, further set will lead to exception.namefield will be converted to «underscore» view (e.g.a-b_cinternaly will be converted toa_b_c).**attributespropagated toclick.optiondecorator.requiredattribute forbidden, since it breaks internal logic.Deprecations and removals0.11.0Deprecations:Usage ofclick.optionas option.build_options_from_dictfunction, since it is obsolete with new api.