Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support reading/loading multiple .env files #424

Open
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

duarte-pompeu
Copy link

@duarte-pompeu duarte-pompeu commented Sep 10, 2022

This PR allows reading from multiple .env files in the dotenv CLI, specifically the targets get, list and run.

This will allow users to have a big .env file with default configs, and smaller ones which only incremental changes - therefore removing the burden of repeating unchanged key-values.

The goal for the new behavior is as follows:

  • files are processed in order
  • new keys lead to creating new key-values
  • repeated keys lead to overriding previous values

Extra remarks:

  • this PR preserves the behavior of working with single files, and falling back to .env when no file is specified
  • this PR forbids write operations on multiple files, specifically set and unset

Example:

$ echo -e 'URL="https://www.example.com"\nUSER="user"\nPASSWORD="secret"' > .env1
$ echo -e 'USER="admin"\nPASSWORD="admin"' > .env2
$ python -m dotenv -f .env1 -f .env2 list
PASSWORD=admin
URL=https://www.example.com
USER=admin

Ideas for the future:

  • also allow loading multiple .env files from the code, eg load_dotenv(f1, f2, ...)
  • also allow setting and unsetting values for multiple .env files

Relates to #418 .

@duarte-pompeu duarte-pompeu changed the title Load multiple .env file (WIP) feat: multiple .env file (WIP) Sep 10, 2022
@duarte-pompeu duarte-pompeu changed the title feat: multiple .env file (WIP) feat: support multiple .env files (WIP) Sep 10, 2022
@duarte-pompeu duarte-pompeu changed the title feat: support multiple .env files (WIP) feat: support multiple .env files Sep 10, 2022
Copy link
Author

@duarte-pompeu duarte-pompeu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be improved

src/dotenv/cli.py Outdated Show resolved Hide resolved
src/dotenv/cli.py Outdated Show resolved Hide resolved
src/dotenv/cli.py Outdated Show resolved Hide resolved
tests/test_main.py Outdated Show resolved Hide resolved
src/dotenv/cli.py Outdated Show resolved Hide resolved
Copy link
Author

@duarte-pompeu duarte-pompeu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double checked

in cli.py we may use multiple files and getting multiple errors
but want to avoid multiple errors if at least one file
has the key
src/dotenv/main.py Outdated Show resolved Hide resolved
@pheanex
Copy link

pheanex commented Dec 4, 2023

@duarte-pompeu will you take care of resolving the conflicts before we ping the maintainer for review?

@duarte-pompeu
Copy link
Author

I can give it a try tonight, it would be interesting to merge this feature.

@duarte-pompeu
Copy link
Author

Solved conflicts but there's still some work to do regarding failing tests.

@duarte-pompeu
Copy link
Author

Think it looks better now @pheanex 🙂

It's missing more tests and documentation, but I'd prefer to have feedback from a maintainer before tackling those.

@pheanex
Copy link

pheanex commented Dec 5, 2023

Awesome! Let's see if @bbc2 or @theskumar is available for a quick review?

@theskumar
Copy link
Owner

Fundamentally as feature I'm good with supporting this. I like your approach and seeing how you are going about it. I haven't had time to look into the implementation details. But I feel free to improve on your implementation. Would really appreciate keeping it backward compatible. Thank you @duarte-pompeu for your contribution.

@duarte-pompeu
Copy link
Author

Thanks for the feedback @theskumar. I can keep working on this over the next days.

I'm thinking about reducing the scope in this PR though - would it be OK to only support read operations, such as get and list? Seems like a useful increment and later we can think about how to handle write operations.

@theskumar
Copy link
Owner

Read is completely fine, I could not see how the write be extended to multiple files. Would be curious if you have some ideas around it.

@theskumar theskumar changed the title feat: support multiple .env files feat: support reading/loading multiple .env files Dec 7, 2023
@duarte-pompeu
Copy link
Author

duarte-pompeu commented Dec 8, 2023

Read is completely fine, I could not see how the write be extended to multiple files. Would be curious if you have some ideas around it.

Actually I already implemented it: unset looks for the key in all files and deletes it when present. But I have some doubts about this usefulness, or if this behavior is intuitive to users - as such, I'd rather remove it from this PR and discuss it later.

