Coverage for src/edwh_restic_plugin/env.py: 13%
60 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-10 20:53 +0100
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-10 20:53 +0100
1import warnings
2from pathlib import Path
4# the path where the environment variables are going
5DOTENV = Path(".env")
6DOTENV.touch(exist_ok=True)
8_dotenv_settings = {}
11def read_dotenv(path: Path = DOTENV) -> dict:
12 """Reads a .env file at the specified path and returns a dictionary of key - value pairs.
14 If the specified key is not found in the.env file, the function prompts the user to enter a value for the key,
15 with a default value provided.The key-value pair is then appended to the.env file.
17 Args:
18 path(Path): The path to the .env file.
20 Returns:
21 dict: A dictionary containing the key - value pairs in the .env file."""
23 if existing := _dotenv_settings.get(path):
24 # 'cache'
25 return existing
27 items = {}
28 with path.open(mode="r") as env_file:
29 for line in env_file:
30 # remove comments and redundant whitespace
31 line = line.split("#", 1)[0].strip()
32 if not line or "=" not in line:
33 # just a comment, skip
34 # or key without value? invalid, prevent crash:
35 continue
37 # convert to tuples
38 k, v = line.split("=", 1)
40 # clean the tuples and add to dict
41 items[k.strip()] = v.strip()
43 _dotenv_settings[path] = items
44 return items
47def set_env_value(path: Path, target: str, value: str) -> None:
48 """
49 update/set environment variables in the .env file, keeping comments intact
51 set_env_value(Path('.env'), 'SCHEMA_VERSION', schemaversion)
53 Args:
54 path: pathlib.Path designating the .env file
55 target: key to write, probably best to use UPPERCASE
56 value: string value to write, or anything that converts to a string using str()
57 """
58 with path.open(mode="r") as env_file:
59 # open the .env file and read every line in the inlines
60 inlines = env_file.read().split("\n")
62 outlines = [] # lines for output
63 geschreven = False
64 for line in inlines:
65 if line.strip().startswith("#"):
66 # ignore comments
67 outlines.append(line)
68 continue
69 # remove redundant whitespace
70 line = line.strip()
71 if not line:
72 # remove empty lines
73 continue
74 # convert to tuples
75 key, oldvalue = line.split("=", 1)
76 # clean the key and value
77 key = key.strip()
78 if key == target:
79 # add the new tuple to the lines
80 outlines.append(f"{key}={value}")
81 geschreven = True
82 else:
83 # or leave it as it is
84 outlines.append(line)
85 if not geschreven:
86 # if target in .env file
87 outlines.append(f"{target.strip().upper()}={value.strip()}")
88 with path.open(mode="w") as env_file:
89 # write outlines to .env file
90 env_file.write("\n".join(outlines))
91 env_file.write("\n")
94def check_env(
95 key: str,
96 default: str | None,
97 comment: str,
98 prefix: str = None,
99 suffix: str = None,
100 postfix: str = None,
101 path: Path = None,
102):
103 """
104 Test if key is in .env file path, appends prompted or default value if missing.
105 """
106 if postfix:
107 warnings.warn("`postfix` option passed. Please use `suffix` instead!", category=DeprecationWarning)
109 suffix = suffix or postfix
111 env = read_dotenv(path)
112 if key in env:
113 return env[key]
115 # get response value from prompt/input
116 # if response_value is empty make value default else value is response_value
117 value = input(f"Enter value for {key} ({comment})\n default=`{default}`: ").strip() or default or ""
118 if value.startswith("~/") and Path(value).expanduser().exists():
119 value = str(Path(value).expanduser())
120 if prefix:
121 value = prefix + value
122 if suffix:
123 value += suffix
125 with path.open(mode="r+") as env_file:
126 env_file.seek(0, 2)
127 # write key and value to .env file
128 env_file.write(f"\n{key.upper()}={value}\n")
130 # update in memory too:
131 env[key] = value
132 return value