Skip to content

Commit

Permalink
Fix read_env recursive bug (#370)
Browse files Browse the repository at this point in the history
* fix: 🐛 fix always recursive behavior on read_env

* fix: 🐛 prevent UnboundLocalError

* Improve test reliability; add test with no .env in cwd

* Return None if return_path=True and .env not found; improve test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update changelog

---------

Co-authored-by: Steven Loria <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 20, 2024
1 parent a873df3 commit 9d1ff82
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 11.2.1 (unreleased)

Bug fixes:

- Fix `Env.read_env(recurse=True)` so that it returns as soon as a `.env`
file is found ([#370](https://github.com/sloria/environs/pull/370)).
Thanks [senese](https://github.com/senese) for the PR.

## 11.2.0 (2024-11-14)

Features:
Expand Down
6 changes: 4 additions & 2 deletions src/environs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,15 +454,15 @@ def read_env(
verbose: _BoolType = False,
override: _BoolType = False,
return_path: _BoolType = False,
) -> typing.Union[_BoolType, _StrType]:
) -> typing.Union[_BoolType, typing.Optional[_StrType]]:
"""Read a .env file into os.environ.
If .env is not found in the directory from which this method is called,
the default behavior is to recurse up the directory tree until a .env
file is found. If you do not wish to recurse up the tree, you may pass
False as a second positional argument.
"""

env_path = None
is_env_loaded = False
if path is None:
# By default, start search from the same directory this function is called
Expand All @@ -488,6 +488,8 @@ def read_env(
check_path, verbose=verbose, override=override
)
env_path = str(check_path)
break

else:
is_env_loaded = load_dotenv(str(start), verbose=verbose, override=override)
env_path = str(start)
Expand Down
27 changes: 27 additions & 0 deletions tests/test_environs.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,33 @@ def test_read_env_return_path(self, env):
env_path = str(HERE / ".env")
assert path == env_path

def test_read_env_return_path_with_dotenv_in_working_dir(self, env):
working_dir = pathlib.Path(os.getcwd())
temp_env = working_dir / ".env"
try:
# Create an empty .env file in working dir
temp_env.touch()
path = env.read_env(return_path=True)
finally:
if temp_env.exists():
temp_env.unlink()

env_path = str(HERE / ".env")
assert path == env_path

def test_read_env_return_path_if_env_not_found(self, env, tmp_path):
# Move .env file to temp location
env_path = HERE / ".env"
temp_env = tmp_path / ".env"
try:
env_path.rename(temp_env)
path = env.read_env(return_path=True)
assert path is None
finally:
# Restore .env file
if temp_env.exists():
temp_env.rename(env_path)


def always_fail(value):
raise environs.EnvError("something went wrong")
Expand Down

0 comments on commit 9d1ff82

Please sign in to comment.