Skip to content

Commit 71c329d

Browse files
committed
add return codes to CLI, simplify nbdev export deps
1 parent 205c7c4 commit 71c329d

File tree

6 files changed

+61
-68
lines changed

6 files changed

+61
-68
lines changed

nbs/00_core.ipynb

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,36 @@
2525
"outputs": [],
2626
"source": [
2727
"#| export\n",
28-
"from nbdev.showdoc import *\n",
29-
"from fastcore.test import *\n",
30-
"from unittest.mock import patch\n",
31-
"\n",
32-
"import dotenv\n",
3328
"import json\n",
29+
"import logging\n",
3430
"import os\n",
3531
"import os.path\n",
36-
"import jsonschema\n",
37-
"import logging\n",
38-
"from jsonschema import validate, ValidationError\n",
3932
"from typing import Union\n",
33+
"\n",
34+
"import dotenv\n",
35+
"import jsonschema\n",
4036
"from fs.base import FS\n",
4137
"from fs.osfs import OSFS\n",
42-
"\n",
38+
"from jsonschema import ValidationError, validate\n",
4339
"\n",
4440
"logger = logging.getLogger(__name__)"
4541
]
4642
},
43+
{
44+
"cell_type": "code",
45+
"execution_count": null,
46+
"metadata": {},
47+
"outputs": [],
48+
"source": [
49+
"#| hide\n",
50+
"\n",
51+
"# dev/testing deps\n",
52+
"from unittest.mock import patch\n",
53+
"\n",
54+
"from fastcore.test import *\n",
55+
"from nbdev.showdoc import *"
56+
]
57+
},
4758
{
4859
"cell_type": "code",
4960
"execution_count": null,
@@ -652,7 +663,7 @@
652663
"ConfigValidator.DEFAULT_STORAGE_DRIVER = memfs_fallback\n",
653664
"\n",
654665
"validated_config5 = ConfigValidator.load_dotenv(\n",
655-
" json_schema='schema.json'\n",
666+
" json_schema='schema.json',\n",
656667
")\n",
657668
" \n",
658669
"ConfigValidator.DEFAULT_STORAGE_DRIVER = OLD_DRIVER"
@@ -662,22 +673,7 @@
662673
"cell_type": "code",
663674
"execution_count": null,
664675
"metadata": {},
665-
"outputs": [
666-
{
667-
"ename": "ResourceNotFound",
668-
"evalue": "resource 'special-bespoke-location/my-own.env' not found",
669-
"output_type": "error",
670-
"traceback": [
671-
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
672-
"\u001b[0;31mResourceNotFound\u001b[0m Traceback (most recent call last)",
673-
"Cell \u001b[0;32mIn[97], line 11\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m memfs\u001b[38;5;241m.\u001b[39mopen(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mfoo.schema.json\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mw\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m ofile:\n\u001b[1;32m 5\u001b[0m ofile\u001b[38;5;241m.\u001b[39mwrite(json\u001b[38;5;241m.\u001b[39mdumps({\n\u001b[1;32m 6\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtype\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mobject\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 7\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mproperties\u001b[39m\u001b[38;5;124m'\u001b[39m: {\n\u001b[1;32m 8\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mA_NUMERIC_VALUE\u001b[39m\u001b[38;5;124m'\u001b[39m: { \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtype\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mnumber\u001b[39m\u001b[38;5;124m'\u001b[39m },\n\u001b[1;32m 9\u001b[0m }\n\u001b[1;32m 10\u001b[0m }))\n\u001b[0;32m---> 11\u001b[0m validated_dotenv \u001b[38;5;241m=\u001b[39m \u001b[43mConfigValidator\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_dotenv\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 12\u001b[0m \u001b[43m \u001b[49m\u001b[43mjson_schema\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mfoo.schema.json\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 13\u001b[0m \u001b[43m \u001b[49m\u001b[43mdotenv_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mspecial-bespoke-location/my-own.env\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 14\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_driver\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmemfs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 15\u001b[0m \u001b[43m)\u001b[49m\n\u001b[1;32m 16\u001b[0m test_eq(validated_dotenv, {\n\u001b[1;32m 17\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mA_NUMERIC_VALUE\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;241m1167.89\u001b[39m,\n\u001b[1;32m 18\u001b[0m })\n\u001b[1;32m 20\u001b[0m test_fail(validator\u001b[38;5;241m.\u001b[39mload_dotenv, kwargs\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdotenv_path\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mnon-existent-location-own.env\u001b[39m\u001b[38;5;124m'\u001b[39m})\n",
674-
"Cell \u001b[0;32mIn[80], line 143\u001b[0m, in \u001b[0;36mConfigValidator.load_dotenv\u001b[0;34m(cls, json_schema, dotenv_path, storage_driver, override)\u001b[0m\n\u001b[1;32m 141\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m dotenv_path:\n\u001b[1;32m 142\u001b[0m dotenv_storage_driver \u001b[38;5;241m=\u001b[39m storage_driver \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39m_get_maybe_abspath_driver(dotenv_path)\n\u001b[0;32m--> 143\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mdotenv_storage_driver\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mopen\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdotenv_path\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m ifile:\n\u001b[1;32m 144\u001b[0m config \u001b[38;5;241m=\u001b[39m dotenv\u001b[38;5;241m.\u001b[39mdotenv_values(stream\u001b[38;5;241m=\u001b[39mifile)\n\u001b[1;32m 146\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m config \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
675-
"File \u001b[0;32m~/Desktop/experiment/python-schematized-config/venv/lib/python3.10/site-packages/fs/base.py:1228\u001b[0m, in \u001b[0;36mFS.open\u001b[0;34m(self, path, mode, buffering, encoding, errors, newline, **options)\u001b[0m\n\u001b[1;32m 1226\u001b[0m validate_open_mode(mode)\n\u001b[1;32m 1227\u001b[0m bin_mode \u001b[38;5;241m=\u001b[39m mode\u001b[38;5;241m.\u001b[39mreplace(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mt\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m-> 1228\u001b[0m bin_file \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mopenbin\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbin_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbuffering\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbuffering\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1229\u001b[0m io_stream \u001b[38;5;241m=\u001b[39m iotools\u001b[38;5;241m.\u001b[39mmake_stream(\n\u001b[1;32m 1230\u001b[0m path,\n\u001b[1;32m 1231\u001b[0m bin_file,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1237\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39moptions\n\u001b[1;32m 1238\u001b[0m )\n\u001b[1;32m 1239\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m io_stream\n",
676-
"File \u001b[0;32m~/Desktop/experiment/python-schematized-config/venv/lib/python3.10/site-packages/fs/memoryfs.py:513\u001b[0m, in \u001b[0;36mMemoryFS.openbin\u001b[0;34m(self, path, mode, buffering, **options)\u001b[0m\n\u001b[1;32m 511\u001b[0m parent_dir_entry \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_dir_entry(dir_path)\n\u001b[1;32m 512\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m parent_dir_entry \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m parent_dir_entry\u001b[38;5;241m.\u001b[39mis_dir:\n\u001b[0;32m--> 513\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m errors\u001b[38;5;241m.\u001b[39mResourceNotFound(path)\n\u001b[1;32m 515\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m _mode\u001b[38;5;241m.\u001b[39mcreate:\n\u001b[1;32m 516\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m file_name \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m parent_dir_entry:\n",
677-
"\u001b[0;31mResourceNotFound\u001b[0m: resource 'special-bespoke-location/my-own.env' not found"
678-
]
679-
}
680-
],
676+
"outputs": [],
681677
"source": [
682678
"#| hide\n",
683679
"# test using custom json schema\n",
@@ -774,8 +770,8 @@
774770
"possibly due to jupyter environment blackmagicfuddery, mocking builtins.open DOES NOT WORK!\n",
775771
"take the easy way out and mock an actual file!\n",
776772
"'''\n",
777-
"import tempfile\n",
778773
"import os.path as _p\n",
774+
"import tempfile\n",
779775
"\n",
780776
"OLD_DRIVER = ConfigValidator.DEFAULT_STORAGE_DRIVER\n",
781777
"ConfigValidator.DEFAULT_STORAGE_DRIVER = None\n",

nbs/01_cli.ipynb

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,16 @@
2828
"outputs": [],
2929
"source": [
3030
"#| export\n",
31-
"from schematized_config.core import (\n",
32-
" ConfigValidator,\n",
33-
" ConfigValidatorException,\n",
34-
" extract_declared_items,\n",
35-
")\n",
36-
"\n",
31+
"import argparse\n",
3732
"import os\n",
3833
"import sys\n",
39-
"import argparse\n",
40-
"import dotenv\n",
4134
"from typing import Union\n",
42-
"from fastcore.script import call_parse, anno_parser"
35+
"\n",
36+
"import dotenv\n",
37+
"from fastcore.script import anno_parser, call_parse\n",
38+
"\n",
39+
"from schematized_config.core import (ConfigValidator, ConfigValidatorException,\n",
40+
" extract_declared_items)"
4341
]
4442
},
4543
{
@@ -50,7 +48,7 @@
5048
"outputs": [],
5149
"source": [
5250
"#| export\n",
53-
"def validate_env(json_schema: Union[str, dict], dotenv_path: str=None):\n",
51+
"def validate_env(json_schema: Union[str, dict], dotenv_path: str=None) -> bool:\n",
5452
" validator = ConfigValidator(json_schema)\n",
5553
" try:\n",
5654
" validator.load_config(dotenv.dotenv_values(dotenv_path))\n",
@@ -70,7 +68,7 @@
7068
"outputs": [],
7169
"source": [
7270
"#| export\n",
73-
"def generate_sample_dotenv(json_schema: Union[str, dict], seed_config: dict=None):\n",
71+
"def generate_sample_dotenv(json_schema: Union[str, dict], seed_config: dict=None) -> str:\n",
7472
" schema_dict = ConfigValidator.load_json(json_schema)\n",
7573
" merged_config = dict(os.environ)\n",
7674
" default_dotenv = dotenv.dotenv_values()\n",
@@ -163,9 +161,12 @@
163161
" sys.stdout.write(generate_sample_dotenv(generate))\n",
164162
" elif schema and validate:\n",
165163
" dotenv_path = validate\n",
166-
" validate_env(schema, dotenv_path)\n",
164+
" if validate_env(schema, dotenv_path):\n",
165+
" sys.exit(0)\n",
166+
" else:\n",
167+
" sys.exit(1)\n",
167168
" else:\n",
168-
" anno_parser(main, EXECUTABLE_NAME).print_help()\n"
169+
" anno_parser(main, EXECUTABLE_NAME).print_help()"
169170
]
170171
},
171172
{

schematized_config/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.0.10"
1+
__version__ = "0.0.11"

schematized_config/cli.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,19 @@
44
__all__ = ['VERSION', 'EXECUTABLE_NAME', 'validate_env', 'generate_sample_dotenv', 'main']
55

66
# %% ../nbs/01_cli.ipynb 2
7-
from schematized_config.core import (
8-
ConfigValidator,
9-
ConfigValidatorException,
10-
extract_declared_items,
11-
)
12-
7+
import argparse
138
import os
149
import sys
15-
import argparse
16-
import dotenv
1710
from typing import Union
18-
from fastcore.script import call_parse, anno_parser
11+
12+
import dotenv
13+
from fastcore.script import anno_parser, call_parse
14+
15+
from .core import (ConfigValidator, ConfigValidatorException,
16+
extract_declared_items)
1917

2018
# %% ../nbs/01_cli.ipynb 3
21-
def validate_env(json_schema: Union[str, dict], dotenv_path: str=None):
19+
def validate_env(json_schema: Union[str, dict], dotenv_path: str=None) -> bool:
2220
validator = ConfigValidator(json_schema)
2321
try:
2422
validator.load_config(dotenv.dotenv_values(dotenv_path))
@@ -30,7 +28,7 @@ def validate_env(json_schema: Union[str, dict], dotenv_path: str=None):
3028
return False
3129

3230
# %% ../nbs/01_cli.ipynb 4
33-
def generate_sample_dotenv(json_schema: Union[str, dict], seed_config: dict=None):
31+
def generate_sample_dotenv(json_schema: Union[str, dict], seed_config: dict=None) -> str:
3432
schema_dict = ConfigValidator.load_json(json_schema)
3533
merged_config = dict(os.environ)
3634
default_dotenv = dotenv.dotenv_values()
@@ -78,7 +76,9 @@ def main(
7876
sys.stdout.write(generate_sample_dotenv(generate))
7977
elif schema and validate:
8078
dotenv_path = validate
81-
validate_env(schema, dotenv_path)
79+
if validate_env(schema, dotenv_path):
80+
sys.exit(0)
81+
else:
82+
sys.exit(1)
8283
else:
8384
anno_parser(main, EXECUTABLE_NAME).print_help()
84-

schematized_config/core.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,21 @@
44
__all__ = ['logger', 'coerce_primitive_values', 'extract_declared_items', 'ConfigValidatorException', 'ConfigValidator']
55

66
# %% ../nbs/00_core.ipynb 2
7-
from nbdev.showdoc import *
8-
from fastcore.test import *
9-
from unittest.mock import patch
10-
11-
import dotenv
127
import json
8+
import logging
139
import os
1410
import os.path
15-
import jsonschema
16-
import logging
17-
from jsonschema import validate, ValidationError
1811
from typing import Union
12+
13+
import dotenv
14+
import jsonschema
1915
from fs.base import FS
2016
from fs.osfs import OSFS
21-
17+
from jsonschema import ValidationError, validate
2218

2319
logger = logging.getLogger(__name__)
2420

25-
# %% ../nbs/00_core.ipynb 3
21+
# %% ../nbs/00_core.ipynb 4
2622
def coerce_primitive_values(json_schema: dict, data: dict) -> dict:
2723
"""
2824
Given a JSON schema dictionary, return a dictionary where the values that have
@@ -68,7 +64,7 @@ def coerce_primitive_values(json_schema: dict, data: dict) -> dict:
6864
continue
6965
return out
7066

71-
# %% ../nbs/00_core.ipynb 6
67+
# %% ../nbs/00_core.ipynb 7
7268
def extract_declared_items(json_schema: dict, data: dict) -> dict:
7369
"""
7470
Given a JSON schema dict, return a dict following specified rules:
@@ -92,7 +88,7 @@ def extract_declared_items(json_schema: dict, data: dict) -> dict:
9288
out[required_property] = property_schema['default']
9389
return out
9490

95-
# %% ../nbs/00_core.ipynb 8
91+
# %% ../nbs/00_core.ipynb 9
9692
class ConfigValidatorException(Exception):
9793

9894
def __init__(self, errors):

settings.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[DEFAULT]
22
repo = python-schematized-config
33
lib_name = python-schematized-config
4-
version = 0.0.10
4+
version = 0.0.12
55
min_python = 3.7
66
license = apache2
77
black_formatting = False
@@ -26,7 +26,7 @@ keywords = nbdev jupyter notebook python
2626
language = English
2727
status = 3
2828
user = tutankalex
29-
requirements = jsonschema>=4.17.3 python-dotenv>=1.0.0 fs>=2.4.16 nbdev>=2.3.12
29+
requirements = jsonschema>=4.17.3 python-dotenv>=1.0.0 fs>=2.4.16
3030
readme_nb = index.ipynb
3131
allowed_metadata_keys =
3232
allowed_cell_metadata_keys =

0 commit comments

Comments
 (0)