Coverage for src/configuraptor/postpone.py: 100%
18 statements
« prev ^ index » next coverage.py v7.2.7, created at 2026-05-01 17:14 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2026-05-01 17:14 +0200
1"""
2File contains logic to do with the 'postpone' feature.
3"""
5from typing import Any, Never, Optional
7from .errors import IsPostponedError
8from .singleton import Singleton
11class Postponed(Singleton):
12 """
13 Class returned by `postpone` below.
14 """
16 def __get_property_name__(self, instance: type[Any], owner: type[Any]) -> Optional[str]:
17 """
18 Internal method to get the property name of the class this descriptor is being used on.
19 """
20 if not instance: # pragma: no cover
21 return None
23 # instance: the instance the descriptor is accessed from
24 # owner: the class that owns the descriptor
25 property_name = None
26 for attr_name, attr_value in owner.__dict__.items():
27 if attr_value is self:
28 property_name = attr_name
29 break
30 # return instance.__dict__.get(property_name, None)
31 return property_name
33 def __get__(self, instance: type[Any], owner: type[Any]) -> Never:
34 """
35 This magic method is called when a property is accessed.
37 Example:
38 someclass.someprop will trigger the __get__ of `someprop`
40 Args:
41 instance: the class on which the postponed property is defined,
42 owner: `SingletonMeta`
43 """
44 msg = f"Err: Using postponed property on {owner.__name__}"
46 if name := self.__get_property_name__(instance, owner):
47 msg += f".{name}"
49 raise IsPostponedError(msg)
52def postpone() -> Any:
53 """
54 Can be used to mark a property as postponed, meaning the user will fill it in later (they promose).
56 If they don't fill it in and still try to use it, they will be met with a IsPostponedError.
57 """
58 return Postponed()