theskumar / python-dotenv

Reads key-value pairs from a .env file and can set them as environment variables. It helps in developing applications following the 12-factor principles.
https://saurabh-kumar.com/python-dotenv/
BSD 3-Clause "New" or "Revised" License
7.7k stars 431 forks source link

Export multiline variable #518

Closed aphilas closed 2 months ago

aphilas commented 5 months ago

The description for --export says "Whether to write the dot file as executable bash script."

However, if I used the --export flag with a multiline variable, the output cannot be correctly parsed by bash.

For example:

# .env
TEST_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDcRcBc/es9fD1s\nsvWIerF1c8BAqDbkoX9A1KF7uZLXTj90MEDoSAgZ6c8Q77A/DAZtIxS5ip6lG6RN\ncfz0JUrN9wQgjiFAUtvqfP74LXm7fG9iz8DUMoCBkQLsefVK2z/bG4Uul/fvTLjM\nPCef7jyertafr+x5F3QrGsAOC9pX28d40g1xW6JtLbQR6++4kfKtS7/D+WFdqqw7=\n-----END PRIVATE KEY-----\n"
$ dotenv -f ./.env -e 1 list
TEST_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDcRcBc/es9fD1s
svWIerF1c8BAqDbkoX9A1KF7uZLXTj90MEDoSAgZ6c8Q77A/DAZtIxS5ip6lG6RN
cfz0JUrN9wQgjiFAUtvqfP74LXm7fG9iz8DUMoCBkQLsefVK2z/bG4Uul/fvTLjM
PCef7jyertafr+x5F3QrGsAOC9pX28d40g1xW6JtLbQR6++4kfKtS7/D+WFdqqw7=
-----END PRIVATE KEY-----
$ eval $(dotenv -f ./.env -e 1 list)
bash: command not found: PRIVATE

Is this expected?

Alternatives workarounds I am aware of:

Bajron commented 5 months ago

I think the help message is indeed a little unfortunate. After browsing the code, it seems the --export or -e is used only during the set operation. It prefixes the variable with the export keyword.

To make you example work try providing --format shell or --format export to the list command. For example eval $(dotenv -f ./.env list --format shell)

Check out this short bash session to figure out what happens when:

# -e adds "export" during "set" operation
dotenv -e 1 set ML "1
2
3"

cat .env
bash -c 'source .env' # bash can handle the format

# simple list
dotenv list
# can be handled by shell
dotenv list --format shell
# can be handled by shell, exports variables
dotenv list --format export

# eval and echo
eval $(dotenv list --format shell)
echo ML: $ML

# eval and echo with changed IFS to see the newlines
OLDIFS=$IFS
IFS=:
eval $(dotenv list --format shell)
echo ML: $ML
IFS=$OLDIFS
aphilas commented 2 months ago

Thank you!

I must've not taken enough time to read help. Just checked dotenv --help. dotenv list --help would have clarified this (unless it's new).

$ dotenv --help
Usage: dotenv [OPTIONS] COMMAND [ARGS]...

  This script is used to set, get or unset values from a .env file.

Options:
  -f, --file PATH                 Location of the .env file, defaults to
                                  .env file in current working directory.
  -q, --quote [always|never|auto]
                                  Whether to quote or not the variable
                                  values. Default mode is always. This does
                                  not affect parsing.
  -e, --export BOOLEAN            Whether to write the dot file as an
                                  executable bash script.
  --version                       Show the version and exit.
  --help                          Show this message and exit.

Commands:
  get    Retrieve the value for the given key.
  list   Display all the stored key/value.
  run    Run command with environment variables present.
  set    Store the given key/value.
  unset  Removes the given key.
$ dotenv list --help
Usage: dotenv list [OPTIONS]

  Display all the stored key/value.

Options:
  --format [simple|json|shell|export]
                                  The format in which to display the list.
                                  Default format is simple, which displays
                                  name=value without quotes.
  --help                          Show this message and exit.