Package: advanced-descriptors
Advanced descriptorsThis package includes helpers for special cases:SeparateClassMethod- allow to have classmethod and normal method both with the same name.AdvancedProperty- property with possibility to set class wide getter.LogOnAccess- property with logging on successful get/set/delete or failure.SeparateClassMethodThis descriptor can be set using standard decorator syntax.
Create instance with arguments:defimeth(instance):returninstance.valuedefcmeth(owner):returnowner.valueclassTarget(object):value=1def__init__(self):self.value=2getval=advanced_descriptors.SeparateClassMethod(imeth,cmeth)Create instance wrapping as decorator:classTarget(object):value=1def__init__(self):self.value=2@advanced_descriptors.SeparateClassMethoddefgetval(self):returnself.value@getval.class_methoddefgetval(cls):returncls.valueCases with method only and classmethod only is useless:
method as-is and@classmethodshould be used in corresponding cases.Noteclassmethod receives class as argument. IDE’s don’t know about custom descriptors and substitutesselfby default.AdvancedPropertyThis descriptor should be used in cases, when in addition to normal property API, class getter is required.
If class-wide setter and deleter also required - you should use standard propery in metaclass.Usage examples:In addition to normal property API:classTarget(object):_value=777def__init__(self):self._value=42@advanced_descriptors.AdvancedPropertydefval(self):returnself._value@val.setterdefval(self,value):self._value=value@val.deleterdefval(self):self._value=0@val.cgetterdefval(cls):returncls._valueUse class-wide getter for instance too:classTarget(object):_value=1val=advanced_descriptors.AdvancedProperty()@val.cgetterdefval(cls):returncls._valueNoteclass-wide getter receives class as argument. IDE’s don’t know about custom descriptors and substitutesselfby default.LogOnAccessThis special case of property is useful in cases, where a lot of properties should be logged by similar way without writing a lot of code.Basic API is conform withproperty, but in addition it is possible to customize logger, log levels and log conditions.Usage examples:Simple usage.
All by default.
logger is re-used from instance if available with namesloggerorlogelse used internaladvanced_descriptors.log_on_accesslogger:importloggingclassTarget(object):definit(self,val='ok')self.val=valself.logger=logging.get_logger(self.__class__.__name__)# Single for class, follow subclassingdef__repr__(self):return"{cls}(val={self.val})".format(cls=self.__class__.__name__,self=self)@advanced_descriptors.LogOnAccessdefok(self):returnself.val@ok.setterdefok(self,val):self.val=val@ok.deleterdefok(self):self.val=""Use with global logger for class:classTarget(object):definit(self,val='ok')self.val=valdef__repr__(self):return"{cls}(val={self.val})".format(cls=self.__class__.__name__,self=self)@advanced_descriptors.LogOnAccessdefok(self):returnself.val@ok.setterdefok(self,val):self.val=val@ok.deleterdefok(self):self.val=""ok.logger='test_logger'ok.log_level=logging.INFOok.exc_level=logging.ERRORok.log_object_repr=True# As by defaultok.log_success=True# As by defaultok.log_failure=True# As by defaultok.log_traceback=True# As by defaultok.override_name=None# As by default: use original nameTestingThe main test mechanism for the packageadvanced-descriptorsis usingtox.
Available environments can be collected viatox -lCI systemsFor CI/CD GitHub actions is used:GitHub actions:is used for checking: PEP8, pylint, bandit, installation possibility and unit tests.