-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathdotenv.py
More file actions
155 lines (119 loc) · 4.52 KB
/
dotenv.py
File metadata and controls
155 lines (119 loc) · 4.52 KB
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
"""
Python-dotenv
Loads environment variables from .env file
Usage:
from dotenv import load_dotenv
load_dotenv() # Load from .env in current directory
load_dotenv('/path/to/.env') # Load from specified file
This is a simplified standalone version of python-dotenv that can be placed
directly in your project folder if you're unable to install the package.
"""
import os
import io
import re
import sys
from typing import Dict, Optional, Union, Any, List, Iterator, TextIO
def load_dotenv(dotenv_path: Union[str, os.PathLike, None] = None,
override: bool = False,
encoding: Optional[str] = None) -> bool:
"""
Load the environment variables from a .env file.
Args:
dotenv_path: Path to the .env file. If not provided, looks for .env in current directory
override: Whether to override existing environment variables
encoding: Encoding of the .env file
Returns:
True if the file was loaded successfully, False otherwise
"""
if dotenv_path is None:
dotenv_path = os.path.join(os.getcwd(), '.env')
if not os.path.exists(dotenv_path):
return False
try:
with io.open(dotenv_path, encoding=encoding or 'utf-8') as f:
env_vars = parse_dotenv(f)
except Exception:
return False
for key, value in env_vars.items():
if key in os.environ and not override:
continue
os.environ[key] = value
return True
def dotenv_values(dotenv_path: Union[str, os.PathLike, None] = None,
encoding: Optional[str] = None) -> Dict[str, str]:
"""
Parse a .env file and return a dictionary of key-value pairs.
This is the function that Flask CLI uses.
Args:
dotenv_path: Path to the .env file. If not provided, looks for .env in current directory
encoding: Encoding of the .env file
Returns:
Dictionary of key-value pairs from the .env file
"""
if dotenv_path is None:
dotenv_path = os.path.join(os.getcwd(), '.env')
if not os.path.exists(dotenv_path):
return {}
try:
with io.open(dotenv_path, encoding=encoding or 'utf-8') as f:
return parse_dotenv(f)
except Exception:
return {}
def parse_dotenv(file_obj: TextIO) -> Dict[str, str]:
"""Parse the contents of a .env file and return a dictionary of key-value pairs."""
result = {}
for line in file_obj:
line = line.strip()
if not line or line.startswith('#'):
continue
# Handle basic KEY=VALUE format
if '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
# Remove quotes if present
if value and (
(value[0] == value[-1] == '"') or
(value[0] == value[-1] == "'")
):
value = value[1:-1]
result[key] = value
return result
def find_dotenv(filename: str = '.env',
raise_error_if_not_found: bool = False,
usecwd: bool = False) -> str:
"""
Search for a .env file in parent directories.
Args:
filename: Name of the file to search for
raise_error_if_not_found: Whether to raise an error if file is not found
usecwd: Whether to use the current working directory
Returns:
Path to the found file
Raises:
IOError: If file is not found and raise_error_if_not_found is True
"""
if usecwd:
path = os.getcwd()
else:
frame = sys._getframe()
current_file = __file__
while frame.f_code.co_filename == current_file:
frame = frame.f_back
frame_filename = frame.f_code.co_filename
path = os.path.dirname(os.path.abspath(frame_filename))
for _ in range(10): # Limit the number of parent directories to search
check_path = os.path.join(path, filename)
if os.path.exists(check_path):
return check_path
parent_path = os.path.dirname(path)
if parent_path == path:
break
path = parent_path
if raise_error_if_not_found:
raise IOError(f"File {filename} not found")
return ""
if __name__ == "__main__":
print("This is a standalone version of python-dotenv.")
print("To use it, import the module and call load_dotenv().")
print("For example: from dotenv import load_dotenv; load_dotenv()")