[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
# PyJsonConfig - pyjsoncfg
Configure your Python Application with a JSON config file.
Create a sanitized sample JSON for git and demo purposes using your real config as template.
## Platform
Tested on Python3
## Development status
Beta state. The API or logical call flow might change without prior notice.
# What's new ?
Check
[`CHANGELOG`](https://github.com/kr-g/pyjsoncfg/blob/master/CHANGELOG.md)
for latest ongoing, or upcoming news
## Configuration
The environment variable `PYJSONCONFIG_BASE` (default: `"."`) is used to find the configuration file.
## Run as main
Run `pyjsoncfg` from cmd-line to create a sanitized config file using your real configuration as template.
pyjsoncfg checks for keywords like `"user", "pass", "url", "host", "remote", "port"`.
The corresponding values are replaced by dummy values.
Keywords containing `"default"` as part of their keyword are __not__ replaced by a dummy value.
Use parameter `-k you_secret_key1` `-k you_secret_key2`... to add additional keywords to scan and replace for.
python3 -m pyjsoncfg -f sample_cfg.json -k secret
use redirect to create template file rather then output to stdout
python3 -m pyjsoncfg -f sample_cfg.json -k secret > sanitized_sample_cfg.json
A sanitized sample can be found here [sanitized_sample_cfg.json](https://github.com/kr-g/pyjsoncfg/blob/master/pyjsoncfg/sanitized_sample_cfg.json)
By running `pyjsoncfg` the environment variable `PYJSONCONFIG_BASE` defaults to `"~"`
## cmd-line options
run `python3 -m pyjsoncfg -h` to see all options.
usage: pyjsoncfg [options]
sanitize json config file, details refer to https://github.com/kr-g/pyjsoncfg
optional arguments:
-h, --help show this help message and exit
-v, --version show version info and exit
-d, --debug show debug info
-f CONFIG input json config file (default: cfg.json)
-l, --list list config, do not sanitize (default: False)
-k KEYWORD, -key KEYWORD, -keyword KEYWORD
additional keyword to scan for (default: [])
## Use within own code
In order to use a global configuration root set the environment before, or do by CODE (see full sample at the end)
PYJSONCONFIG_BASE="~" python3 -m your_application
## Config key navigation and selection
See also [`sample_cfg.json`](https://github.com/kr-g/pyjsoncfg/blob/master/pyjsoncfg/sample_cfg.json) in the github repo for the json config structure
### dict style
# property dc is in the config file
v = cfg()["dummy_complex"]["d"]["dc"]
print(v,type(v))
### string selector
# property de is new here!
v = cfg.val( ["dummy_complex","d","de"], defval=False ) # with default value
print(v,type(v))
### property string selector
# property de is not new here, no chamge since created above
v = cfg.val( cfg("dummy_complex.d.de"), defval=True ) # with default value,
print(v,type(v))
### namespace selector
After loading with `auto_conv=True` or calling `cfg.conv()` namespace selector is available
v = cfg().dummy_complex.d.de
print(v,type(v))
### setting defaults
# also complex types are handled and resolved to namespace
cfg.data.setdefault("a",1)
cfg.data.setdefault("b",[2])
cfg.data.setdefault("c",[{"e":3}])
cfg.data.setdefault("d", [{"e": 3, "f": 4, "g": {"h": 7}}])
cfg.data.setdefault(
"e", [{"e": 3, "f": 4, "g": {"h": 7, "i": [1, 2, 3, 4], "j": {"z": "zoo"}}}]
)
# cfg().c[0].e returns 3
# cfg().d[0].g.h returns 7
# cfg().e[0].g.j.z returns 'zoo'
### dict handling
cfg()["z"] = { "a": 1 }
cfg()["zx"] = { "a" : 1, "b" : { "c" : 2 }}
cfg().zx.b.update({ "c": 3, "d": 4, "e" : 5 })
del cfg().zx.b.c
print( cfg().zx.b.items() )
print( type( cfg().zx.b ) )
print( type( cfg().zx.b.items() ) )
# iterate
for k,v in cfg().zx.b.items():
print(k,v)
print( type( cfg().zx.b.e ) )
### expand vars
with `expandvars()` all vars such as `${user}` or `${host.remote_ip}` inside an eval_string can be replaced by config values.
the default recursion level is `recursion_level=3`. change if the config file has a deeper nesting of vars.
See also [`sample_cfg.json`](https://github.com/kr-g/pyjsoncfg/blob/master/pyjsoncfg/sample_cfg.json) for the structure.
# print structure of substsample config setting
print( "subst var sample:", cfg().substsample )
# subst all vars in substsample setting within a single call
print( "result:", cfg.expand( cfg().substsample ) )
# or more complicated...
# get all vars in the string as tupel
vars = cfg.getexpandvars( cfg().substsample ) # `eval_str` is populated with config value for substsample setting
print( "vars:", vars )
# get all vars and values as tupel
exvars = cfg.expandvars( vars )
print( "expandvars", exvars )
# if required manipulate expandvars beforehand
print( "result:", cfg.expand( cfg().substsample, expandvars=exvars ) )
# nested or referencing vars
print( "referencing:", cfg().substsample2 )
print( "result referencing:", cfg.expand( cfg().substsample2 ) )
# nested or referencing vars with endless loop due to self-referencing
# stops at `recursion_level=3`
print( "self-referencing:", cfg().substsample3 )
print( "result self-referencing:", cfg.expand( cfg().substsample3 ) )
#### limitation of `expandvars()`
substitution of `dict` or complex json object is not supported.
extra whitespace within a variable specifier is not supported.
ok:
${user}
${host.remote_ip}
not ok:
${user } # tailing blank
${ user } # leading and tailing blank
${host . remote_ip} # extra white space
## Code
import os, sys
from pyjsoncfg import Config
cfg = Config(
fnam="sample_cfg.py", # file name of json config, defaults to cfg.json
basepath=".", # base path, defaults to environment variable `PYJSONCONFIG_BASE` if not set
not_exist_ok=True, # do not raise an error if config file is not exsting
auto_conv=True # after loading convert json to namespace, if false dict is used for storing
)
# see sample_cfg.py in github project
val_a = cfg().dummy_complex.a
cfg().dummy_complex.a += 1
val_a_after = cfg().dummy_complex.a
print( "a before", val_a, "after", val_a_after )
val_array = []
val_array.extend( cfg().dummy_array )
cfg().dummy_array.append(17)
val_array_after = cfg().dummy_array
print( "array before", val_array, "after", val_array_after )
# access functions
#
# val, returns the value as in the json
# bool, converts to bool
# int, converts to int
# float, converts to float
# str, converts to str
print( bool(cfg()["dummy_complex"]["d"]["dc"] )) # get the value as given in json
print( cfg.bool(["dummy_complex","d","dc"] )) # get interpreted as bool
print( cfg.bool( cfg("dummy_complex.d.dc") )) # get interpreted as bool
print( cfg.val( cfg("dummy_complex.d.dc") )) # get plain using selector
print( cfg().dummy_complex.d.dc ) # get plain using namespace
# save to disk
cfg.save()
# print to stdout
cfg.savefd(sys.stdout)
Raw data
{
"_id": null,
"home_page": "https://github.com/kr-g/pyjsoncfg",
"name": "pyjsoncfg",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": "",
"keywords": "python config json",
"author": "k. goger",
"author_email": "k.r.goger+pyjsoncfg@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/3c/57/e080549e0207feb89dfe9d288ee9be12984c491e5aedee0113a4a169cf1d/pyjsoncfg-0.0.6.tar.gz",
"platform": null,
"description": "[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\n\n# PyJsonConfig - pyjsoncfg\n\nConfigure your Python Application with a JSON config file.\nCreate a sanitized sample JSON for git and demo purposes using your real config as template.\n\n\n## Platform\n\nTested on Python3\n\n\n## Development status\n\nBeta state. The API or logical call flow might change without prior notice.\n\n# What's new ?\n\nCheck\n[`CHANGELOG`](https://github.com/kr-g/pyjsoncfg/blob/master/CHANGELOG.md)\nfor latest ongoing, or upcoming news\n\n\n## Configuration\n\nThe environment variable `PYJSONCONFIG_BASE` (default: `\".\"`) is used to find the configuration file.\n\n\n## Run as main\n\nRun `pyjsoncfg` from cmd-line to create a sanitized config file using your real configuration as template.\n\npyjsoncfg checks for keywords like `\"user\", \"pass\", \"url\", \"host\", \"remote\", \"port\"`.\nThe corresponding values are replaced by dummy values. \nKeywords containing `\"default\"` as part of their keyword are __not__ replaced by a dummy value.\nUse parameter `-k you_secret_key1` `-k you_secret_key2`... to add additional keywords to scan and replace for.\n\n python3 -m pyjsoncfg -f sample_cfg.json -k secret \n\nuse redirect to create template file rather then output to stdout\n\n python3 -m pyjsoncfg -f sample_cfg.json -k secret > sanitized_sample_cfg.json\n\nA sanitized sample can be found here [sanitized_sample_cfg.json](https://github.com/kr-g/pyjsoncfg/blob/master/pyjsoncfg/sanitized_sample_cfg.json)\n\nBy running `pyjsoncfg` the environment variable `PYJSONCONFIG_BASE` defaults to `\"~\"`\n\n\n## cmd-line options\n\nrun `python3 -m pyjsoncfg -h` to see all options.\n\n\n usage: pyjsoncfg [options]\n\n sanitize json config file, details refer to https://github.com/kr-g/pyjsoncfg\n\n optional arguments:\n -h, --help show this help message and exit\n -v, --version show version info and exit\n -d, --debug show debug info\n -f CONFIG input json config file (default: cfg.json)\n -l, --list list config, do not sanitize (default: False)\n -k KEYWORD, -key KEYWORD, -keyword KEYWORD\n additional keyword to scan for (default: [])\n\n\n## Use within own code\n\nIn order to use a global configuration root set the environment before, or do by CODE (see full sample at the end)\n\n PYJSONCONFIG_BASE=\"~\" python3 -m your_application \n\n\n## Config key navigation and selection\n\nSee also [`sample_cfg.json`](https://github.com/kr-g/pyjsoncfg/blob/master/pyjsoncfg/sample_cfg.json) in the github repo for the json config structure\n\n\n### dict style\n\n # property dc is in the config file\n v = cfg()[\"dummy_complex\"][\"d\"][\"dc\"]\n print(v,type(v))\n\n### string selector\n\n # property de is new here!\n v = cfg.val( [\"dummy_complex\",\"d\",\"de\"], defval=False ) # with default value\n print(v,type(v))\n\n### property string selector\n\n # property de is not new here, no chamge since created above\n v = cfg.val( cfg(\"dummy_complex.d.de\"), defval=True ) # with default value, \n print(v,type(v))\n\n### namespace selector\n\nAfter loading with `auto_conv=True` or calling `cfg.conv()` namespace selector is available\n\n v = cfg().dummy_complex.d.de\n print(v,type(v))\n\n### setting defaults\n\n # also complex types are handled and resolved to namespace\n cfg.data.setdefault(\"a\",1)\n cfg.data.setdefault(\"b\",[2])\n cfg.data.setdefault(\"c\",[{\"e\":3}])\n cfg.data.setdefault(\"d\", [{\"e\": 3, \"f\": 4, \"g\": {\"h\": 7}}])\n cfg.data.setdefault(\n \"e\", [{\"e\": 3, \"f\": 4, \"g\": {\"h\": 7, \"i\": [1, 2, 3, 4], \"j\": {\"z\": \"zoo\"}}}]\n )\n\n # cfg().c[0].e returns 3\n # cfg().d[0].g.h returns 7\n # cfg().e[0].g.j.z returns 'zoo'\n\n\n### dict handling\n\n cfg()[\"z\"] = { \"a\": 1 } \n cfg()[\"zx\"] = { \"a\" : 1, \"b\" : { \"c\" : 2 }}\n \n cfg().zx.b.update({ \"c\": 3, \"d\": 4, \"e\" : 5 })\n\n del cfg().zx.b.c\n \n print( cfg().zx.b.items() ) \n print( type( cfg().zx.b ) )\n print( type( cfg().zx.b.items() ) )\n \n # iterate\n for k,v in cfg().zx.b.items():\n print(k,v)\n\n print( type( cfg().zx.b.e ) )\n \n### expand vars\n\nwith `expandvars()` all vars such as `${user}` or `${host.remote_ip}` inside an eval_string can be replaced by config values.\nthe default recursion level is `recursion_level=3`. change if the config file has a deeper nesting of vars.\nSee also [`sample_cfg.json`](https://github.com/kr-g/pyjsoncfg/blob/master/pyjsoncfg/sample_cfg.json) for the structure.\n\n # print structure of substsample config setting\n print( \"subst var sample:\", cfg().substsample )\n # subst all vars in substsample setting within a single call\n print( \"result:\", cfg.expand( cfg().substsample ) )\n \n # or more complicated...\n # get all vars in the string as tupel\n vars = cfg.getexpandvars( cfg().substsample ) # `eval_str` is populated with config value for substsample setting\n print( \"vars:\", vars )\n # get all vars and values as tupel\n exvars = cfg.expandvars( vars ) \n print( \"expandvars\", exvars )\n # if required manipulate expandvars beforehand\n print( \"result:\", cfg.expand( cfg().substsample, expandvars=exvars ) )\n\n # nested or referencing vars\n print( \"referencing:\", cfg().substsample2 ) \n print( \"result referencing:\", cfg.expand( cfg().substsample2 ) )\n\n # nested or referencing vars with endless loop due to self-referencing\n # stops at `recursion_level=3`\n print( \"self-referencing:\", cfg().substsample3 ) \n print( \"result self-referencing:\", cfg.expand( cfg().substsample3 ) )\n \n#### limitation of `expandvars()`\n \nsubstitution of `dict` or complex json object is not supported.\nextra whitespace within a variable specifier is not supported.\n\nok:\n\n ${user}\n ${host.remote_ip}\n \nnot ok:\n\n ${user } # tailing blank\n ${ user } # leading and tailing blank\n ${host . remote_ip} # extra white space\n\n\n## Code\n\n import os, sys\n from pyjsoncfg import Config\n\n cfg = Config(\n fnam=\"sample_cfg.py\", # file name of json config, defaults to cfg.json\n basepath=\".\", # base path, defaults to environment variable `PYJSONCONFIG_BASE` if not set\n not_exist_ok=True, # do not raise an error if config file is not exsting \n auto_conv=True # after loading convert json to namespace, if false dict is used for storing\n )\n\n # see sample_cfg.py in github project\n\n val_a = cfg().dummy_complex.a \n cfg().dummy_complex.a += 1\n val_a_after = cfg().dummy_complex.a \n print( \"a before\", val_a, \"after\", val_a_after )\n\n val_array = []\n val_array.extend( cfg().dummy_array )\n cfg().dummy_array.append(17)\n val_array_after = cfg().dummy_array\n print( \"array before\", val_array, \"after\", val_array_after )\n\n # access functions\n #\n # val, returns the value as in the json\n # bool, converts to bool\n # int, converts to int\n # float, converts to float\n # str, converts to str\n\n print( bool(cfg()[\"dummy_complex\"][\"d\"][\"dc\"] )) # get the value as given in json\n print( cfg.bool([\"dummy_complex\",\"d\",\"dc\"] )) # get interpreted as bool\n print( cfg.bool( cfg(\"dummy_complex.d.dc\") )) # get interpreted as bool\n\n print( cfg.val( cfg(\"dummy_complex.d.dc\") )) # get plain using selector\n print( cfg().dummy_complex.d.dc ) # get plain using namespace\n\n # save to disk\n cfg.save()\n\n # print to stdout\n cfg.savefd(sys.stdout)\n\n\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "python json config file handling",
"version": "0.0.6",
"split_keywords": [
"python",
"config",
"json"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2341c494d02afd3b87bfb7c00ca28a641396898c00c04ba47f3e66a1c8640ee7",
"md5": "9c439a44dea7a87da11e50fb005fb814",
"sha256": "91b0d5f1e914e0f316359b08f48ea314a28bfb7e0c4d8e825811b51012b1330c"
},
"downloads": -1,
"filename": "pyjsoncfg-0.0.6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9c439a44dea7a87da11e50fb005fb814",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 21247,
"upload_time": "2022-06-24T06:25:03",
"upload_time_iso_8601": "2022-06-24T06:25:03.466755Z",
"url": "https://files.pythonhosted.org/packages/23/41/c494d02afd3b87bfb7c00ca28a641396898c00c04ba47f3e66a1c8640ee7/pyjsoncfg-0.0.6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3c57e080549e0207feb89dfe9d288ee9be12984c491e5aedee0113a4a169cf1d",
"md5": "24bd48efb7bf93f865f74cd1c71f3382",
"sha256": "cffaaab779edfcd2f3e1e45c9277c620532904e2d6d84c05b01821462d2bdd5b"
},
"downloads": -1,
"filename": "pyjsoncfg-0.0.6.tar.gz",
"has_sig": false,
"md5_digest": "24bd48efb7bf93f865f74cd1c71f3382",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 22291,
"upload_time": "2022-06-24T06:25:06",
"upload_time_iso_8601": "2022-06-24T06:25:06.009690Z",
"url": "https://files.pythonhosted.org/packages/3c/57/e080549e0207feb89dfe9d288ee9be12984c491e5aedee0113a4a169cf1d/pyjsoncfg-0.0.6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-06-24 06:25:06",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "kr-g",
"github_project": "pyjsoncfg",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "pyjsoncfg"
}