From aa745255b568aa38a911795579b202a2ee0cef5b Mon Sep 17 00:00:00 2001 From: Paul Aswa Date: Mon, 18 Jun 2018 00:59:30 +0300 Subject: [PATCH] Add docs --- Makefile | 20 ++ Pipfile | 21 ++ Pipfile.lock | 389 +++++++++++++++++++++++++++++++++++ docs/api.rst | 17 ++ docs/conf.py | 201 ++++++++++++++++++ docs/guide.rst | 351 +++++++++++++++++++++++++++++++ docs/index.rst | 25 +++ docs/tutorial.rst | 67 ++++++ make.bat | 36 ++++ pyconfigreader/exceptions.py | 1 + pyconfigreader/reader.py | 174 +++++++++------- requirements.txt | 40 +++- 12 files changed, 1258 insertions(+), 84 deletions(-) create mode 100644 Makefile create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 docs/api.rst create mode 100644 docs/conf.py create mode 100644 docs/guide.rst create mode 100644 docs/index.rst create mode 100644 docs/tutorial.rst create mode 100644 make.bat diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a301217 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = pyconfigreader +SOURCEDIR = docs +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..4b9b8db --- /dev/null +++ b/Pipfile @@ -0,0 +1,21 @@ +[[source]] +url = "https://pypi.python.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +testfixtures = "==5.4.0" +"unittest2" = "==1.1.0" +pypandoc = "==1.4" +coverage = "*" +tox = "*" +codacy-coverage = "*" + +[dev-packages] +watchdog = "*" +u-msgpack-python = "*" +sphinx-rtd-theme = "*" +sphinx = "*" + +[requires] +python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..bf85615 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,389 @@ +{ + "_meta": { + "hash": { + "sha256": "f7ae63128c52562eb7522c7544d9571bc0f79fefcd28ec88a851c0f44dc0bcce" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.6" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "argparse": { + "hashes": [ + "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4", + "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314" + ], + "version": "==1.4.0" + }, + "certifi": { + "hashes": [ + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + ], + "version": "==2018.4.16" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "codacy-coverage": { + "hashes": [ + "sha256:b94651934745c638a980ad8d67494077e60f71e19e29aad1c275b66e0a070cbc", + "sha256:d8a1ce56b0dd156d6b1de14fa6217d32ec86097902f08a17ff2f95ba27264474" + ], + "index": "pypi", + "version": "==1.3.11" + }, + "coverage": { + "hashes": [ + "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", + "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", + "sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a", + "sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd", + "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", + "sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2", + "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", + "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", + "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", + "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", + "sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", + "sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", + "sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", + "sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", + "sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", + "sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", + "sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", + "sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", + "sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", + "sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", + "sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", + "sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", + "sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", + "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", + "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", + "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", + "sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4", + "sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91", + "sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d", + "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", + "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", + "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", + "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", + "sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77", + "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80", + "sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e" + ], + "index": "pypi", + "version": "==4.5.1" + }, + "idna": { + "hashes": [ + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" + ], + "version": "==2.7" + }, + "linecache2": { + "hashes": [ + "sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c", + "sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef" + ], + "version": "==1.0.0" + }, + "pluggy": { + "hashes": [ + "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", + "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", + "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + ], + "version": "==0.6.0" + }, + "py": { + "hashes": [ + "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881", + "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a" + ], + "version": "==1.5.3" + }, + "pypandoc": { + "hashes": [ + "sha256:e914e6d5f84a76764887e4d909b09d63308725f0cbb5293872c2c92f07c11a5b" + ], + "index": "pypi", + "version": "==1.4" + }, + "requests": { + "hashes": [ + "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", + "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" + ], + "version": "==2.19.1" + }, + "six": { + "hashes": [ + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + ], + "version": "==1.11.0" + }, + "testfixtures": { + "hashes": [ + "sha256:338aed9695c432b7c9b8a271dabb521e3e7e2c96b11f7b4e60552f1c8408a8f0", + "sha256:53b8e493366a910f5690749dbfccabbb94e0aac0747e95d267b5a37ac2fc4fe9" + ], + "index": "pypi", + "version": "==5.4.0" + }, + "tox": { + "hashes": [ + "sha256:96efa09710a3daeeb845561ebbe1497641d9cef2ee0aea30db6969058b2bda2f", + "sha256:9ee7de958a43806402a38c0d2aa07fa8553f4d2c20a15b140e9f771c2afeade0" + ], + "index": "pypi", + "version": "==3.0.0" + }, + "traceback2": { + "hashes": [ + "sha256:05acc67a09980c2ecfedd3423f7ae0104839eccb55fc645773e1caa0951c3030", + "sha256:8253cebec4b19094d67cc5ed5af99bf1dba1285292226e98a31929f87a5d6b23" + ], + "version": "==1.4.0" + }, + "unittest2": { + "hashes": [ + "sha256:13f77d0875db6d9b435e1d4f41e74ad4cc2eb6e1d5c824996092b3430f088bb8", + "sha256:22882a0e418c284e1f718a822b3b022944d53d2d908e1690b319a9d3eb2c0579" + ], + "index": "pypi", + "version": "==1.1.0" + }, + "urllib3": { + "hashes": [ + "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", + "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" + ], + "version": "==1.23" + }, + "virtualenv": { + "hashes": [ + "sha256:2ce32cd126117ce2c539f0134eb89de91a8413a29baac49cbab3eb50e2026669", + "sha256:ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752" + ], + "version": "==16.0.0" + }, + "wheel": { + "hashes": [ + "sha256:0a2e54558a0628f2145d2fc822137e322412115173e8a2ddbe1c9024338ae83c", + "sha256:80044e51ec5bbf6c894ba0bc48d26a8c20a9ba629f4ca19ea26ecfcf87685f5f" + ], + "version": "==0.31.1" + } + }, + "develop": { + "alabaster": { + "hashes": [ + "sha256:2eef172f44e8d301d25aff8068fddd65f767a3f04b5f15b0f4922f113aa1c732", + "sha256:37cdcb9e9954ed60912ebc1ca12a9d12178c26637abdf124e3cde2341c257fe0" + ], + "version": "==0.7.10" + }, + "argh": { + "hashes": [ + "sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3", + "sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65" + ], + "version": "==0.26.2" + }, + "babel": { + "hashes": [ + "sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669", + "sha256:8cba50f48c529ca3fa18cf81fa9403be176d374ac4d60738b839122dfaaa3d23" + ], + "version": "==2.6.0" + }, + "certifi": { + "hashes": [ + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + ], + "version": "==2018.4.16" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "docutils": { + "hashes": [ + "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + ], + "version": "==0.14" + }, + "idna": { + "hashes": [ + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" + ], + "version": "==2.7" + }, + "imagesize": { + "hashes": [ + "sha256:3620cc0cadba3f7475f9940d22431fc4d407269f1be59ec9b8edcca26440cf18", + "sha256:5b326e4678b6925158ccc66a9fa3122b6106d7c876ee32d7de6ce59385b96315" + ], + "version": "==1.0.0" + }, + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "version": "==2.10" + }, + "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], + "version": "==1.0" + }, + "packaging": { + "hashes": [ + "sha256:e9215d2d2535d3ae866c3d6efc77d5b24a0192cce0ff20e42896cc0664f889c0", + "sha256:f019b770dd64e585a99714f1fd5e01c7a8f11b45635aa953fd41c689a657375b" + ], + "version": "==17.1" + }, + "pathtools": { + "hashes": [ + "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0" + ], + "version": "==0.1.2" + }, + "pygments": { + "hashes": [ + "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", + "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" + ], + "version": "==2.2.0" + }, + "pyparsing": { + "hashes": [ + "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", + "sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07", + "sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18", + "sha256:9e8143a3e15c13713506886badd96ca4b579a87fbdf49e550dbfc057d6cb218e", + "sha256:b8b3117ed9bdf45e14dcc89345ce638ec7e0e29b2b579fa1ecf32ce45ebac8a5", + "sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58", + "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010" + ], + "version": "==2.2.0" + }, + "pytz": { + "hashes": [ + "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555", + "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749" + ], + "version": "==2018.4" + }, + "pyyaml": { + "hashes": [ + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", + "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", + "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", + "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", + "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" + ], + "version": "==3.12" + }, + "requests": { + "hashes": [ + "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", + "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" + ], + "version": "==2.19.1" + }, + "six": { + "hashes": [ + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + ], + "version": "==1.11.0" + }, + "snowballstemmer": { + "hashes": [ + "sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", + "sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89" + ], + "version": "==1.2.1" + }, + "sphinx": { + "hashes": [ + "sha256:85f7e32c8ef07f4ba5aeca728e0f7717bef0789fba8458b8d9c5c294cad134f3", + "sha256:d45480a229edf70d84ca9fae3784162b1bc75ee47e480ffe04a4b7f21a95d76d" + ], + "index": "pypi", + "version": "==1.7.5" + }, + "sphinx-rtd-theme": { + "hashes": [ + "sha256:aa3e190392e963551432de7df24b8a5fbe5b71a2f4fcd9d5b75808b52ad999e5", + "sha256:de88d637a60371d4f923e06b79c4ba260490c57d2ab5a8316942ab5d9a6ce1bf" + ], + "index": "pypi", + "version": "==0.4.0" + }, + "sphinxcontrib-websupport": { + "hashes": [ + "sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", + "sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" + ], + "version": "==1.1.0" + }, + "u-msgpack-python": { + "hashes": [ + "sha256:1715234fb5bea0f1c2da368b956f85bd64ad565fcb092ac5e20386452ff0b147", + "sha256:7ff18ae3721fa75571f9329c08f7c0120416a6ae36194bd8674f65b3b78d0702" + ], + "index": "pypi", + "version": "==2.5.0" + }, + "urllib3": { + "hashes": [ + "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", + "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" + ], + "version": "==1.23" + }, + "watchdog": { + "hashes": [ + "sha256:7e65882adb7746039b6f3876ee174952f8eaaa34491ba34333ddf1fe35de4162" + ], + "index": "pypi", + "version": "==0.8.3" + } + } +} diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 0000000..db36b58 --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,17 @@ +The PyConfigReader API Reference +================================ + +ConfigReader +------------ + +.. automodule:: pyconfigreader.reader + + .. autoclass:: pyconfigreader.reader.ConfigReader + :members: + +Exceptions +---------- + +.. automodule:: pyconfigreader.exceptions + :members: + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..2b25ab8 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# pyconfigreader documentation build configuration file, created by +# sphinx-quickstart on Sun Jun 17 00:15:14 2018. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', + 'sphinx.ext.githubpages', + 'sphinx.ext.doctest', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] +html_theme = 'sphinx_rtd_theme' + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'pyconfigreader' +copyright = '2018, Aswa Paul' +author = 'Aswa Paul' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.3' +# The full version, including alpha/beta/rc tags. +release = '2' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pyconfigreaderdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pyconfigreader.tex', 'pyconfigreader Documentation', + 'Aswa Paul', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pyconfigreader', 'pyconfigreader Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pyconfigreader', 'pyconfigreader Documentation', + author, 'pyconfigreader', 'One line description of project.', + 'Miscellaneous'), +] + + + +# -- Options for Epub output ---------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project +epub_author = author +epub_publisher = author +epub_copyright = copyright + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} diff --git a/docs/guide.rst b/docs/guide.rst new file mode 100644 index 0000000..728253f --- /dev/null +++ b/docs/guide.rst @@ -0,0 +1,351 @@ +Introduction +============ + +**PyConfigReader** not only makes it easier to work with ini files but also +to migrate between JSON and the OS environment. It is possible to transfer variables +from one to the other. + +The following code examples assume the following sample content in the settings.ini:: + + [main] + reader = configreader + name = pyconfigreader + language = python + versions = [2.7, 3.4, 3.5, 3.6] + + [DATA] + language = English + development = None + path = /home/ubuntu/ + user = Ubuntu + groups = 1000 + + +Getting Values +============== + +:class:`~reader.ConfigReader` creates a default **main** section from which key-value pairs are read if no section is specified. + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> name = config.get('name') + >>> versions = config.get('versions') + >>> agency = config.get('agency') # agency is None, it doesn't exist + >>> name + 'pyconfigreader' + >>> versions + [2.7, 3.4, 3.5, 3.6] + >>> agency + >>> config.sections # Get a list of sections + ['main', 'DATA'] + +To get the value of a key in a different section, use the ``section`` parameter + +.. code-block:: python + + >>> config.get('groups', section='DATA') + 1000 + >>> config.get('language', section='DATA') + 'English' + +By default, :class:`~reader.ConfigReader` tries to evaluate the values into Python literals +(int, None, list, etc..). In th example above, `groups` from the `DATA` section has been +evaluated into an integer. To get a string, set the parameter ``evaluate`` to False. + +.. code-block:: python + + >>> config.get('groups', section='DATA', evaluate=False) + '1000' + +If a key does not exist, :class:`~reader.ConfigReader` will return *None* + +.. code-block:: python + + >>> if config.get('last_name') is None: + ... print(True) + ... + True + >>> + +If, instead, you prefer to get a specific value instead of None, use ``default`` + +.. code-block:: python + + >>> config.get('last_name', default='Some Name') + 'Some Name' + +From the Python console, it is possible to get a preview of the contents in the +settings file. :func:`~reader.ConfigReader.show` previews the contents and also +returns an OrderedDict of all the data. + +.. code-block:: python + + >>> config.show() + + + -------------------settings.ini------------------- + main + reader: configreader + name: pyconfigreader + language: python + version: [2.7, 3.4, 3.5, 3.6] + + DATA + language: English + development: None + path: /home/ubuntu/ + user: Ubuntu + groups: 1000 + + + -----------------------end------------------------ + + OrderedDict([('main', OrderedDict([('reader', 'configreader'), ('name', 'pyconfigreader'), ('language', 'python'), ('version', [2.7, 3.4, 3.5, 3.6])])), ('DATA', OrderedDict([('language', 'English'), ('development', None), ('path', '/home/ubuntu/'), ('user', 'Ubuntu'), ('groups', 1000)]))]) + +To hide the preview, set ``output`` to False + +.. code-block:: python + + >>> config.show(output=False) + OrderedDict([('main', OrderedDict([('reader', 'configreader'), ('name', 'pyconfigreader'), ('language', 'python'), ('version', [2.7, 3.4, 3.5, 3.6])])), ('DATA', OrderedDict([('language', 'English'), ('development', None), ('path', '/home/ubuntu/'), ('user', 'Ubuntu'), ('groups', 1000)]))]) + + +Setting Values +============== + +Setting values is done by passing a *key* and *value* to :func:`~reader.ConfigReader.set`. This +saves the value to section **main** unless ``section`` is specified. Unlike Python's ConfigParser order of section then key then value, :mod:`pyconfigreader` uses the key then value then section order. + +.. code-block:: python + + >>> config.set('key', 'value') + >>> config.set('version', '2') # Saved to section `main` + >>> config.set('user', 'root', section='DATA') # Updates user in section DATA + +If a section does not exist, it is created on-the-fly and the key-value pair is written to it. + +.. code-block:: python + + >>> config.set('key', 'value', section='Section') + >>> name = config.get('name') + +As at the moment, the changes are in-memory. To write these changes to the file on the disk close the :class:`~reader.ConfigReader` instance with ``save`` as True or call :func:`~reader.ConfigReader.save` which does not close the :class:`~reader.ConfigReader` instance. + +.. code-block:: python + + >>> config.close(save=True) # Save on close + >>> # Or explicitly call + >>> # config.save() + >>> # then later, call + >>> # config.close() + +In any case you want the changes to be written directly to the file on disk upon setting a value, then set the parameter ``commit`` to True + +.. code-block:: python + + >>> config.set('name', None, section='DATA', commit=True) + +In order for :class:`~reader.ConfigReader` to be used, the settings.ini file does not have to pre-exist. If the file cannot be found then a new file will be created in the specified path + +.. code-block:: python + + >>> config = ConfigReader() + >>> config.set('tests', 'unit') + >>> config.set('runner', 'default') + >>> config.set('count', 1, section='RUNNER') + >>> config.close(save=True) + +Removing Keys +============= + +Keys can be removed permanently by calling :func:`~reader.ConfigReader.remove_key` + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> config.remove_key('reader') # the reader option is always set by default + >>> # or config.remove_option('reader') + >>> config.set('name', 'first', section='Details') + >>> config.remove_key('name', section='Details') + >>> config.close(save=True) + +:func:`~reader.ConfigReader.remove_key` is aliased by :func:`~reader.ConfigReader.remove_option` +taking the same arguments. + +Sections +======== + +You can derive all keys and their values from sections using :func:`~reader.ConfigReader.get_items`. This +returns an OrderedDict. + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> config.set('name', 'first', section='Details') + >>> config.get_items('Details') + OrderedDict([('name', 'first')]) + >>> config.close() # Or config.close(save=True) + + +Section are created on-the-fly when keys and values are set. + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> config.set('name', 'first', section='Details') # Save key `name` with value `first` in section `Details` + >>> config.close() + +Sections can also be explicitly remove by calling :func:`~reader.ConfigReader.remove_section` + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> config.set('name', 'first', section='Details') # Creates section `Details` + >>> config.remove_section('Details') # Removes section `Details` plus all the keys and values + >>> config.close() + + +Environment Variables +===================== + +Get Environment Variables +------------------------- + +**PyConfigReader** makes it possible to load most environment variables into +the settings.ini. To achieve this, use :func:`~reader.ConfigReader.load_env` + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader('settings.ini') + >>> config.load_env() + + +Dump to Environment +------------------- + +With **pyconfigreader**, it is easy to pass values to the environment. + +.. code-block:: python + + >>> import os + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> config.set('name', 'first', section='Details') + >>> config.to_env() + >>> os.environ['DETAILS_NAME'] + 'first' + >>> os.environ['MAIN_READER'] + 'configreader' + +By default, :class:`~reader.ConfigReader` prepends the key with the section name +and then transforms to uppercase before dumping to the environment. For instance, +in the above example, *name* in section *Details* generated the environment key +``DETAILS_NAME``. If you do not prefer this behaviour and want the key to be saved +as is then set ``prepend`` to False. + +.. code-block:: python + + >>> config.to_env(prepend=False) + +Alternatively, you can pass your instance of an environment to which +the key-value pairs will be dumped. + + >>> environment = os.environ.copy() + >>> config.to_env(environment=environment) + + +JSON Files +========== + +Load JSON Files +--------------- + +**PyConfigReader** makes it convenient to load configuration from JSON files. +This can be done by calling :func:`~reader.ConfigReader.load_json` + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> config.load_json('config.json') # Load from file config.json + +As always, a full path to the JSON file is better than just a file name. + +By default, :func:`~reader.ConfigReader.load_json` loads the JSON configuration +to the **main** section. It is possible to set the JSON data to be dumped to a +different section - the parameter ``section`` makes this possible. + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> with ConfigReader(filename='config.ini') as config: + ... config.load_json('config.json', section='JSONDATA') + +If you prefer some values to be loaded to a different +section in the settings.ini then use the ``identifier`` parameter. For example, +with ``identifier`` as **@** and the following JSON configuration:: + + '@counters': { + 'start': { + 'name': 'scrollers', + 'count': 15 + }, + 'end': { + 'name': 'keepers', + 'count': 5 + } + } + +One should expect a section named ``counters`` that looks like:: + + [counters] + start = {'name': 'scrollers', 'count': 15} + end = {'name': 'keepers', 'count': 5} + +:func:`~reader.ConfigReader.load_json` looks for first-level keys which are +prefixed with the ``identifier`` and turns them into section names with their values +being assigned to the same section. + +The JSON file encoding can be set using the ``encoding`` parameter. + + +Dump JSON +---------- + +The settings.ini configuration can be dumped as JSON by calling :func:`~reader.ConfigReader.to_json`. + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> json_dump = config.to_json() + + +To dump the data to a JSON file, pass an open writable file to :func:`~reader.ConfigReader.to_json`. + +.. code-block:: python + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> with open('config.json', 'w') as f: + ... config.to_json(f) + + +Essentially, any file-like object can have the JSON data dumped into it. + +.. code-block:: python + + >>> from io import StringIO + >>> s_io = StringIO() + >>> with ConfigReader('data.ini') as config: + ... config.to_json(s_io) + + + diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..3f7bd0c --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,25 @@ +.. pyconfigreader documentation master file, created by + sphinx-quickstart on Sun Jun 17 00:15:14 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +PyConfigReader Documentation +============================ + +A configuration file handler for the most basic stuff in ini files that +will get you up and running in no time. + +.. toctree:: + :maxdepth: 2 + + tutorial + guide + api + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/tutorial.rst b/docs/tutorial.rst new file mode 100644 index 0000000..3e71919 --- /dev/null +++ b/docs/tutorial.rst @@ -0,0 +1,67 @@ +Getting Started +=============== + +Installation +------------ + +Installation is as simple as running this command in the terminal. + +.. code-block:: bash + + $ pip install pyconfigreader + + +QuickStart +---------- + +To read a configuration file create a file ``settings.ini`` in the current directory +and paste the following content:: + + [main] + reader = configreader + name = pyconfigreader + language = python + versions = [2.7, 3.4, 3.5, 3.6] + + [DATA] + language = English + development = None + path = /home/ubuntu/ + user = Ubuntu + groups = 1000 + + +In a Python console, import :class:`~reader.ConfigReader`:: + + >>> from pyconfigreader import ConfigReader + +Declare the path to your ``settings.ini`` file:: + + >>> settings_ini = '/path/to/settings.ini' + +Read the settings file:: + + >>> config = ConfigReader(settings_ini) + +Get data from the config:: + + >>> config.get('reader') + ... 'configreader' + >>> config.get('groups', section='DATA') + ... 1000 + +Set values:: + + >>> config.set('key', 'value', section='section') + >>> config.set('number', 4, section='NEW') + +Save changes:: + + >>> config.save() + +Close the :class:`~reader.ConfigReader` object:: + + >>> config.close() # Close without saving changes + >>> # or + >>> config.close(save=True) # Save the changes then close + diff --git a/make.bat b/make.bat new file mode 100644 index 0000000..5ad6d83 --- /dev/null +++ b/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=docs +set BUILDDIR=build +set SPHINXPROJ=pyconfigreader + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/pyconfigreader/exceptions.py b/pyconfigreader/exceptions.py index 9b36065..1a78df2 100644 --- a/pyconfigreader/exceptions.py +++ b/pyconfigreader/exceptions.py @@ -18,3 +18,4 @@ class SectionNameNotAllowed(Exception): FileNotFoundError = FileNotFoundError except NameError: FileNotFoundError = OSError + diff --git a/pyconfigreader/reader.py b/pyconfigreader/reader.py index 5bd6390..d801f11 100644 --- a/pyconfigreader/reader.py +++ b/pyconfigreader/reader.py @@ -57,19 +57,33 @@ class ConfigReader(object): basic config file operations including reading, setting and searching for values. - It is preferred that the value of filename be an absolute path. - If filename is not an absolute path, then the configuration (ini) file - will be saved at the Current Working directory (the value of os.getcwd()). - - If file_object is an open file then filename shall point to it's path - - :param filename: The name of the final config file + It is preferred that the value of ``filename`` be an absolute path. + If ``filename`` is not an absolute path, then the configuration (ini) file + will be saved at the Current Working directory (the value of ``os.getcwd()``). + + If ``file_object`` is an open file then ``filename`` shall point to it's path + + :usage: + + >>> from pyconfigreader import ConfigReader + >>> config = ConfigReader(filename='config.ini') + >>> config.set('version', '2') # Saved to section `main` + >>> config.set('Key', 'Value', section='Section') # Creates a section `Section` on-the-fly + >>> config.set('name', 'main') + >>> name = config.get('name') + >>> default_section = config.get_items('main') + >>> config.close(save=True) # Save on close + >>> # Or explicitly call + >>> # config.save() + >>> # config.close() + + :param str filename: The name of the final config file :param file_object: A file-like object opened in mode w+ - :param case_sensitive: Determines whether keys should retain their + :param bool case_sensitive: Determines whether keys should retain their alphabetic cases or be converted to lowercase - :type filename: str - :type file_object: _io.TextIOWrapper or TextIO or io.StringIO - :type case_sensitive: bool + :type file_object: Union[_io.TextIOWrapper, TextIO, io.StringIO] + :ivar str filename: Path to the ini file + :ivar OrderedDict sections: The sections in the ini file """ __defaults = OrderedDict([('reader', 'configreader')]) @@ -117,7 +131,7 @@ def _get_new_object(self): """Copies the contents of the old file into a buffer and deletes the old file. - To write to disk call save + To write to disk call :func:`~reader.ConfigReader.save` """ new_io = IO() new_io.truncate(0) @@ -137,13 +151,13 @@ def _get_new_object(self): def _check_file_object(self, file_object): """Check if file_object is readable and writable - If file_object if an open file, then self.filename is - set to point at the path of file_object. + If file_object if an open file, then :attr:`reader.ConfigReader.filename` + is set to point at the path of file_object. - :param file_object: StringIO or TextIO + :param file_object: Union[StringIO, TextIO] :raises ModeError: If file_object is not readable and writable :return: Returns the file object - :rtype: StringIO or TextIO + :rtype: Union[StringIO, TextIO] """ if file_object is None: return IO() @@ -170,7 +184,8 @@ def _set_filename(value): """Set the file name provided to a full path If the filename provided is not an absolute path - the ini file is stored at the home directory. + the ini file is stored at the current working directory - + the value of ``os.getcwd()``. :param value: The new file name or path :type value: str @@ -268,16 +283,16 @@ def get(self, key, section=None, evaluate=True, """Return the value of the provided key Returns None if the key does not exist. - The section defaults to 'main' if not provided. - If the value of key does not exist and default is not None, - the value of default is returned. And if default_commit is True, then - the value of default is written to file on disk immediately. + The section defaults to **main** if not provided. + If the value of ``key`` does not exist and ``default`` is not None, + the value of ``default`` is returned. And if ``default_commit`` is True, then + the value of ``default`` is written to file on disk immediately. - If evaluate is True, the returned values are evaluated to + If ``evaluate`` is True, the returned values are evaluated to Python data types int, float and boolean. :param key: The key name - :param section: The name of the section, defaults to 'main' + :param section: The name of the section, defaults to **main** :param evaluate: Determines whether to evaluate the acquired values into Python literals :param default: The value to return if the key is not found :param default_commit: Also write the value of default to ini file on disk @@ -287,7 +302,7 @@ def get(self, key, section=None, evaluate=True, :type default: str :type default_commit: bool :returns: The value that is mapped to the key or None if not found - :rtype: str, int, float, bool or None + :rtype: Union[str, int, float, bool, None] """ section = section or self.__default_section value = 'None' @@ -306,21 +321,20 @@ def get(self, key, section=None, evaluate=True, def set(self, key, value, section=None, commit=False): """Sets the value of key to the provided value - Section defaults to 'main' is not provided. + Section defaults to **main** if not provided. The section is created if it does not exist. - When :param commit: is True, all changes up to the current + When ``commit`` is True, all changes up to the current one are written to disk. :param key: The key name :param value: The value to which the key is mapped - :param section: The name of the section, defaults to 'main' + :param section: The name of the section, defaults to **main** :param commit: Also write changes to ini file on disk :type key: str :type value: str :type section: str :type commit: bool - :returns: Nothing :rtype: None """ section = section or self.__default_section @@ -340,12 +354,12 @@ def get_items(self, section): The values are evaluated into Python literals, if possible. - Returns None if section not found. + Returns None if section is not found. :param section: The section from which items (key-value pairs) are to be read from :type section: str :return: An dictionary of keys and their values - :rtype: OrderedDict or None + :rtype: Union[OrderedDict, None] """ if section not in self.sections: @@ -380,7 +394,7 @@ def remove_option(self, key, section=None, commit=False): """Remove an option from the configuration file :param key: The key name - :param section: The section name, defaults to 'main' + :param section: The section name, defaults to **main** :param commit: Also write changes to ini file on disk :type key: str :type section: str @@ -401,7 +415,7 @@ def remove_option(self, key, section=None, commit=False): self.save() def remove_key(self, *args, **kwargs): - """Same as calling self.remove_option + """Same as calling :func:`~reader.ConfigReader.remove_option` This is just in case one is used to the key-value term pair """ @@ -442,13 +456,12 @@ def search(self, value, case_sensitive=True, """Returns a tuple containing the key, value and section of the best match found, else empty tuple - If exact_match is False, checks if there exists a value - that matches above the threshold value. In this case, - case_sensitive is ignored. + If ``exact_match`` is False, checks if there exists a value that matches + above the threshold value. In this case, ``case_sensitive`` is ignored. - If exact_match is True then the value of case_sensitive matters. + If ``exact_match`` is True then the value of ``case_sensitive`` matters. - The threshold value should be 0, 1 or any value + The ``threshold`` value should be 0, 1 or any value between 0 and 1. The higher the value the better the accuracy. :param value: The value to search for in the config file @@ -495,20 +508,20 @@ def search(self, value, case_sensitive=True, def to_json(self, file_object=None): """Export config to JSON - If a file_object is given, it is exported to it + If a ``file_object`` is given, it is exported to it else returned as called - Example - ------- + :usage: + + >>> # Example >>> reader = ConfigReader() >>> with open('config.json', 'w') as f: - >>> reader.to_json(f) - - or: - + ... reader.to_json(f) + >>> # or >>> from io import StringIO >>> s_io = StringIO() >>> reader.to_json(s_io) + >>> reader.close() :param file_object: A file-like object for the JSON content :type file_object: io.TextIO @@ -529,26 +542,24 @@ def load_json(self, filename='settings.json', section=None, identifier='@', encoding=None): """Load config from JSON file - For instance:- - - With :param identifier: as '@', - - '@counters': { - 'start': { - 'name': 'scrollers', - 'count': 15 - }, - 'end': { - 'name': 'keepers', - 'count': 5 + For instance:: + + # With ``identifier`` as '@', + '@counters': { + 'start': { + 'name': 'scrollers', + 'count': 15 + }, + 'end': { + 'name': 'keepers', + 'count': 5 + } } - } - will result in a section - - [counters] - start = {'name': 'scrollers', 'count': 15} - end = {'name': 'keepers', 'count': 5} + # will result in a section + [counters] + start = {'name': 'scrollers', 'count': 15} + end = {'name': 'keepers', 'count': 5} :param filename: name of the JSON file :param section: config section name to save key and values by default @@ -595,24 +606,25 @@ def load_json(self, filename='settings.json', section=None, def to_env(self, environment=None, prepend=True): """Export contents to an environment - Exports by default to os.environ. + Exports by default to ``os.environ()``. By default, the section and option would be capitalised and joined by an underscore to form the key - as an attempt at avoid collision with (any) environment variables. - Example - ------- + :usage: + >>> reader = ConfigReader() >>> reader.show(output=False) - {'main': {'reader': 'configreader'}} + OrderedDict([('main', OrderedDict([('reader', 'configreader')]))]) >>> reader.to_env() >>> import os >>> os.environ['MAIN_READER'] - 'configreader' + 'configreader' >>> reader.to_env(prepend=False) >>> os.environ['READER'] - 'configreader' + 'configreader' + >>> reader.close() :param environment: An environment to export to :param prepend: Prepend the section name to the key @@ -641,8 +653,8 @@ def save(self): Write the contents to a file on the disk. - If an open file was passed during instantiation, the - contents will be written without closing the file. + This does not close the file. You have to explicitly call + :func:`~reader.ConfigReader.close` to do so. :returns: Nothing :rtype: None @@ -656,7 +668,12 @@ def save(self): os.fsync(self.__file_object.fileno()) def to_file(self): - """Same as :method save:""" + """Same as :func:`~reader.ConfigReader.save` + + .. WARNING:: + This method has been renamed to :func:`~reader.ConfigReader.save`. + This alias will be removed in future versions. + """ warnings.warn("The method 'to_file' has been renamed to 'save'. " "This alias will be removed in future versions.", DeprecationWarning) @@ -665,10 +682,11 @@ def to_file(self): def close(self, save=False): """Close the file-like object - Saves contents to file on disk first. + If ``save`` is True, the contents are written to the file on disk first . - caution:: Not closing the object might have it update any other - instance created later on. + .. CAUTION:: + Not closing the object might have it update any other + instance created later on. :param save: write changes to disk :type save: bool @@ -681,15 +699,13 @@ def close(self, save=False): def load_env(self, environment=None, prefix='', commit=False): """Load alphanumeric environment variables into configuration file - Default environment is provided by os.environ. + Default environment is provided by ``os.environ()``. - The :param prefix: is used to filter keys in the environment which - start with the value. This is an adaptive mode to the :method to_env: + The ``prefix`` is used to filter keys in the environment which + start with the value. This is an adaptive mode to :func:`~reader.ConfigReader.to_env` which prepends the section to the key before loading it to the environment. - warning:: skips variables with keys or values which contain % (percentage sign) - :param environment: the environment to load from :param prefix: only keys which are prefixed with this string are loaded :param commit: write to disk immediately diff --git a/requirements.txt b/requirements.txt index 192af0b..55de823 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,37 @@ +alabaster==0.7.10 +argh==0.26.2 +Babel==2.6.0 +certifi==2018.4.16 +chardet==3.0.4 +codacy-coverage==1.3.11 +coverage==4.5.1 +docutils==0.14 +idna==2.7 +imagesize==1.0.0 +Jinja2==2.10 +linecache2==1.0.0 +MarkupSafe==1.0 +packaging==17.1 +pathtools==0.1.2 +pluggy==0.6.0 +py==1.5.3 +Pygments==2.2.0 +pypandoc==1.4 +pyparsing==2.2.0 +pytz==2018.4 +PyYAML==3.12 +requests==2.19.1 +six==1.11.0 +snowballstemmer==1.2.1 +Sphinx==1.7.5 +sphinx-rtd-theme==0.4.0 +sphinxcontrib-websupport==1.1.0 testfixtures==5.4.0 +toml==0.9.4 +tox==3.0.0 +traceback2==1.4.0 +u-msgpack-python==2.5.0 unittest2==1.1.0 -setuptools==18.3.2 -pypandoc==1.4 -coverage -tox -codacy-coverage +urllib3==1.23 +virtualenv==16.0.0 +watchdog==0.8.3