Skip to content

Commit fa2db65

Browse files
committed
add notebook with cli usage; update index
1 parent ab44606 commit fa2db65

5 files changed

Lines changed: 400 additions & 27 deletions

File tree

nbs/01_cli.ipynb

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "fa9d3839",
6+
"metadata": {},
7+
"source": [
8+
"# cli\n",
9+
"\n",
10+
"> command line interface providing friendly tools"
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": 1,
16+
"id": "292835bc",
17+
"metadata": {
18+
"ExecuteTime": {
19+
"end_time": "2023-06-17T05:24:59.152067Z",
20+
"start_time": "2023-06-17T05:24:59.148711Z"
21+
}
22+
},
23+
"outputs": [],
24+
"source": [
25+
"#| default_exp cli"
26+
]
27+
},
28+
{
29+
"cell_type": "code",
30+
"execution_count": 2,
31+
"id": "edb02c6d",
32+
"metadata": {
33+
"ExecuteTime": {
34+
"end_time": "2023-06-17T05:25:00.300364Z",
35+
"start_time": "2023-06-17T05:25:00.144682Z"
36+
}
37+
},
38+
"outputs": [],
39+
"source": [
40+
"#| export\n",
41+
"from python_schematized_config.core import ConfigValidator, load_json, extract_declared_items\n",
42+
"\n",
43+
"import os\n",
44+
"import sys\n",
45+
"import argparse\n",
46+
"import dotenv\n",
47+
"from typing import Union\n",
48+
"from fastcore.script import *"
49+
]
50+
},
51+
{
52+
"cell_type": "code",
53+
"execution_count": 3,
54+
"id": "c76d8ad0",
55+
"metadata": {
56+
"ExecuteTime": {
57+
"end_time": "2023-06-17T05:25:01.089147Z",
58+
"start_time": "2023-06-17T05:25:01.083831Z"
59+
}
60+
},
61+
"outputs": [],
62+
"source": [
63+
"def validate_env(json_schema: Union[str, dict], dotenv_path: str=None):\n",
64+
" validator = ConfigValidator(json_schema)\n",
65+
" try:\n",
66+
" validator.load_config(dotenv.dotenv_values(dotenv_path))\n",
67+
" return True\n",
68+
" except ConfigValidatorException as ex:\n",
69+
" sys.stderr.write(f'{str(ex)}\\n')\n",
70+
" for error in ex.errors:\n",
71+
" sys.stderr.write(f'{error.json_path}:\\t{error.message}\\n')\n",
72+
" return False"
73+
]
74+
},
75+
{
76+
"cell_type": "code",
77+
"execution_count": 4,
78+
"id": "85f3438b",
79+
"metadata": {
80+
"ExecuteTime": {
81+
"end_time": "2023-06-17T05:25:01.895278Z",
82+
"start_time": "2023-06-17T05:25:01.887838Z"
83+
}
84+
},
85+
"outputs": [],
86+
"source": [
87+
"def generate_sample_dotenv(json_schema: Union[str, dict], seed_config: dict=None):\n",
88+
" schema_dict = load_json(json_schema)\n",
89+
" merged_config = dict(os.environ)\n",
90+
" default_dotenv = dotenv.dotenv_values()\n",
91+
" merged_config.update(default_dotenv)\n",
92+
" merged_config.update(seed_config or {})\n",
93+
" extracted_config = extract_declared_items(schema_dict, merged_config)\n",
94+
" out = [\n",
95+
" f'{key}={value}'\n",
96+
" for key, value in extracted_config.items()\n",
97+
" ]\n",
98+
" # for all keys that are in the schema, but NOT in the current config,\n",
99+
" # add them as comments\n",
100+
" for (key, value_schema) in schema_dict['properties'].items():\n",
101+
" if key not in extracted_config:\n",
102+
" out.append(f'# {key}=<{value_schema.get(\"type\")}>')\n",
103+
" return '\\n'.join(out)"
104+
]
105+
},
106+
{
107+
"cell_type": "code",
108+
"execution_count": 5,
109+
"id": "227d3160",
110+
"metadata": {
111+
"ExecuteTime": {
112+
"end_time": "2023-06-17T05:25:02.648856Z",
113+
"start_time": "2023-06-17T05:25:02.642876Z"
114+
}
115+
},
116+
"outputs": [
117+
{
118+
"name": "stdout",
119+
"output_type": "stream",
120+
"text": [
121+
"HAS_DEFAULT=NO COERCION!\n",
122+
"# STRING=<string>\n",
123+
"# SOMETHING_ELSE=<None>\n"
124+
]
125+
}
126+
],
127+
"source": [
128+
"#| hide\n",
129+
"sample_dotenv = generate_sample_dotenv(\n",
130+
" {\n",
131+
" 'type': 'object',\n",
132+
" 'properties': {\n",
133+
" 'STRING': { 'type': 'string' },\n",
134+
" 'SOMETHING_ELSE': {},\n",
135+
" 'HAS_DEFAULT': { 'type': 'boolean', 'default': 'NO COERCION!' },\n",
136+
" },\n",
137+
" },\n",
138+
" {\n",
139+
" 'string_value_with_enum': 'these',\n",
140+
" 'MY_INTEGER_VALUE': '1122334',\n",
141+
" 'A_NUMERIC_VALUE': '13',\n",
142+
" }\n",
143+
")\n",
144+
"print(sample_dotenv)"
145+
]
146+
},
147+
{
148+
"cell_type": "code",
149+
"execution_count": 6,
150+
"id": "02a377e6",
151+
"metadata": {
152+
"ExecuteTime": {
153+
"end_time": "2023-06-17T05:25:03.370818Z",
154+
"start_time": "2023-06-17T05:25:03.340627Z"
155+
}
156+
},
157+
"outputs": [],
158+
"source": [
159+
"#| export\n",
160+
"\n",
161+
"@call_parse\n",
162+
"def main(\n",
163+
" generate: str = None, # path to a json schema that validates a dotenv\n",
164+
" schema: str = None, # path to json schema used for validation\n",
165+
" validate: Union[bool, str] = None, # validate a dotenv; if a path not given, assume .env; requires <schema>\n",
166+
"):\n",
167+
" \"friendly tools to work with schemas and dotenv\"\n",
168+
" \n",
169+
" if generate:\n",
170+
" sys.stdout.write(generate_sample_dotenv(generate))\n",
171+
" elif schema and validate:\n",
172+
" if validate is True:\n",
173+
" dotenv_path = '.env'\n",
174+
" else:\n",
175+
" dotenv_path = None\n",
176+
" validate_env(schema, dotenv_path)"
177+
]
178+
},
179+
{
180+
"cell_type": "code",
181+
"execution_count": 7,
182+
"id": "3c3ca54a",
183+
"metadata": {
184+
"ExecuteTime": {
185+
"end_time": "2023-06-17T05:25:05.623222Z",
186+
"start_time": "2023-06-17T05:25:05.577176Z"
187+
}
188+
},
189+
"outputs": [],
190+
"source": [
191+
"#| hide\n",
192+
"import nbdev; nbdev.nbdev_export()"
193+
]
194+
}
195+
],
196+
"metadata": {
197+
"kernelspec": {
198+
"display_name": "Python 3 (ipykernel)",
199+
"language": "python",
200+
"name": "python3"
201+
},
202+
"language_info": {
203+
"codemirror_mode": {
204+
"name": "ipython",
205+
"version": 3
206+
},
207+
"file_extension": ".py",
208+
"mimetype": "text/x-python",
209+
"name": "python",
210+
"nbconvert_exporter": "python",
211+
"pygments_lexer": "ipython3",
212+
"version": "3.10.8"
213+
},
214+
"toc": {
215+
"base_numbering": 1,
216+
"nav_menu": {},
217+
"number_sections": true,
218+
"sideBar": true,
219+
"skip_h1_title": false,
220+
"title_cell": "Table of Contents",
221+
"title_sidebar": "Contents",
222+
"toc_cell": false,
223+
"toc_position": {},
224+
"toc_section_display": true,
225+
"toc_window_display": false
226+
},
227+
"varInspector": {
228+
"cols": {
229+
"lenName": 16,
230+
"lenType": 16,
231+
"lenVar": 40
232+
},
233+
"kernels_config": {
234+
"python": {
235+
"delete_cmd_postfix": "",
236+
"delete_cmd_prefix": "del ",
237+
"library": "var_list.py",
238+
"varRefreshCmd": "print(var_dic_list())"
239+
},
240+
"r": {
241+
"delete_cmd_postfix": ") ",
242+
"delete_cmd_prefix": "rm(",
243+
"library": "var_list.r",
244+
"varRefreshCmd": "cat(var_dic_list()) "
245+
}
246+
},
247+
"types_to_exclude": [
248+
"module",
249+
"function",
250+
"builtin_function_or_method",
251+
"instance",
252+
"_Feature"
253+
],
254+
"window_display": false
255+
}
256+
},
257+
"nbformat": 4,
258+
"nbformat_minor": 5
259+
}

