From da4c0e208d39a639960ef6ad41c41cc570796977 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Sat, 28 Feb 2026 21:51:06 -0300 Subject: [PATCH 01/11] perf: use ChainMap in resolve_variables to avoid redundant dict copies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matheus Virgolino Co-authored-by: Manoel Netto Co-authored-by: Pedro Co-authored-by: Lucaslg7 Co-authored-by: RailtonDantas Co-authored-by: João Pereira --- src/dotenv/main.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 491634d9..5f6d8bc9 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -6,6 +6,7 @@ import sys import tempfile from collections import OrderedDict +from collections import ChainMap from contextlib import contextmanager from typing import IO, Dict, Iterable, Iterator, Mapping, Optional, Tuple, Union @@ -292,18 +293,16 @@ def resolve_variables( ) -> Mapping[str, Optional[str]]: new_values: Dict[str, Optional[str]] = {} + if override: + env = ChainMap(new_values,os.environ) + else: + env = ChainMap(os.environ,new_values) + for name, value in values: if value is None: result = None else: atoms = parse_variables(value) - env: Dict[str, Optional[str]] = {} - if override: - env.update(os.environ) # type: ignore - env.update(new_values) - else: - env.update(new_values) - env.update(os.environ) # type: ignore result = "".join(atom.resolve(env) for atom in atoms) new_values[name] = result From 93439895c9eb3fa4a1ba6176e31d4037d3068c09 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Tue, 3 Mar 2026 19:44:28 -0300 Subject: [PATCH 02/11] docs(python-dotenv): describe resolve_variables method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matheus Virgolino Co-authored-by: Manoel Netto Co-authored-by: Pedro Co-authored-by: Lucaslg7 Co-authored-by: RailtonDantas Co-authored-by: João Pereira --- src/dotenv/main.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 5f6d8bc9..5447c64e 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -291,6 +291,12 @@ def resolve_variables( values: Iterable[Tuple[str, Optional[str]]], override: bool, ) -> Mapping[str, Optional[str]]: + """ + Resolve interpolated variables from a .env file, + iterating over tuples with pairs that represent the key and value of each variable in the .env file. + + If override is True, .env variables take priority over system environment variables. + """ new_values: Dict[str, Optional[str]] = {} if override: From cfdc7e57a6b9c5ee429f3a25d8c4c6d51fc450a2 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Wed, 11 Mar 2026 23:19:01 -0300 Subject: [PATCH 03/11] style: merge collections imports into single line --- src/dotenv/main.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 5447c64e..4c3f4074 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -5,8 +5,7 @@ import stat import sys import tempfile -from collections import OrderedDict -from collections import ChainMap +from collections import ChainMap, OrderedDict from contextlib import contextmanager from typing import IO, Dict, Iterable, Iterator, Mapping, Optional, Tuple, Union From f3a1b2fa50f475ba8af0400d989bee19d344df66 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Wed, 11 Mar 2026 23:33:38 -0300 Subject: [PATCH 04/11] style: apply ruff formatting to main.py --- src/dotenv/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 4c3f4074..95e2b7c7 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -299,9 +299,9 @@ def resolve_variables( new_values: Dict[str, Optional[str]] = {} if override: - env = ChainMap(new_values,os.environ) + env = ChainMap(new_values, os.environ) else: - env = ChainMap(os.environ,new_values) + env = ChainMap(os.environ, new_values) for name, value in values: if value is None: From 51aa9b8f2c34630b77f3dca468a9b123bf8f3228 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Wed, 11 Mar 2026 23:38:17 -0300 Subject: [PATCH 05/11] style: add type comment to ChainMap assignments in resolve_variables --- src/dotenv/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 95e2b7c7..1a88934f 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -299,9 +299,9 @@ def resolve_variables( new_values: Dict[str, Optional[str]] = {} if override: - env = ChainMap(new_values, os.environ) + env = ChainMap(new_values, os.environ) # type: ChainMap[str, Optional[str]] else: - env = ChainMap(os.environ, new_values) + env = ChainMap(os.environ, new_values) # type: ChainMap[str, Optional[str]] for name, value in values: if value is None: From 4cdda2e250d4f5cf8b2c69e76290d1037b8ca966 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Wed, 11 Mar 2026 23:41:07 -0300 Subject: [PATCH 06/11] style: fix unecessary space --- src/dotenv/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 1a88934f..94171852 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -299,7 +299,7 @@ def resolve_variables( new_values: Dict[str, Optional[str]] = {} if override: - env = ChainMap(new_values, os.environ) # type: ChainMap[str, Optional[str]] + env = ChainMap(new_values, os.environ) # type: ChainMap[str, Optional[str]] else: env = ChainMap(os.environ, new_values) # type: ChainMap[str, Optional[str]] From 5c5db9616999d6e9825c3eebad8b686ff5a6865c Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Wed, 11 Mar 2026 23:45:38 -0300 Subject: [PATCH 07/11] style: fix space problem --- src/dotenv/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 94171852..9d31a88a 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -299,9 +299,9 @@ def resolve_variables( new_values: Dict[str, Optional[str]] = {} if override: - env = ChainMap(new_values, os.environ) # type: ChainMap[str, Optional[str]] + env = ChainMap(new_values, os.environ) # type: ChainMap[str, Optional[str]] else: - env = ChainMap(os.environ, new_values) # type: ChainMap[str, Optional[str]] + env = ChainMap(os.environ, new_values) # type: ChainMap[str, Optional[str]] for name, value in values: if value is None: From 738a47f7673ab48c53162f0cfa5f19a988bd52d3 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Wed, 11 Mar 2026 23:57:30 -0300 Subject: [PATCH 08/11] style: fix ruff problems --- src/dotenv/main.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 9d31a88a..b4734a55 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -285,7 +285,6 @@ def unset_key( return removed, key_to_unset - def resolve_variables( values: Iterable[Tuple[str, Optional[str]]], override: bool, @@ -298,10 +297,11 @@ def resolve_variables( """ new_values: Dict[str, Optional[str]] = {} - if override: - env = ChainMap(new_values, os.environ) # type: ChainMap[str, Optional[str]] - else: - env = ChainMap(os.environ, new_values) # type: ChainMap[str, Optional[str]] + env: ChainMap[str, Optional[str]] = ( + ChainMap(new_values, os.environ) # type: ignore + if override + else ChainMap(os.environ, new_values) # type: ignore + ) for name, value in values: if value is None: @@ -314,7 +314,6 @@ def resolve_variables( return new_values - def _walk_to_root(path: str) -> Iterator[str]: """ Yield directories starting from the given directory up to the root From 03a4ee947db1198d08e132c4546e90bf36666e14 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Thu, 12 Mar 2026 00:01:00 -0300 Subject: [PATCH 09/11] style: add breakline after unset_key() --- src/dotenv/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index b4734a55..2cd2851b 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -285,6 +285,7 @@ def unset_key( return removed, key_to_unset + def resolve_variables( values: Iterable[Tuple[str, Optional[str]]], override: bool, @@ -314,6 +315,7 @@ def resolve_variables( return new_values + def _walk_to_root(path: str) -> Iterator[str]: """ Yield directories starting from the given directory up to the root From e7ca8b39af583d35a99ccaacf1c80ba28596392e Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Thu, 12 Mar 2026 00:55:03 -0300 Subject: [PATCH 10/11] style: fix ruff problems --- .editorconfig | 17 ----------------- src/dotenv/main.py | 1 + 2 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index e2764043..00000000 --- a/.editorconfig +++ /dev/null @@ -1,17 +0,0 @@ -# see: http://editorconfig.org - -root = true - -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -[*.{py,rst,ini}] -indent_style = space -indent_size = 4 - -[*.yml] -indent_style = space -indent_size = 2 diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 2cd2851b..20cea84d 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -296,6 +296,7 @@ def resolve_variables( If override is True, .env variables take priority over system environment variables. """ + #test new_values: Dict[str, Optional[str]] = {} env: ChainMap[str, Optional[str]] = ( From 1f1ba01eb85b27902f7970346cc8b76896823858 Mon Sep 17 00:00:00 2001 From: RailtonDantas Date: Thu, 12 Mar 2026 00:56:50 -0300 Subject: [PATCH 11/11] style: fix ruff problems --- src/dotenv/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotenv/main.py b/src/dotenv/main.py index 20cea84d..e8b9fa81 100644 --- a/src/dotenv/main.py +++ b/src/dotenv/main.py @@ -296,7 +296,7 @@ def resolve_variables( If override is True, .env variables take priority over system environment variables. """ - #test + # test new_values: Dict[str, Optional[str]] = {} env: ChainMap[str, Optional[str]] = (