Skip to content

Commit

Permalink
Fix type hint for dotenv_path var, add StrPath alias (#432)
Browse files Browse the repository at this point in the history
* Fix type hint for load_dotenv

Fixes #431

* Quote type hints to avoid runtime errors in earlier Python versions

* 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

* 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 python/typeshed#6832

* Create a type alias for the paths this library accepts

And use it consistently in main.py.
  • Loading branch information
eaftan authored Jan 11, 2023
1 parent f75103c commit 09cf4ab
Showing 1 changed file with 14 additions and 8 deletions.
22 changes: 14 additions & 8 deletions src/dotenv/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)


Expand All @@ -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: Optional[str] = None,
interpolate: bool = True,
override: bool = True,
) -> None:
self.dotenv_path: Optional[Union[str, os.PathLike]] = dotenv_path
self.dotenv_path: Optional[StrPath] = dotenv_path
self.stream: Optional[IO[str]] = stream
self._dict: Optional[Dict[str, Optional[str]]] = None
self.verbose: bool = verbose
Expand Down Expand Up @@ -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]:
Expand All @@ -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]]]:
if not os.path.isfile(path):
Expand All @@ -139,7 +145,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",
Expand Down Expand Up @@ -188,7 +194,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",
Expand Down Expand Up @@ -303,7 +309,7 @@ def _is_interactive():


def load_dotenv(
dotenv_path: Union[str, os.PathLike, None] = None,
dotenv_path: Optional[StrPath] = None,
stream: Optional[IO[str]] = None,
verbose: bool = False,
override: bool = False,
Expand Down Expand Up @@ -341,7 +347,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,
Expand Down

0 comments on commit 09cf4ab

Please sign in to comment.