Skip to content

Commit 46a8fdd

Browse files
committed
fix bad variable breaking .env local fallback
fixes bug noted in [](f1911af)
1 parent f1911af commit 46a8fdd

File tree

4 files changed

+97
-64
lines changed

4 files changed

+97
-64
lines changed

nbs/00_core.ipynb

Lines changed: 94 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@
363363
" if config is None:\n",
364364
" dotenv_storage_driver = storage_driver or cls.get_default_storage_driver()\n",
365365
" if dotenv_storage_driver.exists('.env'): # unlike dotenv.find_dotenv, stay relative!\n",
366-
" with dotenv_storage_driver.open('.env') as ofile:\n",
366+
" with dotenv_storage_driver.open('.env') as ifile:\n",
367367
" config = dotenv.dotenv_values(stream=ifile)\n",
368368
" \n",
369369
" if config is None:\n",
@@ -634,65 +634,50 @@
634634
"outputs": [],
635635
"source": [
636636
"#| hide\n",
637-
"# test loading out of CWD\n",
637+
"# test non-os FS with fallback .env path (=$PWD/.env)\n",
638638
"\n",
639+
"memfs_fallback = MemoryFS()\n",
639640
"\n",
640-
"'''\n",
641-
"possibly due to jupyter environment blackmagicfuddery, mocking builtins.open DOES NOT WORK!\n",
642-
"take the easy way out and mock an actual file!\n",
643-
"'''\n",
644-
"import tempfile\n",
645-
"import os.path as _p\n",
641+
"with memfs_fallback.open('schema.json', 'w') as ofile:\n",
642+
" ofile.write(json.dumps(example_properties_schema))\n",
643+
" \n",
644+
"with memfs_fallback.open('.env', 'w') as ofile:\n",
645+
" ofile.write('\\n'.join([\n",
646+
" 'string_value_with_enum=only',\n",
647+
" 'MY_INTEGER_VALUE=9989998',\n",
648+
" 'A_NUMERIC_VALUE=1167.89',\n",
649+
" ]))\n",
646650
"\n",
647651
"OLD_DRIVER = ConfigValidator.DEFAULT_STORAGE_DRIVER\n",
648-
"ConfigValidator.DEFAULT_STORAGE_DRIVER = None\n",
649-
"\n",
650-
"with tempfile.TemporaryDirectory() as tempdir:\n",
651-
"\n",
652-
" orig_dir = os.getcwd()\n",
653-
" os.chdir(tempdir)\n",
654-
"\n",
655-
" dotenv_path = '.flag-env1'\n",
656-
" with open(dotenv_path, 'wt') as f:\n",
657-
" f.write('WINTER=COLD\\n')\n",
658-
"\n",
659-
" json_schema_path = 'flag.schema.json'\n",
660-
" with open(json_schema_path, 'wt') as f:\n",
661-
" schema = {\"type\": \"object\", \"properties\": {\"WINTER\": {\"type\": \"string\"}, \"SUMMER\": {\"type\": \"string\", \"default\": \"HOT\"}}}\n",
662-
" json.dump(schema, f)\n",
663-
"\n",
664-
" dotenv_abspath = _p.join(tempdir, dotenv_path)\n",
665-
" json_schema_abspath = _p.join(tempdir, json_schema_path)\n",
666-
"\n",
667-
" validated_config = ConfigValidator.load_dotenv(\n",
668-
" json_schema=json_schema_path,\n",
669-
" dotenv_path=dotenv_path\n",
670-
" )\n",
671-
" test_eq(validated_config, {'WINTER': 'COLD', 'SUMMER': 'HOT'})\n",
672-
" os.chdir(orig_dir)\n",
673-
"\n",
674-
" # test ConfigValidator continues to use the working directory on first invocation\n",
675-
" validated_config2 = ConfigValidator.load_dotenv(\n",
676-
" json_schema=json_schema_path,\n",
677-
" dotenv_path=dotenv_abspath\n",
678-
" )\n",
679-
" test_eq(validated_config, validated_config2)\n",
680-
"\n",
681-
" validated_config3 = ConfigValidator.load_dotenv(\n",
682-
" json_schema=json_schema_abspath,\n",
683-
" dotenv_path=dotenv_abspath\n",
684-
" )\n",
685-
" test_eq(validated_config, validated_config2)\n",
686-
"\n",
652+
"ConfigValidator.DEFAULT_STORAGE_DRIVER = memfs_fallback\n",
687653
"\n",
654+
"validated_config5 = ConfigValidator.load_dotenv(\n",
655+
" json_schema='schema.json'\n",
656+
")\n",
657+
" \n",
688658
"ConfigValidator.DEFAULT_STORAGE_DRIVER = OLD_DRIVER"
689659
]
690660
},
691661
{
692662
"cell_type": "code",
693663
"execution_count": null,
694664
"metadata": {},
695-
"outputs": [],
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+
],
696681
"source": [
697682
"#| hide\n",
698683
"# test using custom json schema\n",
@@ -775,6 +760,66 @@
775760
"})"
776761
]
777762
},
763+
{
764+
"cell_type": "code",
765+
"execution_count": null,
766+
"metadata": {},
767+
"outputs": [],
768+
"source": [
769+
"#| hide\n",
770+
"# test loading out of CWD\n",
771+
"\n",
772+
"\n",
773+
"'''\n",
774+
"possibly due to jupyter environment blackmagicfuddery, mocking builtins.open DOES NOT WORK!\n",
775+
"take the easy way out and mock an actual file!\n",
776+
"'''\n",
777+
"import tempfile\n",
778+
"import os.path as _p\n",
779+
"\n",
780+
"OLD_DRIVER = ConfigValidator.DEFAULT_STORAGE_DRIVER\n",
781+
"ConfigValidator.DEFAULT_STORAGE_DRIVER = None\n",
782+
"\n",
783+
"with tempfile.TemporaryDirectory() as tempdir:\n",
784+
"\n",
785+
" orig_dir = os.getcwd()\n",
786+
" os.chdir(tempdir)\n",
787+
"\n",
788+
" dotenv_path = '.flag-env1'\n",
789+
" with open(dotenv_path, 'wt') as f:\n",
790+
" f.write('WINTER=COLD\\n')\n",
791+
"\n",
792+
" json_schema_path = 'flag.schema.json'\n",
793+
" with open(json_schema_path, 'wt') as f:\n",
794+
" schema = {\"type\": \"object\", \"properties\": {\"WINTER\": {\"type\": \"string\"}, \"SUMMER\": {\"type\": \"string\", \"default\": \"HOT\"}}}\n",
795+
" json.dump(schema, f)\n",
796+
"\n",
797+
" dotenv_abspath = _p.join(tempdir, dotenv_path)\n",
798+
" json_schema_abspath = _p.join(tempdir, json_schema_path)\n",
799+
"\n",
800+
" validated_config = ConfigValidator.load_dotenv(\n",
801+
" json_schema=json_schema_path,\n",
802+
" dotenv_path=dotenv_path\n",
803+
" )\n",
804+
" test_eq(validated_config, {'WINTER': 'COLD', 'SUMMER': 'HOT'})\n",
805+
" os.chdir(orig_dir)\n",
806+
"\n",
807+
" # test ConfigValidator continues to use the working directory on first invocation\n",
808+
" validated_config2 = ConfigValidator.load_dotenv(\n",
809+
" json_schema=json_schema_path,\n",
810+
" dotenv_path=dotenv_abspath\n",
811+
" )\n",
812+
" test_eq(validated_config, validated_config2)\n",
813+
"\n",
814+
" validated_config3 = ConfigValidator.load_dotenv(\n",
815+
" json_schema=json_schema_abspath,\n",
816+
" dotenv_path=dotenv_abspath\n",
817+
" )\n",
818+
" test_eq(validated_config, validated_config2)\n",
819+
"\n",
820+
"ConfigValidator.DEFAULT_STORAGE_DRIVER = OLD_DRIVER"
821+
]
822+
},
778823
{
779824
"cell_type": "code",
780825
"execution_count": null,
@@ -869,21 +914,9 @@
869914
],
870915
"metadata": {
871916
"kernelspec": {
872-
"display_name": "Python 3 (ipykernel)",
917+
"display_name": "python3",
873918
"language": "python",
874919
"name": "python3"
875-
},
876-
"language_info": {
877-
"codemirror_mode": {
878-
"name": "ipython",
879-
"version": 3
880-
},
881-
"file_extension": ".py",
882-
"mimetype": "text/x-python",
883-
"name": "python",
884-
"nbconvert_exporter": "python",
885-
"pygments_lexer": "ipython3",
886-
"version": "3.10.8"
887920
}
888921
},
889922
"nbformat": 4,

schematized_config/__init__.py

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

schematized_config/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def load_dotenv(cls,
240240
if config is None:
241241
dotenv_storage_driver = storage_driver or cls.get_default_storage_driver()
242242
if dotenv_storage_driver.exists('.env'): # unlike dotenv.find_dotenv, stay relative!
243-
with dotenv_storage_driver.open('.env') as ofile:
243+
with dotenv_storage_driver.open('.env') as ifile:
244244
config = dotenv.dotenv_values(stream=ifile)
245245

246246
if config is None:

settings.ini

Lines changed: 1 addition & 1 deletion
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.9
4+
version = 0.0.10
55
min_python = 3.7
66
license = apache2
77
black_formatting = False

0 commit comments

Comments
 (0)