Skip to content

Commit 5302b53

Browse files
committed
Update CLI module to support multiple files
1 parent 3c8bb79 commit 5302b53

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

src/dotenv/cli.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,17 @@ def enumerate_env() -> Optional[str]:
3030
try:
3131
cwd = os.getcwd()
3232
except FileNotFoundError:
33-
return None
33+
return ()
3434
path = os.path.join(cwd, ".env")
35-
return path
35+
return (path,)
3636

3737

3838
@click.group()
3939
@click.option(
4040
"-f",
4141
"--file",
4242
default=enumerate_env(),
43+
multiple=True,
4344
type=click.Path(file_okay=True),
4445
help="Location of the .env file, defaults to .env file in current working directory.",
4546
)
@@ -59,9 +60,9 @@ def enumerate_env() -> Optional[str]:
5960
)
6061
@click.version_option(version=__version__)
6162
@click.pass_context
62-
def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None:
63+
def cli(ctx: click.Context, file: List[Any], quote: Any, export: Any) -> None:
6364
"""This script is used to set, get or unset values from a .env file."""
64-
ctx.obj = {"QUOTE": quote, "EXPORT": export, "FILE": file}
65+
ctx.obj = {"QUOTE": quote, "EXPORT": export, "FILES": file}
6566

6667

6768
@contextmanager
@@ -92,10 +93,12 @@ def stream_file(path: os.PathLike) -> Iterator[IO[str]]:
9293
)
9394
def list_values(ctx: click.Context, output_format: str) -> None:
9495
"""Display all the stored key/value."""
95-
file = ctx.obj["FILE"]
96+
files = ctx.obj["FILES"]
9697

97-
with stream_file(file) as stream:
98-
values = dotenv_values(stream=stream)
98+
values = {}
99+
for file in files:
100+
with stream_file(file) as stream:
101+
values.update(dotenv_values(stream=stream))
99102

100103
if output_format == "json":
101104
click.echo(json.dumps(values, indent=2, sort_keys=True))
@@ -115,9 +118,11 @@ def list_values(ctx: click.Context, output_format: str) -> None:
115118
@click.argument("value", required=True)
116119
def set_value(ctx: click.Context, key: Any, value: Any) -> None:
117120
"""Store the given key/value."""
118-
file = ctx.obj["FILE"]
121+
files = ctx.obj["FILES"]
119122
quote = ctx.obj["QUOTE"]
120123
export = ctx.obj["EXPORT"]
124+
125+
file = files[-1]
121126
success, key, value = set_key(file, key, value, quote, export)
122127
if success:
123128
click.echo(f"{key}={value}")
@@ -130,10 +135,12 @@ def set_value(ctx: click.Context, key: Any, value: Any) -> None:
130135
@click.argument("key", required=True)
131136
def get(ctx: click.Context, key: Any) -> None:
132137
"""Retrieve the value for the given key."""
133-
file = ctx.obj["FILE"]
138+
files = ctx.obj["FILES"]
134139

135-
with stream_file(file) as stream:
136-
values = dotenv_values(stream=stream)
140+
values = {}
141+
for file in files:
142+
with stream_file(file) as stream:
143+
values.update(dotenv_values(stream=stream))
137144

138145
stored_value = values.get(key)
139146
if stored_value:
@@ -147,9 +154,10 @@ def get(ctx: click.Context, key: Any) -> None:
147154
@click.argument("key", required=True)
148155
def unset(ctx: click.Context, key: Any) -> None:
149156
"""Removes the given key."""
150-
file = ctx.obj["FILE"]
157+
files = ctx.obj["FILES"]
151158
quote = ctx.obj["QUOTE"]
152-
success, key = unset_key(file, key, quote)
159+
for file in files:
160+
success, key = unset_key(file, key, quote)
153161
if success:
154162
click.echo(f"Successfully removed {key}")
155163
else:
@@ -172,14 +180,17 @@ def unset(ctx: click.Context, key: Any) -> None:
172180
@click.argument("commandline", nargs=-1, type=click.UNPROCESSED)
173181
def run(ctx: click.Context, override: bool, commandline: tuple[str, ...]) -> None:
174182
"""Run command with environment variables present."""
175-
file = ctx.obj["FILE"]
176-
if not os.path.isfile(file):
177-
raise click.BadParameter(
178-
f"Invalid value for '-f' \"{file}\" does not exist.", ctx=ctx
179-
)
183+
files = ctx.obj["FILES"]
184+
for file in files:
185+
if not os.path.isfile(file):
186+
raise click.BadParameter(
187+
f"Invalid value for '-f' \"{file}\" does not exist.", ctx=ctx
188+
)
189+
180190
dotenv_as_dict = {
181191
k: v
182-
for (k, v) in dotenv_values(file).items()
192+
for file in files
193+
for k, v in dotenv_values(file).items()
183194
if v is not None and (override or k not in os.environ)
184195
}
185196

0 commit comments

Comments
 (0)