From 6e2a2878df2a66770c72dad8937b242a40a7f7fa Mon Sep 17 00:00:00 2001 From: eaftan Date: Thu, 20 Oct 2022 16:25:41 -0700 Subject: [PATCH 1/6] Fix type hint for load_dotenv Fixes #431 --- src/dotenv/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 83ea3239..da1e91ac 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -305,7 +305,7 @@ def _is_interactive(): def load_dotenv( - dotenv_path: Union[str, os.PathLike, None] = None, + dotenv_path: Union[str, os.PathLike[str], os.PathLike[bytes], None] = None, stream: Optional[IO[str]] = None, verbose: bool = False, override: bool = False, From 3982ba5a9fe05bc05ebef6430efd47fa7b8cbe5e Mon Sep 17 00:00:00 2001 From: eaftan Date: Thu, 20 Oct 2022 16:51:31 -0700 Subject: [PATCH 2/6] Quote type hints to avoid runtime errors in earlier Python versions --- src/dotenv/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index da1e91ac..fcb604fa 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -305,7 +305,7 @@ def _is_interactive(): def load_dotenv( - dotenv_path: Union[str, os.PathLike[str], os.PathLike[bytes], None] = None, + dotenv_path: Union[str, 'os.PathLike[str]', 's.PathLike[bytes]', None] = None, stream: Optional[IO[str]] = None, verbose: bool = False, override: bool = False, From 787fd20a2a9be807c2f65a3882c96a8da15b5950 Mon Sep 17 00:00:00 2001 From: eaftan Date: Thu, 20 Oct 2022 16:55:15 -0700 Subject: [PATCH 3/6] Fix typo --- src/dotenv/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index fcb604fa..145210e6 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -305,7 +305,7 @@ def _is_interactive(): def load_dotenv( - dotenv_path: Union[str, 'os.PathLike[str]', 's.PathLike[bytes]', None] = None, + dotenv_path: Union[str, 'os.PathLike[str]', 'os.PathLike[bytes]', None] = None, stream: Optional[IO[str]] = None, verbose: bool = False, override: bool = False, From 979b36b71c33249dd2e129ac27a3543b00ad3b40 Mon Sep 17 00:00:00 2001 From: eaftan Date: Tue, 10 Jan 2023 15:15:46 -0800 Subject: [PATCH 4/6] Revise type of dotenv_path parameter Based on PR feedback and typeshed's type hint for the built-in open() function: https://github.com/python/typeshed/blob/e2d67bf7034f68c07bd35150247e58e0817725d9/stdlib/builtins.pyi#L1421 --- src/dotenv/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 145210e6..1126a537 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -305,7 +305,7 @@ def _is_interactive(): def load_dotenv( - dotenv_path: Union[str, 'os.PathLike[str]', 'os.PathLike[bytes]', None] = None, + dotenv_path: Optional[Union[str, bytes, 'os.PathLike[Union[str, bytes]]', int]] = None, stream: Optional[IO[str]] = None, verbose: bool = False, override: bool = False, From 183e59e91cb133f066d20ba138055cea1a114dc7 Mon Sep 17 00:00:00 2001 From: eaftan Date: Tue, 10 Jan 2023 15:48:11 -0800 Subject: [PATCH 5/6] Allow only string paths, not byte paths These paths can flow into `shutil.move`, which does not accept byte paths or (int) file descriptors. See https://github.com/python/typeshed/pull/6832 --- src/dotenv/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 1126a537..fc3a99af 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -305,7 +305,7 @@ def _is_interactive(): def load_dotenv( - dotenv_path: Optional[Union[str, bytes, 'os.PathLike[Union[str, bytes]]', int]] = None, + dotenv_path: Optional[Union[str, 'os.PathLike[str]']] = None, stream: Optional[IO[str]] = None, verbose: bool = False, override: bool = False, From a709ba06b882ac3a393c687b8788acd6564890a3 Mon Sep 17 00:00:00 2001 From: eaftan Date: Tue, 10 Jan 2023 15:11:14 -0800 Subject: [PATCH 6/6] Create a type alias for the paths this library accepts And use it consistently in main.py. --- src/dotenv/main.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index fc3a99af..678b808d 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -12,6 +12,12 @@ from .parser import Binding, parse_stream from .variables import parse_variables +# A type alias for a string path to be used for the paths in this file. +# These paths may flow to `open()` and `shutil.move()`; `shutil.move()` +# only accepts string paths, not byte paths or file descriptors. See +# https://github.com/python/typeshed/pull/6832. +StrPath = Union[str, 'os.PathLike[str]'] + logger = logging.getLogger(__name__) @@ -28,14 +34,14 @@ def with_warn_for_invalid_lines(mappings: Iterator[Binding]) -> Iterator[Binding class DotEnv(): def __init__( self, - dotenv_path: Optional[Union[str, os.PathLike]], + dotenv_path: Optional[StrPath], stream: Optional[IO[str]] = None, verbose: bool = False, encoding: Union[None, str] = None, interpolate: bool = True, override: bool = True, ) -> None: - self.dotenv_path = dotenv_path # type: Optional[Union[str, os.PathLike]] + self.dotenv_path = dotenv_path # type: Optional[StrPath] self.stream = stream # type: Optional[IO[str]] self._dict = None # type: Optional[Dict[str, Optional[str]]] self.verbose = verbose # type: bool @@ -108,7 +114,7 @@ def get(self, key: str) -> Optional[str]: def get_key( - dotenv_path: Union[str, os.PathLike], + dotenv_path: StrPath, key_to_get: str, encoding: Optional[str] = "utf-8", ) -> Optional[str]: @@ -122,7 +128,7 @@ def get_key( @contextmanager def rewrite( - path: Union[str, os.PathLike], + path: StrPath, encoding: Optional[str], ) -> Iterator[Tuple[IO[str], IO[str]]]: try: @@ -141,7 +147,7 @@ def rewrite( def set_key( - dotenv_path: Union[str, os.PathLike], + dotenv_path: StrPath, key_to_set: str, value_to_set: str, quote_mode: str = "always", @@ -190,7 +196,7 @@ def set_key( def unset_key( - dotenv_path: Union[str, os.PathLike], + dotenv_path: StrPath, key_to_unset: str, quote_mode: str = "always", encoding: Optional[str] = "utf-8", @@ -305,7 +311,7 @@ def _is_interactive(): def load_dotenv( - dotenv_path: Optional[Union[str, 'os.PathLike[str]']] = None, + dotenv_path: Optional[StrPath] = None, stream: Optional[IO[str]] = None, verbose: bool = False, override: bool = False, @@ -343,7 +349,7 @@ def load_dotenv( def dotenv_values( - dotenv_path: Union[str, os.PathLike, None] = None, + dotenv_path: Optional[StrPath] = None, stream: Optional[IO[str]] = None, verbose: bool = False, interpolate: bool = True,