Default Values and Config File Class using wxPyton and dictionaries

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • bartonc
    Recognized Expert Expert
    • Sep 2006
    • 6478

    Default Values and Config File Class using wxPyton and dictionaries

    For those of you who have never used the *listofargs and **dictofargs syntax, here is a look at the latter. By using **kwargs, a dictionary of any size is sent into the fuction as dict(a=1, b=2). Inside the function, it's just a dictionary named kwargs (or whaterver, but this is conventional). The truly amazing thing to me is that I am able to write to the Windows registry with so little interface!

    Code:
    """Encapuslate a Default Values Object and Config File"""
    
    from inspect import getmembers
    import wx
    
    class DefaultValueHolder(object):
        """Intended for use with wxConfig (or maybe _winreg) to set up and/or get
           registry key names and values. Name attrs as default*. "default"
           will be stripped of when reading and writing to the config file"""
    ##    defaultTestStr = "this is a test"
    ##    defaultTestInt = 1
    
        def __init__(self, appName, grpName):
            """The name of the config file that will be created"""
            self.appName = appName          # if the key doesn't exit, it will be created
            self.grpName = grpName          # same goes for groups.
            self.config = wx.Config(appName) # Open the file (HKCU in windows registry)
    
        def GetVariables(self):
            return [{"name":var[0][7:], "value":var[1], "type":type(var[1])}
                    for var in getmembers(self) if var[0].startswith('default')]
    
        def SetVariables(self, **kwargs):
            for name, value in kwargs.items():
                setattr(self, "default" + name, value)
    
        def InitFromConfig(self):
            self.config.SetPath(self.grpName)
            for var in self.GetVariables():
                if var['type'] == str:
                    self.config.Write(var['name'], var['value'])
                elif var['type'] == int:
                    self.config.WriteInt(var['name'], var['value'])
                elif var['type'] == float:
                    self.config.WriteFloat(var['name'], var['value'])
    
    
    if __name__ == "__main__":
        test = DefaultValueHolder("MyAppName", "Database")
    
        test.SetVariables(UserName = "joe", Password = "", ServerName = "MyServer")
        #### this also works:
        ## test.defaultUserName = "joe"
    
        test.InitFromConfig()
  • bartonc
    Recognized Expert Expert
    • Sep 2006
    • 6478

    #2
    Ok- it was a little more complicated that I initially thought, but not much.
    Here's the final version. GetVariables() uses a "list comprehension" to return a list of dictionaries. comprehensions are nifty little list builders which avoid list.append() calls if you don't have lots of stuff going on in your loop. Sometimes, loops with append() are called for, however. Generators look a lot like comprehensions but don't actually make the list in memory until you assign it something ie:
    a, b = (i for i in range(2))
    also very handy.

    Code:
    """Encapuslate a Default Values Object and Config File"""
    
    from inspect import getmembers
    import wx
    
    class DefaultValueHolder(object):
        """Intended for use with wxConfig (or maybe _winreg) to set up and/or get
           registry key names and values. Name attrs as default*. "default"
           will be stripped of when reading and writing to the config file"""
    
        def __init__(self, appName, grpName):
            """Open or create the application key"""
            self.grpName = grpName  # if the key or group doesn't exit, it will be created
            self.config = wx.Config(appName)     # Open the file (HKCU in windows registry)
    
        def GetVariables(self):
            return [{"name":var[0][7:], "value":var[1], "type":type(var[1])}
                    for var in getmembers(self) if var[0].startswith('default')]
    
        def SetVariables(self, varDict={}, **kwargs):
            kwargs.update(varDict)
            for name, value in kwargs.items():
                setattr(self, "default" + name, value)
    
        def InitFromConfig(self):
            config = self.config
            group = self.grpName
    
            if not config.Exists(group):
                self.WriteRegistryGroup(Group)
                return
    
            config.SetPath(group)
            for var in self.GetVariables():
                name = var['name']
                print name, "exists"
                if config.Exists(name):
                    value = self.ReadRegistry(name, var['type'])
                    self.SetVariables({name:value})
                else:
                    self.WriteRegistry(name, var['value'], var['type'])
            config.SetPath("")
    
        def UpdateConfig(self):
            self.WriteRegistryGroup(self.grpName)
    
        def WriteRegistryGroup(self, group):
            self.config.SetPath(group)
            for var in self.GetVariables():
                self.WriteRegistry(var['name'], var['value'], var['type'])
            self.config.SetPath("")
    
        def ReadRegistry(self, name, type):
            value = None
            if type == str:
                value = self.config.Read(name)
            elif type in (int, long):
                value = self.config.ReadInt(name)
            elif type == float:
                value = self.config.ReadFloat(name)
            return value
    
        def WriteRegistry(self, name, value, type):
            print "writing registry", name, value, type
            if type == str:
                self.config.Write(name, value)
            elif type in (int, long):
                self.config.WriteInt(name, value)
            elif type == float:
                self.config.WriteFloat(name, value)
    
    
    if __name__ == "__main__":
        test = DefaultValueHolder("HETAP Pro 2.00", "Database")
        test.SetVariables(UserName = "barton", Password = "", ServerName = "MyServer", database="trails")
        test.InitFromConfig()
        print test.GetVariables()
    
    ##    #### this also works:
    ##    ## test.defaultUserName = "joe"
    ##
    Last edited by bartonc; Dec 11 '06, 09:20 AM. Reason: fixed bug pointed out by bv in reply

    Comment

    • bvdet
      Recognized Expert Specialist
      • Oct 2006
      • 2851

      #3
      Good AM Barton! Thanks for sharing this code. It looks nicely structured and well thought out. I have one question though. Where/how is the below method and its argument defined?
      Code:
              if not config.Exists(group):
                  self.[b][U][I]WriteRegistryGroup[/I][/U][/b](Group)
                  return
      Thanks again Barton. Learning about new things is always interesting if not fun!

      Comment

      • bartonc
        Recognized Expert Expert
        • Sep 2006
        • 6478

        #4
        Originally posted by bvdet
        Good AM Barton! Thanks for sharing this code. It looks nicely structured and well thought out. I have one question though. Where/how is the below method and its argument defined?
        Code:
                if not config.Exists(group):
                    self.[b][U][I]WriteRegistryGroup[/I][/U][/b](Group)
                    return
        Thanks again Barton. Learning about new things is always interesting if not fun!
        Hay! This system works! Fresh eyes see bugs! Since those entries do exist, on my system (not on a fresh installation) that call never got made, so I never got an errror. Thanks, BV. I have edited the original.

        Comment

        • bvdet
          Recognized Expert Specialist
          • Oct 2006
          • 2851

          #5
          Originally posted by bartonc
          Hay! This system works! Fresh eyes see bugs! Since those entries do exist, on my system (not on a fresh installation) that call never got made, so I never got an errror. Thanks, BV. I have edited the original.
          You were just testing us, weren't you Barton? :)

          Comment

          • bartonc
            Recognized Expert Expert
            • Sep 2006
            • 6478

            #6
            Originally posted by bvdet
            You were just testing us, weren't you Barton? :)
            THIS is the test: It didn't actually work! I Fixed it though... three lines:

            Code:
                def SetVariables(self, varDict={}, **kwargs):
                    kwargs.update(varDict)
            
            
            # in InitFromConfig...
                            self.SetVariables({name:value})

            Comment

            • true911m
              New Member
              • Dec 2006
              • 92

              #7
              Originally posted by bartonc
              THIS is the test: It didn't actually work! I Fixed it though... three lines:

              Code:
                  def SetVariables(self, varDict={}, **kwargs):
                      kwargs.update(varDict)
              
              
              # in InitFromConfig...
                              self.SetVariables({name:value})
              Barton,

              I'm a little unsteady about this last patch...

              In 'InitFromConfig ", does "self.SetVariab les(...)" replace "self.WriteRegi stryGroup(Group )"?

              Trying to store the final final away for future reference. :)

              Thanks.

              Comment

              • bartonc
                Recognized Expert Expert
                • Sep 2006
                • 6478

                #8
                Here it is in it's entirety. Sorry about the confussion.

                Code:
                """Encapuslate a Default Values Object and Config File"""
                
                from inspect import getmembers
                import wx
                
                class DefaultValueHolder(object):
                    """Intended for use with wxConfig (or maybe _winreg) to set up and/or get
                       registry key names and values. Name attrs as default*. "default"
                       will be stripped of when reading and writing to the config file.
                       You may not use the name varDict as one of the variable names."""
                
                    def __init__(self, appName, grpName):
                        """Open or create the application key"""
                        self.appName = appName
                        self.grpName = grpName  # if the key or group doesn't exit, it will be created
                        self.config = wx.Config(appName)     # Open the file (HKCU in windows registry)
                
                    def GetVariables(self):
                        return [{"name":var[0][7:], "value":var[1], "type":type(var[1])}
                                for var in getmembers(self) if var[0].startswith('default')]
                
                    def SetVariables(self, varDict={}, **kwargs):
                        kwargs.update(varDict)
                        for name, value in kwargs.items():
                            setattr(self, ("default" + name), value)
                
                    def InitFromConfig(self):
                        config = self.config
                        group = self.grpName
                
                        if not config.Exists(group):
                            self.WriteRegistryGroup(group)
                
                        else:
                            config.SetPath(group)
                            for var in self.GetVariables():
                                name = var['name']
                                if config.Exists(name):
                                    value = self.ReadRegistry(name, var['type'])
                                    self.SetVariables({name:value})
                                else:
                                    self.WriteRegistry(name, var['value'], var['type'])
                        config.SetPath("")
                
                    def WriteRegistryGroup(self, group):
                        self.config.SetPath(group)
                        for var in self.GetVariables():
                            self.WriteRegistry(var['name'], var['value'], var['type'])
                        self.config.SetPath("")
                
                    def UpdateConfig(self):
                        self.WriteRegistryGroup(self.grpName)
                
                    def ReadRegistry(self, name, type):
                        value = None
                        if type == str:
                            value = self.config.Read(name)
                        elif type in (int, long):
                            value = self.config.ReadInt(name)
                        elif type == float:
                            value = self.config.ReadFloat(name)
                        return value
                
                    def WriteRegistry(self, name, value, type):
                        if type == str:
                            self.config.Write(name, value)
                        elif type in (int, long):
                            self.config.WriteInt(name, value)
                        elif type == float:
                            self.config.WriteFloat(name, value)
                
                
                if __name__ == "__main__":
                    test = DefaultValueHolder("HETAP Pro 2.00", "Database")
                    test.SetVariables(UserName = "peter", Password = "pan", ServerName = "MyServer", database="")
                    test.InitFromConfig()
                    for line in test.GetVariables():
                        print line
                
                ##    #### this also works:
                ##    ## test.defaultUserName = "joe"
                ##

                Comment

                • true911m
                  New Member
                  • Dec 2006
                  • 92

                  #9
                  Originally posted by bartonc
                  Here it is in it's entirety. Sorry about the confussion.

                  Code:
                  """Encapuslate a Default Values Object and Config File"""
                  
                  ...
                  
                      def InitFromConfig(self):
                          config = self.config
                          group = self.grpName
                  
                          if not config.Exists(group):
                              self.WriteRegistryGroup(Group)
                              return
                  Well, almost:

                  Code:
                          if not config.Exists(group):
                              self.WriteRegistryGroup(group)  #  <<=== lowercase
                              return
                  :)

                  Cheers,

                  - Mark

                  Comment

                  • bartonc
                    Recognized Expert Expert
                    • Sep 2006
                    • 6478

                    #10
                    Originally posted by true911m
                    Well, almost:

                    Code:
                            if not config.Exists(group):
                                self.WriteRegistryGroup(group)  #  <<=== lowercase
                                return
                    :)

                    Cheers,

                    - Mark
                    Do you realize that you just saved me much embarrassment? This is due to be installed on a system that would certainly execute that line. I guess I need to do more thorough testing before even thinking about delivery! Thanks Mark! Much appreciated,
                    Barton

                    Comment

                    • true911m
                      New Member
                      • Dec 2006
                      • 92

                      #11
                      Originally posted by bartonc
                      Do you realize that you just saved me much embarrassment? This is due to be installed on a system that would certainly execute that line. I guess I need to do more thorough testing before even thinking about delivery! Thanks Mark! Much appreciated,
                      Barton
                      Hey, the debugger calls em like it sees em!

                      Comment

                      • bartonc
                        Recognized Expert Expert
                        • Sep 2006
                        • 6478

                        #12
                        Originally posted by true911m
                        Hey, the debugger calls em like it sees em!
                        I cleaned up the structure a bit while I was there:


                        Code:
                            def InitFromConfig(self):
                                config = self.config
                                group = self.grpName
                        
                                if not config.Exists(group):
                                    self.WriteRegistryGroup(group)
                        
                                else:
                                    config.SetPath(group)
                                    for var in self.GetVariables():
                                        name = var['name']
                                        if config.Exists(name):
                                            value = self.ReadRegistry(name, var['type'])
                                            self.SetVariables({name:value})
                                        else:
                                            self.WriteRegistry(name, var['value'], var['type'])
                                config.SetPath("")
                        
                            def WriteRegistryGroup(self, group):
                                self.config.SetPath(group)
                                for var in self.GetVariables():
                                    self.WriteRegistry(var['name'], var['value'], var['type'])
                                self.config.SetPath("")

                        Comment

                        • bartonc
                          Recognized Expert Expert
                          • Sep 2006
                          • 6478

                          #13
                          Originally posted by bartonc
                          I cleaned up the structure a bit while I was there:


                          Code:
                              def InitFromConfig(self):
                                  config = self.config
                                  group = self.grpName
                          
                                  if not config.Exists(group):
                                      self.WriteRegistryGroup(group)
                          
                                  else:
                                      config.SetPath(group)
                                      for var in self.GetVariables():
                                          name = var['name']
                                          if config.Exists(name):
                                              value = self.ReadRegistry(name, var['type'])
                                              self.SetVariables({name:value})
                                          else:
                                              self.WriteRegistry(name, var['value'], var['type'])
                                  config.SetPath("")
                          
                              def WriteRegistryGroup(self, group):
                                  self.config.SetPath(group)
                                  for var in self.GetVariables():
                                      self.WriteRegistry(var['name'], var['value'], var['type'])
                                  self.config.SetPath("")
                          And here's how to initialize module-scope variables with either the values sent into the function or the registry values. Registry values are used if they exist.
                          Code:
                          import DefaultHolder as DH
                          import wxdbtools as db
                          
                          ## Don't actually have to declare these before making them global.
                          dbDefaultHolder = None
                          dbServer = None
                          dbConnect = None
                          
                          def InitDBDialog(HKey, group, user, password, host):
                              """Connect to database using registry defaults if they exist.
                                 Return the connection or (which may be None)."""
                              global dbDefaultHolder, dbServer, dbConnect, dbServer, dbConnect
                              dbDefaultHolder = DH.DefaultValueHolder(HKey, group)
                              dbDefaultHolder.SetVariables(UserName=user, Password=password,
                                                           ServerName=host)  #, database='trails'
                              dbDefaultHolder.InitFromConfig()
                              dhVars = dbDefaultHolder.GetVariables()
                          
                              for var in dhVars:
                                  execStr = "%s = %s" %(var['name'], (repr(var['value']), var['value'])[var['type'] != str])
                                  exec(execStr) in globals()
                          
                              dbServer = db.DBServer(sys.stdout)
                              dbConnect = dbServer.Login(ServerName, UserName, Password)
                              return dbServer
                          Postponed dialog box instantiation is the reason for module-scope here. Once there are set up, my Login Dialog Box can be created on the fly, already connected to the database:
                          Code:
                          def create(parent):
                              return DBConnectDialog(parent, dbDefaultHolder, dbConnect, dbServer)
                          
                          class DBConnectDialog(wx.Dialog):
                              def __init__(self, parent, defaultHolder, dbConnect, dbServer):
                                  self._init_ctrls(parent)
                          
                                  self.connectButton.SetDefault()
                                  self.OkButton.Disable()
                          
                                  self.defaultHolder = defaultHolder
                          
                                  self.dbConnect = dbConnect  # save the connection so it can be closed
                                  dbServer.SetMaster(self)
                                  self.dbServer = dbServer
                          
                                  self.SetWidgetData()

                          Comment

                          Working...