Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

delattr on class instance produces unexpected AttributeError

I have the following abstract base class for configuration implementation (cut short):

class Config():
    """
    Configuration file binding
    """   
    def __init__(self, path):
        """
        Initialize the config file
        """
        path = path if path.endswith(self.__SUFFIX) else path + self.__SUFFIX
        self.__file = ConfigFile(path)
        self.__defaults = self.dict()

    @property    
    def fields(self):
        """
        Returns a list of fields
        """
        return [field for field in self.dict()]

    def dict(self):
        """
        Determine existing fields
        """
        return {field:getattr(self, field) 
                for field in dir(self) 
                if field.upper() == field 
                and not field.startswith('_')}

    def reset(self):
        """
        Reset the file to the default values
        """
        self.__clear()
        return self.__load(self.__defaults)

    def __load(self, d):
        """
        Load data from file
        """
        for field in d:
            if field.upper() == field:
                setattr(self, field, self.__decode(d[field]))

    def __clear(self):
        """
        Remove all fields
        """
        print('My fields: ', end='')    # XXX: Debug
        print(self.fields)  # XXX: Debug
        print('My attributes: ', end='')    # XXX: Debug
        print(dir(self))    # XXX: Debug
        for field in self.fields:
            print('Removing field: ' + field)
            delattr(self, field)

    <SNIP>

This is being implemented by my program's system-wide configuration:

class __Sysconfig(Config):
    """
    H.O.M.I.E.'s system configuration
    """
    ### Application information ###
    APP_NAME = 'H.O.M.I.E.'
    APP_VER = '0.1-indev'
    APP_FULL_NAME = "Cool system"

    ### System logging ###
    LOG_DIR = '/var/log/homie.d'
    LOGFILE = '/var/log/homie'
    LOGLVL = 2

    ### System files ###
    DAEMON_SERVICES_FILE = '/var/run/homie.services'
    DAEMON_SOCK = 'tcp://127.0.0.1'
    GLOBAL_CONFIG_DIR = '/usr/local/etc/homie.d'

    ### System EMail ###
    EMAIL_FROM = '[email protected]'
    TECH_EMAIL = '[email protected]'
    ADMIN_EMAILS = ['[email protected]', '[email protected]']

    def __init__(self):
        """
        Creates a sysconfig instance
        """
        super().__init__('/usr/local/etc/homie')

Which then is initialized by:

sysconfig = __Sysconfig()
sysconfig.reset()

This, however, produces the following error (With printouts from Config() for debugging):

My fields: ['EMAIL_FROM', 'APP_VER', 'LOG_DIR', 'GLOBAL_CONFIG_DIR', 'TECH_EMAIL', 'DAEMON_SERVICES_FILE', 'ADMIN_EMAILS', 'APP_NAME', 'LOGFILE', 'APP_FULL_NAME', 'DAEMON_SOCK', 'LOGLVL']
My attributes: ['ADMIN_EMAILS', 'APP_FULL_NAME', 'APP_NAME', 'APP_VER', 'DAEMON_SERVICES_FILE', 'DAEMON_SOCK', 'EMAIL_FROM', 'GLOBAL_CONFIG_DIR', 'LOGFILE', 'LOGLVL', 'LOG_DIR', 'TECH_EMAIL', '_Config__SUFFIX', '_Config__TYPES', '_Config__clear', '_Config__decode', '_Config__defaults', '_Config__encode', '_Config__file', '_Config__lbi', '_Config__lei', '_Config__load', '_Config__ls', '_Config__ts', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'dict', 'exists', 'fields', 'lbi', 'lei', 'load', 'loaded', 'ls', 'reload', 'remove', 'reset', 'store', 'ts']
Removing field: EMAIL_FROM
Traceback (most recent call last):
  File "/etc/init.d/retard", line 3, in <module>
    from homie.init import __main__
  File "/usr/lib/python3.4/site-packages/homie/init/__main__.py", line 20, in <module>
    from ..api import Customer, Service
  File "/usr/lib/python3.4/site-packages/homie/api/__init__.py", line 12, in <module>
    from .abc import CAC
  File "/usr/lib/python3.4/site-packages/homie/api/abc.py", line 14, in <module>
    from ..homie import sysconfig
  File "/usr/lib/python3.4/site-packages/homie/homie.py", line 50, in <module>
    sysconfig.reset()
  File "/usr/lib/python3.4/site-packages/homie/lib/config.py", line 114, in reset
    self.__clear()
  File "/usr/lib/python3.4/site-packages/homie/lib/config.py", line 159, in __clear
    delattr(self, field)
AttributeError: EMAIL_FROM

Why does delattr() does not find the attribute?

like image 605
Richard Neumann Avatar asked Feb 13 '23 09:02

Richard Neumann


1 Answers

When defining the subclass __Sysconfig(Config), python obviously binds the attributes to the class. The instance self can access them, but not delete them.

Changing delattr(self, field) to delattr(self.__class__, field) did the trick!

like image 200
Richard Neumann Avatar answered May 10 '23 09:05

Richard Neumann