Skip to content

Commit d93324a

Browse files
techalchemybbc2
authored andcommitted
Make typing optional (theskumar#179)
- Fall back to `collections.namedtuple` for `Binding` when typing is not present - Add import guards to all imports - Fixes theskumar#178 - Add missing coverage config to setup.cfg
1 parent b7759b7 commit d93324a

7 files changed

Lines changed: 57 additions & 15 deletions

File tree

MANIFEST.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
include LICENSE *.md *.yml
1+
include LICENSE *.md *.yml *.toml
22

33
include tox.ini
44
recursive-include tests *.py

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ source =
3333

3434
[coverage:report]
3535
show_missing = True
36+
exclude_lines =
37+
if IS_TYPE_CHECKING:
38+
pragma: no cover

src/dotenv/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
from typing import Any, Optional # noqa
1+
from .compat import IS_TYPE_CHECKING
22
from .main import load_dotenv, get_key, set_key, unset_key, find_dotenv, dotenv_values
33

4+
if IS_TYPE_CHECKING:
5+
from typing import Any, Optional
6+
47

58
def load_ipython_extension(ipython):
69
# type: (Any) -> None

src/dotenv/cli.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import os
22
import sys
33
from subprocess import Popen
4-
from typing import Any, Dict, List # noqa
54

65
try:
76
import click
@@ -10,9 +9,13 @@
109
'Run pip install "python-dotenv[cli]" to fix this.')
1110
sys.exit(1)
1211

12+
from .compat import IS_TYPE_CHECKING
1313
from .main import dotenv_values, get_key, set_key, unset_key
1414
from .version import __version__
1515

16+
if IS_TYPE_CHECKING:
17+
from typing import Any, List, Dict
18+
1619

1720
@click.group()
1821
@click.option('-f', '--file', default=os.path.join(os.getcwd(), '.env'),

src/dotenv/compat.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import sys
2-
from typing import Text # noqa
32

43
PY2 = sys.version_info[0] == 2 # type: bool
54

@@ -9,6 +8,22 @@
98
from io import StringIO # noqa
109

1110

11+
def is_type_checking():
12+
# type: () -> bool
13+
try:
14+
from typing import TYPE_CHECKING
15+
except ImportError: # pragma: no cover
16+
return False
17+
return TYPE_CHECKING
18+
19+
20+
IS_TYPE_CHECKING = is_type_checking()
21+
22+
23+
if IS_TYPE_CHECKING:
24+
from typing import Text
25+
26+
1227
def to_env(text):
1328
# type: (Text) -> str
1429
"""

src/dotenv/main.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@
77
import shutil
88
import sys
99
import tempfile
10-
from typing import (Dict, Iterator, List, Match, Optional, # noqa
11-
Pattern, Union, TYPE_CHECKING, Text, IO, Tuple)
1210
import warnings
1311
from collections import OrderedDict
1412
from contextlib import contextmanager
1513

16-
from .compat import StringIO, PY2, to_env
14+
from .compat import StringIO, PY2, to_env, IS_TYPE_CHECKING
1715
from .parser import parse_stream
1816

19-
if TYPE_CHECKING: # pragma: no cover
17+
if IS_TYPE_CHECKING:
18+
from typing import (
19+
Dict, Iterator, Match, Optional, Pattern, Union, Text, IO, Tuple
20+
)
2021
if sys.version_info >= (3, 6):
2122
_PathLike = os.PathLike
2223
else:
@@ -278,7 +279,8 @@ def load_dotenv(dotenv_path=None, stream=None, verbose=False, override=False, **
278279
- *dotenv_path*: absolute or relative path to .env file.
279280
- *stream*: `StringIO` object with .env content.
280281
- *verbose*: whether to output the warnings related to missing .env file etc. Defaults to `False`.
281-
- *override*: where to override the system environment variables with the variables in `.env` file. Defaults to `False`.
282+
- *override*: where to override the system environment variables with the variables in `.env` file.
283+
Defaults to `False`.
282284
"""
283285
f = dotenv_path or stream or find_dotenv()
284286
return DotEnv(f, verbose=verbose, **kwargs).set_as_environment_variables(override=override)

src/dotenv/parser.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import codecs
22
import re
3-
from typing import (IO, Iterator, Match, NamedTuple, Optional, Pattern, # noqa
4-
Sequence, Text)
53

6-
from .compat import to_text
4+
from .compat import to_text, IS_TYPE_CHECKING
5+
6+
7+
if IS_TYPE_CHECKING:
8+
from typing import ( # noqa:F401
9+
IO, Iterator, Match, NamedTuple, Optional, Pattern, Sequence, Text,
10+
Tuple
11+
)
712

813

914
def make_regex(string, extra_flags=0):
@@ -25,9 +30,20 @@ def make_regex(string, extra_flags=0):
2530
_double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]")
2631
_single_quote_escapes = make_regex(r"\\[\\']")
2732

28-
Binding = NamedTuple("Binding", [("key", Optional[Text]),
29-
("value", Optional[Text]),
30-
("original", Text)])
33+
34+
try:
35+
# this is necessary because we only import these from typing
36+
# when we are type checking, and the linter is upset if we
37+
# re-import
38+
import typing
39+
Binding = typing.NamedTuple("Binding", [("key", typing.Optional[typing.Text]),
40+
("value", typing.Optional[typing.Text]),
41+
("original", typing.Text)])
42+
except ImportError: # pragma: no cover
43+
from collections import namedtuple
44+
Binding = namedtuple("Binding", ["key", # type: ignore
45+
"value",
46+
"original"]) # type: Tuple[Optional[Text], Optional[Text], Text]
3147

3248

3349
class Error(Exception):

0 commit comments

Comments
 (0)