diff --git a/README.md b/README.md index 77cc7ff4..4458cb5f 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,8 @@ DATABASE_PASSWORD = os.getenv("DATABASE_PASSWORD") `load_dotenv` do not override existing System environment variables. To override, pass `override=True` to `load_dotenv()`. +`load_dotenv` also accepts `encoding` parameter to open the `.env` file. The default encoding is platform dependent (whatever `locale.getpreferredencoding()` returns), but any encoding supported by Python can be used. See the [codecs](https://docs.python.org/3/library/codecs.html#standard-encodings) module for the list of supported encodings. + You can use `find_dotenv()` method that will try to find a `.env` file by (a) guessing where to start using `__file__` or the working directory -- allowing this to work in non-file contexts such as IPython notebooks @@ -298,6 +300,7 @@ Unreleased ----- - Add type hints and expose them to users ([@qnighy])([#172]) +- `load_dotenv` and `dotenv_values` now accepts `encoding` paramater, defaults to `None` ([@theskumar])([@earlbread]) (#161) 0.10.1 ----- @@ -409,6 +412,7 @@ Unreleased [@hugochinchilla](https://github.com/hugochinchilla)). - Improved test coverage. +[#161]: https://github.com/theskumar/python-dotenv/issues/161 [#78]: https://github.com/theskumar/python-dotenv/issues/78 [#148]: https://github.com/theskumar/python-dotenv/issues/148 [#158]: https://github.com/theskumar/python-dotenv/issues/158 @@ -423,3 +427,4 @@ Unreleased [@cjauvin]: https://github.com/cjauvin [@bbc2]: https://github.com/bbc2 [@qnighy]: https://github.com/qnighy +[@earlbread]: https://github.com/earlbread diff --git a/src/dotenv/main.py b/src/dotenv/main.py index c1c36226..715a08e2 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -111,11 +111,12 @@ def parse_stream(stream): class DotEnv(): - def __init__(self, dotenv_path, verbose=False): - # type: (Union[Text, _PathLike, _StringIO], bool) -> None + 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.verbose = verbose # type: bool + self.encoding = encoding # type: Union[None, Text] @contextmanager def _get_stream(self): @@ -123,7 +124,7 @@ def _get_stream(self): if isinstance(self.dotenv_path, StringIO): yield self.dotenv_path elif os.path.isfile(self.dotenv_path): - with io.open(self.dotenv_path) as stream: + with io.open(self.dotenv_path, encoding=self.encoding) as stream: yield stream else: if self.verbose: @@ -349,16 +350,16 @@ def find_dotenv(filename='.env', raise_error_if_not_found=False, usecwd=False): return '' -def load_dotenv(dotenv_path=None, stream=None, verbose=False, override=False): - # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, bool) -> bool +def load_dotenv(dotenv_path=None, stream=None, verbose=False, override=False, **kwargs): + # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, bool, Union[None, Text]) -> bool f = dotenv_path or stream or find_dotenv() - return DotEnv(f, verbose=verbose).set_as_environment_variables(override=override) + return DotEnv(f, verbose=verbose, **kwargs).set_as_environment_variables(override=override) -def dotenv_values(dotenv_path=None, stream=None, verbose=False): - # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool) -> Dict[Text, Text] +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] f = dotenv_path or stream or find_dotenv() - return DotEnv(f, verbose=verbose).dict() + return DotEnv(f, verbose=verbose, **kwargs).dict() def run_command(command, env):