Skip to content
Merged
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
4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ matrix:

- python: "2.7"
env: TOXENV=py27
- python: "3.4"
env: TOXENV=py34
- python: "3.4"
env: TOXENV=py34-no-typing
- python: "3.5"
env: TOXENV=py35
- python: "3.6"
Expand Down
19 changes: 10 additions & 9 deletions src/dotenv/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class DotEnv():
def __init__(self, dotenv_path, verbose=False, encoding=None):
# type: (Union[Text, _PathLike, _StringIO], bool, Union[None, Text]) -> None
self.dotenv_path = dotenv_path # type: Union[Text,_PathLike, _StringIO]
self._dict = None # type: Optional[Dict[Text, Text]]
self._dict = None # type: Optional[Dict[Text, Optional[Text]]]
self.verbose = verbose # type: bool
self.encoding = encoding # type: Union[None, Text]

Expand All @@ -68,7 +68,7 @@ def _get_stream(self):
yield StringIO('')

def dict(self):
# type: () -> Dict[Text, Text]
# type: () -> Dict[Text, Optional[Text]]
"""Return dotenv as dict"""
if self._dict:
return self._dict
Expand All @@ -78,10 +78,10 @@ def dict(self):
return self._dict

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

def set_as_environment_variables(self, override=False):
Expand All @@ -92,7 +92,8 @@ def set_as_environment_variables(self, override=False):
for k, v in self.dict().items():
if k in os.environ and not override:
continue
os.environ[to_env(k)] = to_env(v)
if v is not None:
os.environ[to_env(k)] = to_env(v)

return True

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


def resolve_nested_variables(values):
# type: (Dict[Text, Text]) -> Dict[Text, Text]
# type: (Dict[Text, Optional[Text]]) -> Dict[Text, Optional[Text]]
def _replacement(name):
# type: (Text) -> Text
"""
Expand All @@ -206,7 +207,7 @@ def _replacement(name):
then look into the dotenv variables
"""
ret = os.getenv(name, new_values.get(name, ""))
return ret
return ret # type: ignore

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

for k, v in values.items():
new_values[k] = __posix_variable.sub(_re_sub_callback, v)
new_values[k] = __posix_variable.sub(_re_sub_callback, v) if v is not None else None

return new_values

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


def dotenv_values(dotenv_path=None, stream=None, verbose=False, **kwargs):
# type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, Union[None, Text]) -> Dict[Text, Text]
# type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, Union[None, Text]) -> Dict[Text, Optional[Text]]
f = dotenv_path or stream or find_dotenv()
return DotEnv(f, verbose=verbose, **kwargs).dict()
6 changes: 3 additions & 3 deletions src/dotenv/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def make_regex(string, extra_flags=0):
_export = make_regex(r"(?:export[^\S\r\n]+)?")
_single_quoted_key = make_regex(r"'([^']+)'")
_unquoted_key = make_regex(r"([^=\#\s]+)")
_equal_sign = make_regex(r"[^\S\r\n]*=[^\S\r\n]*")
_equal_sign = make_regex(r"([^\S\r\n]*=[^\S\r\n]*)?")
_single_quoted_value = make_regex(r"'((?:\\'|[^'])*)'")
_double_quoted_value = make_regex(r'"((?:\\"|[^"])*)"')
_unquoted_value_part = make_regex(r"([^ \r\n]*)")
Expand Down Expand Up @@ -194,8 +194,8 @@ def parse_binding(reader):
reader.read_regex(_whitespace)
reader.read_regex(_export)
key = parse_key(reader)
reader.read_regex(_equal_sign)
value = parse_value(reader)
(sign,) = reader.read_regex(_equal_sign)
value = parse_value(reader) if sign else None
reader.read_regex(_comment)
reader.read_regex(_end_of_line)
return Binding(
Expand Down
8 changes: 5 additions & 3 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
(u"a='b\\'c'", [Binding(key=u"a", value=u"b'c", original=Original(string=u"a='b\\'c'", line=1))]),
(u"a=à", [Binding(key=u"a", value=u"à", original=Original(string=u"a=à", line=1))]),
(u'a="à"', [Binding(key=u"a", value=u"à", original=Original(string=u'a="à"', line=1))]),
(u'garbage', [Binding(key=None, value=None, original=Original(string=u"garbage", line=1))]),
(u'no_value_var', [Binding(key=u'no_value_var', value=None, original=Original(string=u"no_value_var", line=1))]),
(
u"a=b\nc=d",
[
Expand Down Expand Up @@ -87,9 +87,11 @@
],
),
(
u'garbage[%$#\na=b',
u'uglyKey[%$=\"S3cr3t_P4ssw#rD\" #\na=b',
[
Binding(key=None, value=None, original=Original(string=u"garbage[%$#\n", line=1)),
Binding(key=u'uglyKey[%$',
value=u'S3cr3t_P4ssw#rD',
original=Original(string=u"uglyKey[%$=\"S3cr3t_P4ssw#rD\" #\n", line=1)),
Binding(key=u"a", value=u"b", original=Original(string=u'a=b', line=2)),
],
),
Expand Down