Reengineered decorator to accept JSON to Python attributes mapping.

This commit is contained in:
2025-11-02 17:22:15 +01:00
parent ce38e275a9
commit deed075727

View File

@@ -6,26 +6,49 @@ DEVOPS_SCOPE = "https://app.vssps.visualstudio.com/.default"
DEVOPS_API_VERSION = "7.1" DEVOPS_API_VERSION = "7.1"
# Define a class decorator # Define a class decorator
def auto_properties(names=None): def auto_properties(mapping: dict[str,str] | None = None):
names = names or []
def make_property(name): def make_property(name: str):
private_var = f"_{name}" private_var = f"_{name}"
def getter(self): def getter(self):
try:
i = getattr(self, private_var) i = getattr(self, private_var)
if i is not None: if i is not None:
return i return i
# Fetch repository details from the API except AttributeError:
pass
# Fetch repository details from the API if it is set to None or not existing
self._get(getattr(self, "_id")) self._get(getattr(self, "_id"))
return getattr(self, private_var) return getattr(self, private_var)
return property(getter) return property(fget=getter)
def set_auto_properties(self, **kwargs):
allowed = set(self.__class__.__auto_properties__)
unknown = [k for k in kwargs if k not in allowed]
if unknown:
raise ValueError(f"Unknown properties for {self.__class__.__name__}: {', '.join(unknown)}")
for k, v in kwargs.items():
setattr(self, f"_{k}", v)
return self
def from_json(self, json_data: dict):
for name in self.__class__.__auto_properties__:
setattr(self, f"_{name}", json_data.get(self.__class__.__auto_properties__[name], None))
return self
def decorator(cls): def decorator(cls):
cls.__auto_properties__ = names cls.__auto_properties__ = mapping # Make a copy of the mapping
for name in names:
# Create properties dynamically
for name in mapping:
setattr(cls, name, make_property(name)) setattr(cls, name, make_property(name))
setattr(cls, "set_auto_properties", set_auto_properties)
setattr(cls, "from_json", from_json)
return cls return cls
return decorator return decorator