Skip to content

Commit 23509f2

Browse files
ulyssessouzabbc2
authored andcommitted
Support no value keys
Signed-off-by: ulyssessouza <[email protected]>
1 parent 723809f commit 23509f2

3 files changed

Lines changed: 18 additions & 15 deletions

File tree

src/dotenv/main.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class DotEnv():
5050
def __init__(self, dotenv_path, verbose=False, encoding=None):
5151
# type: (Union[Text, _PathLike, _StringIO], bool, Union[None, Text]) -> None
5252
self.dotenv_path = dotenv_path # type: Union[Text,_PathLike, _StringIO]
53-
self._dict = None # type: Optional[Dict[Text, Text]]
53+
self._dict = None # type: Optional[Dict[Text, Optional[Text]]]
5454
self.verbose = verbose # type: bool
5555
self.encoding = encoding # type: Union[None, Text]
5656

@@ -68,7 +68,7 @@ def _get_stream(self):
6868
yield StringIO('')
6969

7070
def dict(self):
71-
# type: () -> Dict[Text, Text]
71+
# type: () -> Dict[Text, Optional[Text]]
7272
"""Return dotenv as dict"""
7373
if self._dict:
7474
return self._dict
@@ -78,10 +78,10 @@ def dict(self):
7878
return self._dict
7979

8080
def parse(self):
81-
# type: () -> Iterator[Tuple[Text, Text]]
81+
# type: () -> Iterator[Tuple[Text, Optional[Text]]]
8282
with self._get_stream() as stream:
8383
for mapping in with_warn_for_invalid_lines(parse_stream(stream)):
84-
if mapping.key is not None and mapping.value is not None:
84+
if mapping.key is not None:
8585
yield mapping.key, mapping.value
8686

8787
def set_as_environment_variables(self, override=False):
@@ -92,7 +92,8 @@ def set_as_environment_variables(self, override=False):
9292
for k, v in self.dict().items():
9393
if k in os.environ and not override:
9494
continue
95-
os.environ[to_env(k)] = to_env(v)
95+
if v is not None:
96+
os.environ[to_env(k)] = to_env(v)
9697

9798
return True
9899

@@ -197,7 +198,7 @@ def unset_key(dotenv_path, key_to_unset, quote_mode="always"):
197198

198199

199200
def resolve_nested_variables(values):
200-
# type: (Dict[Text, Text]) -> Dict[Text, Text]
201+
# type: (Dict[Text, Optional[Text]]) -> Dict[Text, Optional[Text]]
201202
def _replacement(name):
202203
# type: (Text) -> Text
203204
"""
@@ -206,7 +207,7 @@ def _replacement(name):
206207
then look into the dotenv variables
207208
"""
208209
ret = os.getenv(name, new_values.get(name, ""))
209-
return ret
210+
return ret # type: ignore
210211

211212
def _re_sub_callback(match_object):
212213
# type: (Match[Text]) -> Text
@@ -219,7 +220,7 @@ def _re_sub_callback(match_object):
219220
new_values = {}
220221

221222
for k, v in values.items():
222-
new_values[k] = __posix_variable.sub(_re_sub_callback, v)
223+
new_values[k] = __posix_variable.sub(_re_sub_callback, v) if v is not None else None
223224

224225
return new_values
225226

@@ -301,6 +302,6 @@ def load_dotenv(dotenv_path=None, stream=None, verbose=False, override=False, **
301302

302303

303304
def dotenv_values(dotenv_path=None, stream=None, verbose=False, **kwargs):
304-
# type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, Union[None, Text]) -> Dict[Text, Text]
305+
# type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, Union[None, Text]) -> Dict[Text, Optional[Text]]
305306
f = dotenv_path or stream or find_dotenv()
306307
return DotEnv(f, verbose=verbose, **kwargs).dict()

src/dotenv/parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def make_regex(string, extra_flags=0):
2020
_export = make_regex(r"(?:export[^\S\r\n]+)?")
2121
_single_quoted_key = make_regex(r"'([^']+)'")
2222
_unquoted_key = make_regex(r"([^=\#\s]+)")
23-
_equal_sign = make_regex(r"[^\S\r\n]*=[^\S\r\n]*")
23+
_equal_sign = make_regex(r"([^\S\r\n]*=[^\S\r\n]*)?")
2424
_single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'")
2525
_double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"')
2626
_unquoted_value_part = make_regex(r"([^ \r\n]*)")
@@ -194,8 +194,8 @@ def parse_binding(reader):
194194
reader.read_regex(_whitespace)
195195
reader.read_regex(_export)
196196
key = parse_key(reader)
197-
reader.read_regex(_equal_sign)
198-
value = parse_value(reader)
197+
(sign,) = reader.read_regex(_equal_sign)
198+
value = parse_value(reader) if sign else None
199199
reader.read_regex(_comment)
200200
reader.read_regex(_end_of_line)
201201
return Binding(

tests/test_parser.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
(u"a='b\\'c'", [Binding(key=u"a", value=u"b'c", original=Original(string=u"a='b\\'c'", line=1))]),
3636
(u"a=à", [Binding(key=u"a", value=u"à", original=Original(string=u"a=à", line=1))]),
3737
(u'a="à"', [Binding(key=u"a", value=u"à", original=Original(string=u'a="à"', line=1))]),
38-
(u'garbage', [Binding(key=None, value=None, original=Original(string=u"garbage", line=1))]),
38+
(u'no_value_var', [Binding(key=u'no_value_var', value=None, original=Original(string=u"no_value_var", line=1))]),
3939
(
4040
u"a=b\nc=d",
4141
[
@@ -87,9 +87,11 @@
8787
],
8888
),
8989
(
90-
u'garbage[%$#\na=b',
90+
u'uglyKey[%$=\"S3cr3t_P4ssw#rD\" #\na=b',
9191
[
92-
Binding(key=None, value=None, original=Original(string=u"garbage[%$#\n", line=1)),
92+
Binding(key=u'uglyKey[%$',
93+
value=u'S3cr3t_P4ssw#rD',
94+
original=Original(string=u"uglyKey[%$=\"S3cr3t_P4ssw#rD\" #\n", line=1)),
9395
Binding(key=u"a", value=u"b", original=Original(string=u'a=b', line=2)),
9496
],
9597
),

0 commit comments

Comments
 (0)