forked from jpadilla/django-dotenv
-
Notifications
You must be signed in to change notification settings - Fork 2
/
dotenv.py
159 lines (138 loc) · 5.54 KB
/
dotenv.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import os
import sys
import warnings
from collections import OrderedDict
def load_dotenv(dotenv_path):
"""
Read a .env file and load into os.environ.
"""
if not os.path.exists(dotenv_path):
warnings.warn("can't read %s - it doesn't exist." % dotenv_path)
return None
for k, v in parse_dotenv(dotenv_path):
os.environ.setdefault(k, v)
return True
def read_dotenv(dotenv_path=None):
"""
Prior name of load_dotenv function.
Deprecated and pending removal
If not given a path to a dotenv path, does filthy magic stack backtracking
to find manage.py and then find the dotenv.
"""
warnings.warn("read_dotenv deprecated, use load_dotenv instead")
if dotenv_path is None:
warnings.warn("read_dotenv without an explicit path is deprecated and will be removed soon")
frame = sys._getframe()
dotenv_path = os.path.join(os.path.dirname(frame.f_back.f_code.co_filename), '.env')
return load_dotenv(dotenv_path)
def get_key(dotenv_path, key_to_get):
"""
Gets the value of a given key from the given .env
If the .env path given doesn't exist, fails
"""
key_to_get = str(key_to_get)
if not os.path.exists(dotenv_path):
warnings.warn("can't read %s - it doesn't exist." % dotenv_path)
return None
dotenv_as_dict = OrderedDict(parse_dotenv(dotenv_path))
if dotenv_as_dict.has_key(key_to_get):
return dotenv_as_dict[key_to_get]
else:
warnings.warn("key %s not found in %s." % (key_to_get, dotenv_path))
return None
def set_key(dotenv_path, key_to_set, value_to_set):
"""
Adds or Updates a key/value to the given .env
If the .env path given doesn't exist, fails instead of risking creating
an orphan .env somewhere in the filesystem
"""
key_to_set = str(key_to_set)
value_to_set = str(value_to_set).strip("'").strip('"')
if not os.path.exists(dotenv_path):
warnings.warn("can't write to %s - it doesn't exist." % dotenv_path)
return None
dotenv_as_dict = OrderedDict(parse_dotenv(dotenv_path))
dotenv_as_dict[key_to_set] = value_to_set
success = flatten_and_write(dotenv_path, dotenv_as_dict)
return success, key_to_set, value_to_set
def unset_key(dotenv_path, key_to_unset):
"""
Removes a given key from the given .env
If the .env path given doesn't exist, fails
If the given key doesn't exist in the .env, fails
"""
key_to_unset = str(key_to_unset)
if not os.path.exists(dotenv_path):
warnings.warn("can't delete from %s - it doesn't exist." % dotenv_path)
return None
dotenv_as_dict = OrderedDict(parse_dotenv(dotenv_path))
if dotenv_as_dict.has_key(key_to_unset):
dotenv_as_dict.pop(key_to_unset, None)
else:
warnings.warn("key %s not removed from %s - key doesn't exist." % (key_to_unset, dotenv_path))
return None
success = flatten_and_write(dotenv_path, dotenv_as_dict)
return success, key_to_unset
def parse_dotenv(dotenv_path):
with open(dotenv_path) as f:
for line in f:
line = line.strip()
if not line or line.startswith('#') or '=' not in line:
continue
k, v = line.split('=', 1)
v = v.strip("'").strip('"')
yield k, v
def flatten_and_write(dotenv_path, dotenv_as_dict):
with open(dotenv_path, "w") as f:
for k, v in dotenv_as_dict.items():
f.write('%s="%s"\r\n' % (k, v))
return True
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("file_path", help="the absolute path of the .env file you want to use")
parser.add_argument("action", help="what you want to do with the .env file (get, set, unset)", nargs='?')
parser.add_argument("key", help="the environment key you want to set", nargs='?')
parser.add_argument("value", help="the value you want to set 'key' to", nargs='?')
parser.add_argument("--force", help="force writing even if the file at the given path doesn't end in .env")
args = parser.parse_args()
if not os.path.exists(args.file_path):
warnings.warn("there doesn't appear to be a file at %s" % args.file_path)
exit(1)
if not args.force:
if not args.file_path.endswith(".env"):
warnings.warn("the file %s doesn't appear to be a .env file, use --force to proceed" % args.file_path)
exit(1)
if args.action == None:
with open(args.file_path) as f:
print f.read()
exit(0)
elif args.action == "get":
stored_value = get_key(args.file_path, args.key)
if stored_value != None:
print(args.key)
print(stored_value)
else:
exit(1)
elif args.action == "set":
success, key, value = set_key(args.file_path, args.key, args.value)
if success != None:
print("%s: %s" % (key, value))
else:
exit(1)
elif args.action == "unset":
success, key = unset_key(args.file_path, args.key)
if success != None:
print("unset %s" % key)
else:
exit(1)
# Need to investigate if this can actually work or if the scope of the new environ variables
# Expires when python exits
#
# elif args.action == "load":
# success = load_dotenv(args.file_path)
# if success != None:
# print("loaded %s into environment" % args.file_path)
# else:
# exit(1)
exit(0)