Skip to content
This repository was archived by the owner on Feb 11, 2023. It is now read-only.

Commit a4339b0

Browse files
committed
Fixes #161 -- is_default and has_value take into consideration value override set via environment variables
1 parent b5c405d commit a4339b0

5 files changed

Lines changed: 60 additions & 15 deletions

File tree

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 1.32.0
2+
current_version = 1.32.1
33
commit = true
44
tag = false
55

configmanager/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = '1.32.0'
1+
__version__ = '1.32.1'
22

33
from .managers import Config
44
from .items import Item

configmanager/items.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -175,23 +175,38 @@ def default(self, value):
175175
return
176176
self._default = self.type.deserialize(value)
177177

178+
def _get_envvar_value(self):
179+
"""
180+
Internal helper to get item value from an environment variable
181+
if item is controlled by one, and if the variable is set.
182+
183+
Returns not_set otherwise.
184+
"""
185+
envvar_name = None
186+
187+
if self.envvar is True:
188+
envvar_name = self.envvar_name
189+
if envvar_name is None:
190+
envvar_name = '_'.join(self.get_path()).upper()
191+
elif self.envvar:
192+
envvar_name = self.envvar
193+
194+
if envvar_name and envvar_name in os.environ:
195+
return self.type.deserialize(os.environ[envvar_name])
196+
else:
197+
return not_set
198+
178199
def get(self, fallback=not_set):
179200
"""
180201
Returns config value.
181202
182203
See Also:
183204
:meth:`.set` and :attr:`.value`
184205
"""
185-
if self.envvar:
186-
if self.envvar is True:
187-
envvar_name = self.envvar_name
188-
if envvar_name is None:
189-
envvar_name = '_'.join(self.get_path()).upper()
190-
if envvar_name in os.environ:
191-
return self.type.deserialize(os.environ[envvar_name])
192-
else:
193-
if self.envvar in os.environ:
194-
return self.type.deserialize(os.environ[self.envvar])
206+
207+
envvar_value = self._get_envvar_value()
208+
if envvar_value is not not_set:
209+
return envvar_value
195210

196211
if self.has_value:
197212
if self._value is not not_set:
@@ -268,15 +283,26 @@ def reset(self):
268283
def is_default(self):
269284
"""
270285
``True`` if the item's value is its default value or if no value and no default value are set.
286+
287+
If the item is backed by an environment variable, this will be ``True`` only
288+
if the environment variable is set and is different to the
289+
default value of the item.
271290
"""
272-
return self._value is not_set or self._value == self.default
291+
envvar_value = self._get_envvar_value()
292+
if envvar_value is not not_set:
293+
return envvar_value == self.default
294+
else:
295+
return self._value is not_set or self._value == self.default
273296

274297
@property
275298
def has_value(self):
276299
"""
277300
``True`` if item has a default value or custom value set.
278301
"""
279-
return self.default is not not_set or self._value is not not_set
302+
if self._get_envvar_value() is not not_set:
303+
return True
304+
else:
305+
return self.default is not not_set or self._value is not not_set
280306

281307
@property
282308
def section(self):

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ Similarly to reading, you find the appropriate persistence adapter, and use the
119119
120120
config.json.dump('~/.config/helloworld/config.json', with_defaults=True)
121121
122-
Unless you also pass ``with_defaults=True``, ::dump:: will not include items who don't have a custom value set.
122+
Unless you also pass ``with_defaults=True``, ``dump`` will exclude values for items who have no custom value set.
123123

124124
How do I export all configuration values to a dictionary?
125125
---------------------------------------------------------

tests/test_item.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@ def test_is_default():
254254
assert e.is_default
255255

256256

257+
def test_is_default_respects_envvar(monkeypatch):
258+
a = Item('a', default=5, envvar=True)
259+
assert a.is_default
260+
261+
monkeypatch.setenv('A', '5')
262+
assert a.is_default
263+
264+
monkeypatch.setenv('A', '6')
265+
assert not a.is_default
266+
267+
257268
def test_has_value_returns_true_if_value_or_default_is_set():
258269
c = Item()
259270
assert not c.has_value
@@ -277,6 +288,14 @@ def test_has_value_returns_true_if_value_or_default_is_set():
277288
assert not e.has_value
278289

279290

291+
def test_has_value_respects_envvar(monkeypatch):
292+
a = Item('a', envvar=True, type=int)
293+
assert not a.has_value
294+
295+
monkeypatch.setenv('A', '5')
296+
assert a.has_value
297+
298+
280299
def test_type_is_guessed_either_from_default_or_value():
281300
c = Item()
282301
assert c.type is Types.str

0 commit comments

Comments
 (0)