pyjsoncfg


Namepyjsoncfg JSON
Version 0.0.6 PyPI version JSON
download
home_pagehttps://github.com/kr-g/pyjsoncfg
Summarypython json config file handling
upload_time2022-06-24 06:25:06
maintainer
docs_urlNone
authork. goger
requires_python>=3.6
licenseMIT
keywords python config json
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![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"
}
        
Elapsed time: 0.05327s