|
27 | 27 | "#| export\n", |
28 | 28 | "from nbdev.showdoc import *\n", |
29 | 29 | "from fastcore.test import *\n", |
| 30 | + "from unittest.mock import patch\n", |
30 | 31 | "\n", |
31 | 32 | "import dotenv\n", |
32 | 33 | "import json\n", |
|
280 | 281 | " return cls.load_validated_config(json_schema, dict(os.environ), **kwargs)\n", |
281 | 282 | " \n", |
282 | 283 | " @classmethod\n", |
283 | | - " def load_dotenv(cls, json_schema: Union[str, dict]=None, dotenv_path: str=None, storage_driver: FS=None):\n", |
| 284 | + " def load_dotenv(cls,\n", |
| 285 | + " json_schema: Union[str, dict]=None,\n", |
| 286 | + " dotenv_path: str=None,\n", |
| 287 | + " storage_driver: FS=None,\n", |
| 288 | + " override: bool=False,\n", |
| 289 | + " ):\n", |
| 290 | + " '''\n", |
| 291 | + " :param override: set variables into os.environ where applicable; i.e.\n", |
| 292 | + " - if set in os.environ already and valid, leave alone\n", |
| 293 | + " - if not set in os.environ already, read from .env or schema default\n", |
| 294 | + " '''\n", |
| 295 | + " \n", |
284 | 296 | " storage_driver = storage_driver or cls.DEFAULT_STORAGE_DRIVER\n", |
285 | 297 | " if dotenv_path is None:\n", |
286 | 298 | " maybe_dotenv_path = dotenv.find_dotenv() # '' if not exist\n", |
|
301 | 313 | " if key in config and config[key] != os.environ[key]:\n", |
302 | 314 | " logger.debug(f'os.environ key \"{key}\" overriding value present in {dotenv_path}')\n", |
303 | 315 | " config[key] = os.environ[key]\n", |
304 | | - " return cls.load_validated_config(\n", |
| 316 | + " validated_config = cls.load_validated_config(\n", |
305 | 317 | " json_schema or cls.get_default_json_schema(storage_driver=storage_driver),\n", |
306 | | - " config, storage_driver=storage_driver)" |
| 318 | + " config, storage_driver=storage_driver)\n", |
| 319 | + " \n", |
| 320 | + " if override:\n", |
| 321 | + " for key, value in validated_config.items():\n", |
| 322 | + " if key in os.environ:\n", |
| 323 | + " continue\n", |
| 324 | + " os.environ[key] = value\n", |
| 325 | + " \n", |
| 326 | + " return validated_config" |
307 | 327 | ] |
308 | 328 | }, |
309 | 329 | { |
|
675 | 695 | "})" |
676 | 696 | ] |
677 | 697 | }, |
| 698 | + { |
| 699 | + "cell_type": "code", |
| 700 | + "execution_count": null, |
| 701 | + "metadata": {}, |
| 702 | + "outputs": [], |
| 703 | + "source": [ |
| 704 | + "#| hide\n", |
| 705 | + "# test propagating values into os.environ depending on flag\n", |
| 706 | + "\n", |
| 707 | + "def test_propagate_values_into_os_environ():\n", |
| 708 | + " \n", |
| 709 | + " with memfs.open('flag.schema.json', 'w') as ofile:\n", |
| 710 | + " ofile.write(json.dumps({\n", |
| 711 | + " 'type': 'object',\n", |
| 712 | + " 'properties': {\n", |
| 713 | + " 'UNINVITED_GUEST': { 'type': 'string', 'default': 'from schema' },\n", |
| 714 | + " }\n", |
| 715 | + " }))\n", |
| 716 | + " \n", |
| 717 | + " with memfs.open('.flag-env1', 'w') as ofile:\n", |
| 718 | + " ofile.write('')\n", |
| 719 | + " \n", |
| 720 | + " with memfs.open('.flag-env2', 'w') as ofile:\n", |
| 721 | + " ofile.write('\\n'.join([\n", |
| 722 | + " 'UNINVITED_GUEST=from dotenv',\n", |
| 723 | + " ]))\n", |
| 724 | + " \n", |
| 725 | + " with memfs.open('.flag-env3', 'w') as ofile:\n", |
| 726 | + " ofile.write('\\n'.join([\n", |
| 727 | + " 'UNINVITED_GUEST=I should be ignored!',\n", |
| 728 | + " ]))\n", |
| 729 | + "\n", |
| 730 | + " mock_env = {\"already_here\": \"no touch me\"}\n", |
| 731 | + "\n", |
| 732 | + " with patch.dict('os.environ', mock_env):\n", |
| 733 | + " \n", |
| 734 | + " # don't update os.environ\n", |
| 735 | + " validated_config1 = ConfigValidator.load_dotenv(\n", |
| 736 | + " json_schema='flag.schema.json',\n", |
| 737 | + " dotenv_path='.flag-env1',\n", |
| 738 | + " storage_driver=memfs,\n", |
| 739 | + " )\n", |
| 740 | + " test_eq(os.environ.get(\"already_here\"), \"no touch me\")\n", |
| 741 | + " test_eq(os.environ.get(\"UNINVITED_GUEST\"), None)\n", |
| 742 | + " test_eq(validated_config1.get(\"UNINVITED_GUEST\"), \"from schema\")\n", |
| 743 | + " \n", |
| 744 | + " # update os.environ, loading from schema\n", |
| 745 | + " validated_config2 = ConfigValidator.load_dotenv(\n", |
| 746 | + " json_schema='flag.schema.json',\n", |
| 747 | + " dotenv_path='.flag-env1',\n", |
| 748 | + " storage_driver=memfs,\n", |
| 749 | + " override=True\n", |
| 750 | + " )\n", |
| 751 | + " test_eq(validated_config1, validated_config2)\n", |
| 752 | + " test_eq(os.environ.get(\"UNINVITED_GUEST\"), \"from schema\")\n", |
| 753 | + " \n", |
| 754 | + " os.environ.pop('UNINVITED_GUEST')\n", |
| 755 | + " # update os.environ, loading from dotenv\n", |
| 756 | + " validated_config3 = ConfigValidator.load_dotenv(\n", |
| 757 | + " json_schema='flag.schema.json',\n", |
| 758 | + " dotenv_path='.flag-env2',\n", |
| 759 | + " storage_driver=memfs,\n", |
| 760 | + " override=True\n", |
| 761 | + " )\n", |
| 762 | + " test_eq(os.environ.get(\"UNINVITED_GUEST\"), \"from dotenv\")\n", |
| 763 | + " \n", |
| 764 | + " # os.environ is set; takes precedence\n", |
| 765 | + " validated_config3 = ConfigValidator.load_dotenv(\n", |
| 766 | + " json_schema='flag.schema.json',\n", |
| 767 | + " dotenv_path='.flag-env3',\n", |
| 768 | + " storage_driver=memfs,\n", |
| 769 | + " override=True\n", |
| 770 | + " )\n", |
| 771 | + " test_eq(os.environ.get(\"UNINVITED_GUEST\"), \"from dotenv\")\n", |
| 772 | + " \n", |
| 773 | + "test_propagate_values_into_os_environ()" |
| 774 | + ] |
| 775 | + }, |
678 | 776 | { |
679 | 777 | "cell_type": "code", |
680 | 778 | "execution_count": null, |
|
0 commit comments