Skip to content

Commit

Permalink
fix: postpone() now gives a more descriptive error when being accessed
Browse files Browse the repository at this point in the history
  • Loading branch information
robinvandernoord committed Dec 4, 2023
1 parent 42cac45 commit da69257
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
26 changes: 24 additions & 2 deletions src/configuraptor/postpone.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
File contains logic to do with the 'postpone' feature.
"""

from typing import Any
from typing import Any, Optional

from typing_extensions import Never

Expand All @@ -15,6 +15,23 @@ class Postponed(Singleton):
Class returned by `postpone` below.
"""

def __get_property_name__(self, instance: type[Any], owner: type[Any]) -> Optional[str]:
"""
Internal method to get the property name of the class this descriptor is being used on.
"""
if not instance: # pragma: no cover
return None

# instance: the instance the descriptor is accessed from
# owner: the class that owns the descriptor
property_name = None
for attr_name, attr_value in owner.__dict__.items():
if attr_value is self:
property_name = attr_name
break
# return instance.__dict__.get(property_name, None)
return property_name

def __get__(self, instance: type[Any], owner: type[Any]) -> Never:
"""
This magic method is called when a property is accessed.
Expand All @@ -26,7 +43,12 @@ def __get__(self, instance: type[Any], owner: type[Any]) -> Never:
instance: the class on which the postponed property is defined,
owner: `SingletonMeta`
"""
raise IsPostponedError()
msg = f"Err: Using postponed property on {owner.__name__}"

if name := self.__get_property_name__(instance, owner):
msg += f".{name}"

raise IsPostponedError(msg)


def postpone() -> Any:
Expand Down
6 changes: 5 additions & 1 deletion tests/test_postponed.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ def test_postponed_can_be_filled_later():

# later.other_field should throw an error
with pytest.raises(IsPostponedError):
print(later.other_field)
try:
print(later.other_field)
except IsPostponedError as e:
assert "Later.other_field" in str(e)
raise e

later.update()

Expand Down

0 comments on commit da69257

Please sign in to comment.