Example as of 49c34a5:

$ for f in $(ls .env*); do echo $f; cat $f; echo; done
.env1
a=1
b=2
.env2
b=2
c=3
# unset 'a', which is only present in .env1
$ python -m dotenv -f .env1 -f .env2 unset a
Successfully removed a from .env1.
$ for f in $(ls .env*); do echo $f; cat $f; echo; done
.env1
b=2
.env2
b=2
c=3
# unset 'b', which is present in both .env1 and .env2
$ python -m dotenv -f .env1 -f .env2 unset b
Successfully removed b from ['.env1', '.env2'].
$ for f in (ls .env*); do echo $f; cat $f; echo; done
.env1
.env2
c=3
# try to unset key which does not exist
$ python -m dotenv -f .env1 -f .env2 unset d
Key d not removed from ('.env1', '.env2') - key doesn't exist.

dotenv_path.write_text(contents[0] + '\n')
extra_dotenv_path.write_text(contents[1] + '\n')

args = ['--file', dotenv_path, '--file', extra_dotenv_path, 'list']
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I omitted tests with multiple formatting because that seems to me like a separate concern - if the variables are loaded correctly, the formatting behavior shouldn't change.

Do you agree?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. This is fine.

@duarte-pompeu
Copy link
Author

I think this is ready for review @theskumar:

  • implemented changes
  • kept backward compatibility (I think so, someone please double check for peace of mind 😃)
  • added tests
  • updated docs
  • improved PR description

We didn't talk about this, but I only implemented this for the CLI utility. If there's interest to also enable this behavior from the library code, I'm up to contribute to it (but would prefer to have it in a separate PR, as I find this one already useful as is).

@duarte-pompeu
Copy link
Author

Hi @theskumar and @pheanex , any feedback?

@pheanex
Copy link

pheanex commented Dec 17, 2023

Lgtm. Looking forward to this ☺️👍

@theskumar
Copy link
Owner

theskumar commented Dec 21, 2023

@duarte-pompeu thanks for all the hard work. Unfortunately, I've had not been able to review this yet. Looks like we Christmas 🎄 break would be a good time to taking care of it for me, along with few more pull requests.

@duarte-pompeu
Copy link
Author

@duarte-pompeu thanks for all the hard work. Unfortunately, I've had not been able to review this yet. Looks like we Christmas 🎄 break would be a good time to taking care of it for me, along with few more pull requests.

Cool, I also have some free time now so it would also work for me 😃

a=1
b=20
c=30
```
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@duarte-pompeu Consider document the precedence/loading order values from the of the files. I didn't see a test but based on the this example it seems the .env2 overrides the previous value from .env1.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree: it's important to document this. I chose an overriding behavior, as my use case would be:

  • have a big file with all values
  • have smaller .env files with specific values to override in certain situations

I tried to improve it on 363aab5

README.md Outdated
@@ -3,7 +3,7 @@
[![Build Status][build_status_badge]][build_status_link]
[![PyPI version][pypi_badge]][pypi_link]

Python-dotenv reads key-value pairs from a `.env` file and can set them as environment
Python-dotenv reads key-value pairs from `.env` files and can set them as environment
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm hesitant to change this yet as the core/python API, doesn't support reading from multiple files.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I agree it makes sense to only document this in the CLI section.

Resolved in 1d33b6a

@duarte-pompeu
Copy link
Author

Hi @theskumar , I agree with your feedback and addressed in the last commits. What do you think?

@pheanex
Copy link

pheanex commented Jan 12, 2024

@theskumar any chance to take a quick look again?

@pheanex
Copy link

pheanex commented Mar 5, 2024

@bbc2 any chance you can take a look at this? It seems @theskumar is currently unavailable.

Copy link
Collaborator

@bbc2 bbc2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with this (we might be opening Pandora's box but so be it) and it looks like you addressed all the concerns raised previously, so if no one objects for a few more days I'll go ahead and merge it. Thank you for your contribution!

@pheanex
Copy link

pheanex commented Mar 27, 2024

@bbc2 as two more weeks have passed: Are we good to move forward with this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants