Coverage for src/edwh_restic_plugin/env.py: 13%

1 import warnings

2 from pathlib import Path

3

4# the path where the environment variables are going

5 DOTENV = Path(".env")

6 DOTENV.touch(exist_ok=True)

7

8 _dotenv_settings = {}

9

10

11 def read_dotenv(path: Path = DOTENV) -> dict:

12 """Reads a .env file at the specified path and returns a dictionary of key - value pairs.

13

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.

16

17 Args:

18 path(Path): The path to the .env file.

19

20 Returns:

21 dict: A dictionary containing the key - value pairs in the .env file."""

22

23 if existing := _dotenv_settings.get(path):

24 # 'cache'

25 return existing

26

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

36

37 # convert to tuples

38 k, v = line.split("=", 1)

39

40 # clean the tuples and add to dict

41 items[k.strip()] = v.strip()

42

43 _dotenv_settings[path] = items

44 return items

45

46

47 def set_env_value(path: Path, target: str, value: str) -> None:

48 """

49 update/set environment variables in the .env file, keeping comments intact

50

51 set_env_value(Path('.env'), 'SCHEMA_VERSION', schemaversion)

52

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")

61

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")

92

93

94 def 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)

108

109 suffix = suffix or postfix

110

111 env = read_dotenv(path)

112 if key in env:

113 return env[key]

114

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

124

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")

129

130 # update in memory too:

131 env[key] = value

132 return value