Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions dotenv/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from .compat import StringIO

__escape_decoder = codecs.getdecoder('unicode_escape')
__posix_variable = re.compile('\$\{[^\}]*\}')
__posix_variable = re.compile(r'\$\{[^\}]*\}')


def decode_escaped(escaped):
Expand Down Expand Up @@ -78,12 +78,17 @@ def dict(self):
def parse(self):
f = self._get_stream()

for line in f:
key, value = parse_line(line)
if not key:
continue

yield key, value
fbody = f.read()
# key starts with either `export FOO`, or `FOO`
key = r'^(?:export )?([a-zA-Z_][a-zA-Z0-9_]+)'
# `=` may be padded with spaces
eql = r' *= *'
# val is either wrapped in quotes, or a string of non-white-space chars
val = r'(?:\'(.*?)\'|"(.*?)"|([^\s]+))'
envs = re.findall(key + eql + val, fbody, re.MULTILINE | re.DOTALL)
for env in envs:
# Yield the key and the first non-empty val
yield env[0], next(x for x in env[1:] if x)

if self._is_file:
f.close()
Expand Down
5 changes: 4 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ bumpversion
wheel
pytest-cov
click
ipython
jedi<0.13; python_version <= '3.3'
ipython<6; python_version <= '2'
ipython<7; python_version <= '3.3'
ipython; python_version > '3.3'
pypandoc
13 changes: 13 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import tempfile
from os import environ
from os.path import dirname, join

Expand Down Expand Up @@ -95,6 +96,18 @@ def test_value_with_special_characters():
sh.rm(dotenv_path)


def test_multiline_value():
with tempfile.NamedTemporaryFile() as f:
f.write("TEST='line 1\nline 2'".encode('utf-8'))
f.flush()
assert dotenv.get_key(f.name, 'TEST') == "line 1\nline 2"

with tempfile.NamedTemporaryFile() as f:
f.write("TEST='line 1\nline 2'\nFIZZ=BUZZ".encode('utf-8'))
f.flush()
assert dotenv.get_key(f.name, 'TEST') == "line 1\nline 2"


def test_unset():
sh.touch(dotenv_path)
success, key_to_set, value_to_set = dotenv.set_key(dotenv_path, 'HELLO', 'WORLD')
Expand Down