From d0762cf36a395af1b39b18b70da07c1727d3812a Mon Sep 17 00:00:00 2001 From: dirkf Date: Wed, 4 Oct 2023 01:09:29 +0100 Subject: [PATCH] [utils] Add `classpropinit()` decorator for easier use of inherited class vars --- youtube_dl/utils.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index ddec962f4..fb2fa41a4 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -6540,3 +6540,33 @@ class classproperty(object): elif cls not in self._cache: self._cache[cls] = self.func(cls) return self._cache[cls] + + +class classpropinit(classproperty): + """ A Python fubar: parent class vars are not in scope when the + `class suite` is evaluated, so disallowing `childvar = fn(parentvar)`. + Instead, the parent class has to be mentioned redundantly and + unmaintainably, since the current class isn't yet bound. + This decorator evaluates a class method and assigns its result + in place of the method. + + class child(parent): + # before + childvar = fn(parent.parentvar) + # now + @classpropinit + def childvar(cls): + return fn(cls.parentvar) + # or + childvar = classpropinit(lambda cls: fn(cls.parentvar)) + """ + + def __init__(self, func): + functools.update_wrapper(self, func) + self.name = func.__name__ + self.func = func + + def __get__(self, _, cls): + val = self.func(cls) + setattr(cls, self.name, val) + return val