nbs/index.ipynb

Lines changed: 77 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,6 @@
1919
"> validate configs using json schema"
2020
]
2121
},
22-
{
23-
"cell_type": "markdown",
24-
"metadata": {},
25-
"source": [
26-
"This file will become your README and also the index of your documentation."
27-
]
28-
},
2922
{
3023
"cell_type": "markdown",
3124
"metadata": {},
@@ -58,37 +51,96 @@
5851
},
5952
{
6053
"cell_type": "code",
61-
"execution_count": null,
62-
"metadata": {},
63-
"outputs": [
64-
{
65-
"data": {
66-
"text/plain": [
67-
"2"
68-
]
69-
},
70-
"execution_count": null,
71-
"metadata": {},
72-
"output_type": "execute_result"
54+
"execution_count": 1,
55+
"metadata": {
56+
"ExecuteTime": {
57+
"end_time": "2023-06-17T05:27:55.391527Z",
58+
"start_time": "2023-06-17T05:27:55.187083Z"
7359
}
74-
],
60+
},
61+
"outputs": [],
7562
"source": [
76-
"1+1"
63+
"from python_schematized_config.core import ConfigValidator"
7764
]
7865
},
7966
{
8067
"cell_type": "code",
81-
"execution_count": null,
82-
"metadata": {},
68+
"execution_count": 4,
69+
"metadata": {
70+
"ExecuteTime": {
71+
"end_time": "2023-06-17T05:30:00.083972Z",
72+
"start_time": "2023-06-17T05:30:00.081674Z"
73+
}
74+
},
8375
"outputs": [],
84-
"source": []
76+
"source": [
77+
"import os\n",
78+
"import os.path as _p\n",
79+
"\n",
80+
"if _p.exists('.env') and 'CONFIG_VALIDATOR_JSON_SCHEMA' in os.environ:\n",
81+
" ConfigValidator.load_dotenv() # use defaults of .env and CONFIG_VALIDATOR_JSON_SCHEMA"
82+
]
8583
}
8684
],
8785
"metadata": {
8886
"kernelspec": {
89-
"display_name": "python3",
87+
"display_name": "Python 3 (ipykernel)",
9088
"language": "python",
9189
"name": "python3"
90+
},
91+
"language_info": {
92+
"codemirror_mode": {
93+
"name": "ipython",
94+
"version": 3
95+
},
96+
"file_extension": ".py",
97+
"mimetype": "text/x-python",
98+
"name": "python",
99+
"nbconvert_exporter": "python",
100+
"pygments_lexer": "ipython3",
101+
"version": "3.10.8"
102+
},
103+
"toc": {
104+
"base_numbering": 1,
105+
"nav_menu": {},
106+
"number_sections": true,
107+
"sideBar": true,
108+
"skip_h1_title": false,
109+
"title_cell": "Table of Contents",
110+
"title_sidebar": "Contents",
111+
"toc_cell": false,
112+
"toc_position": {},
113+
"toc_section_display": true,
114+
"toc_window_display": false
115+
},
116+
"varInspector": {
117+
"cols": {
118+
"lenName": 16,
119+
"lenType": 16,
120+
"lenVar": 40
121+
},
122+
"kernels_config": {
123+
"python": {
124+
"delete_cmd_postfix": "",
125+
"delete_cmd_prefix": "del ",
126+
"library": "var_list.py",
127+
"varRefreshCmd": "print(var_dic_list())"
128+
},
129+
"r": {
130+
"delete_cmd_postfix": ") ",
131+
"delete_cmd_prefix": "rm(",
132+
"library": "var_list.r",
133+
"varRefreshCmd": "cat(var_dic_list()) "
134+
}
135+
},
136+
"types_to_exclude": [
137+
"module",
138+
"function",
139+
"builtin_function_or_method",
140+
"instance",
141+
"_Feature"
142+
],
143+
"window_display": false
92144
}
93145
},
94146
"nbformat": 4,

nbs/sidebar.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
website:
2+
sidebar:
3+
contents:
4+
- index.ipynb
5+
- 00_core.ipynb
6+
- 01_cli.ipynb

0 commit comments

Comments
 (0)