Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ $ dotenv set EMAIL [email protected]
$ dotenv list
USER=foo
[email protected]
$ dotenv list --format=json
{
"USER": "foo",
"EMAIL": "[email protected]"
}
$ dotenv run -- python foo.py
```

Expand Down
20 changes: 17 additions & 3 deletions src/dotenv/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import json
import os
import shlex
import sys
from subprocess import Popen
from typing import Any, Dict, List
Expand Down Expand Up @@ -36,7 +38,11 @@ def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None:

@cli.command()
@click.pass_context
def list(ctx: click.Context) -> None:
@click.option('--format', default='simple',
type=click.Choice(['simple', 'json', 'shell', 'export']),
help="The format in which to display the list. Default format is simple, "
"which displays name=value without quotes.")
def list(ctx: click.Context, format: bool) -> None:
'''Display all the stored key/value.'''
file = ctx.obj['FILE']
if not os.path.isfile(file):
Expand All @@ -45,8 +51,16 @@ def list(ctx: click.Context) -> None:
ctx=ctx
)
dotenv_as_dict = dotenv_values(file)
for k, v in dotenv_as_dict.items():
click.echo('%s=%s' % (k, v))
if format == 'json':
click.echo(json.dumps(dotenv_as_dict, indent=2, sort_keys=True))
else:
prefix = 'export ' if format == 'export' else ''
for k in sorted(dotenv_as_dict):
v = dotenv_as_dict[k]
if v is not None:
if format in ('export', 'shell'):
v = shlex.quote(v)
click.echo('%s%s=%s' % (prefix, k, v))


@cli.command()
Expand Down
29 changes: 24 additions & 5 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,38 @@

import pytest
import sh

from typing import Optional
import dotenv
from dotenv.cli import cli as dotenv_cli
from dotenv.version import __version__


def test_list(cli, dotenv_file):
@pytest.mark.parametrize(
"format,content,expected",
(
(None, "x='a b c'", '''x=a b c\n'''),
("simple", "x='a b c'", '''x=a b c\n'''),
("simple", """x='"a b c"'""", '''x="a b c"\n'''),
("simple", '''x="'a b c'"''', '''x='a b c'\n'''),
("json", "x='a b c'", '''{\n "x": "a b c"\n}\n'''),
("shell", "x='a b c'", "x='a b c'\n"),
("shell", """x='"a b c"'""", '''x='"a b c"'\n'''),
("shell", '''x="'a b c'"''', '''x=''"'"'a b c'"'"''\n'''),
("shell", "x='a\nb\nc'", "x='a\nb\nc'\n"),
("export", "x='a b c'", '''export x='a b c'\n'''),
)
)
def test_list(cli, dotenv_file, format: Optional[str], content: str, expected: str):
with open(dotenv_file, "w") as f:
f.write("a=b")
f.write(content + '\n')

args = ['--file', dotenv_file, 'list']
if format is not None:
args.extend(['--format', format])

result = cli.invoke(dotenv_cli, ['--file', dotenv_file, 'list'])
result = cli.invoke(dotenv_cli, args)

assert (result.exit_code, result.output) == (0, result.output)
assert (result.exit_code, result.output) == (0, expected)


def test_list_non_existent_file(cli):
Expand Down