omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    [Share] Just an idea to give seemly simple params some structured interface

    Pythonista
    param idea share
    2
    9
    5984
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Phuket2
      Phuket2 last edited by

      Well, it's a quite night on the forum tonight, so I may as well share something. I think it's smart idea, but I have been proven wrong many times before :( What I am posting is not finished but its enough to see the intent.
      The intent I have in mind is to provide some simple data structures /classes for parameters to lib functions such as dialogs. I know, the param list is simple enough, but in practice you end up writing a lot of code to support the params. And not in a structured way.
      Look, I accept if I am wrong. But it seems to me that when you write a lib, if you could support it with a type of generic data/param interface class without much work it would be a big bonus.
      Just an idea

      # coding: utf-8
      
      
      import ui
      import dialogs
      
      _fld_attrs = {
      						'type': None,
      						'key' : None,
      						'value' : '',
      						'title' : None,
      						'tint_color': None,
      						'icon' : None,
      						'placeholder': '',
      						'autocorrection' : False,
      						'autocapitalization' : False,		
      					}
      					
      	
      class DialogFormField (object):
      	def __init__(self, **kwargs):
      		'''
      			DialogFormField
      			Just start of an idea to create an easy way to give more comlicated params to functions/methods some form of structured params. i could be off on the wrong track. But while the params look easy enough to a lot of libs, in practice they make for a lot code. also dot notation not avalible etc...
      			Again, is not finished... just exploring
      		'''
      		
      		# create the class attributes from a dict
      		for attr in _fld_attrs:
      			setattr(self, attr, _fld_attrs[attr])
      		'''
      		# fields as per definition of the 
      		# dialog.form_dialog()
      		self.type = None
      		self.key = None
      		self.value = ''
      		self.title = None
      		self.tint_color = None
      		self.icon = None
      		self.placeholder = 'Enter your text...'
      		self.autocorrection = False
      		self.autocapitalization = False
      		'''
      		
      		# maybe this needs to be stronger. In my testing
      		# it has been ok. but maybe some tricky stuff,
      		# i dont know about.
      		self.flds = [attr for attr in dir(self) if not attr.startswith('__') and not callable(getattr(self, attr))]
      		
      		for k in kwargs:
      			if hasattr(self, k):
      				setattr(self, k, kwargs[k])
      		
      		# calling this because can not declare any more
      		# attributes in this method. we want to get a 
      		# list of the field attrs. So can declare more
      		# class attrs in the init2 method.
      		self.init2()
      		
      	def init2(self):
      		'''
      			just some test values to prove these attrs are not getting in the way
      		'''
      		self.another_item = 'init2'
      		self.xxx = 'init2'
      		
      	def get_dict(self):
      		return  {attr : getattr(self, attr) for attr in self.flds}
      
      
      
      
      if __name__ == '__main__':
      	flds = []
      	fld = DialogFormField(title = 'test', type = 'text', tint_color = 'blue', placeholder = 'Enter your text...')
      	fld.icon = 'typb:Anchor'
      	fld.key = 'TextVal'
      	flds.append(fld.get_dict())
      	
      	x = DialogFormField()
      	x.type = 'switch'
      	x.title = 'My switch'
      	x.value = 'True'
      	x.key = 'SwitchVal'
      	flds.append(x.get_dict())
      	
      	d = dialogs.form_dialog(title = 'Test', fields = flds)
      	print d
      
      1 Reply Last reply Reply Quote 1
      • Phuket2
        Phuket2 last edited by

        Ok, I see self.flds should be made up when the attributes are been set from the dict. This helps simply the class a lot.

        1 Reply Last reply Reply Quote 0
        • Phuket2
          Phuket2 last edited by

          Simplified code

          # coding: utf-8
          
          
          import ui
          import dialogs
          
          _fld_attrs = {
          						'type': None,
          						'key' : None,
          						'value' : '',
          						'title' : None,
          						'tint_color': None,
          						'icon' : None,
          						'placeholder': '',
          						'autocorrection' : False,
          						'autocapitalization' : False,		
          					}
          					
          	
          class DialogFormField (object):
          	def __init__(self, **kwargs):
          		'''
          			DialogFormField
          			Just start of an idea to create an easy way to give more comlicated params to functions/methods some form of structured params. i could be off on the wrong track. But while the params look easy enough to a lot of libs, in practice they make for a lot code. also dot notation not avalible etc...
          			Again, is not finished... just exploring
          		'''
          		
          		self.flds = []
          		
          		# create the class attributes from a dict
          		for attr in _fld_attrs:
          			setattr(self, attr, _fld_attrs[attr])
          			self.flds.append(attr)
          			
          		# set the attrs 
          		for k in kwargs:
          			if hasattr(self, k):
          				setattr(self, k, kwargs[k])
          	
          	def get_dict(self):
          		return  {attr : getattr(self, attr) for attr in self.flds}
          
          if __name__ == '__main__':
          	flds = []
          	fld = DialogFormField(title = 'test', type = 'text', tint_color = 'blue', placeholder = 'Enter your text...')
          	fld.icon = 'typb:Anchor'
          	fld.key = 'TextVal'
          	flds.append(fld.get_dict())
          	
          	x = DialogFormField()
          	x.type = 'switch'
          	x.title = 'My switch'
          	x.value = 'True'
          	x.key = 'SwitchVal'
          	flds.append(x.get_dict())
          	
          	d = dialogs.form_dialog(title = 'Test', fields = flds)
          	print d```
          1 Reply Last reply Reply Quote 0
          • dgelessus
            dgelessus last edited by dgelessus

            @Phuket2 Instead of manually converting dicts into attributes and vice-versa, consider using an actual dict internally (self.style_dict) and overwriting __getattr__ and __setattr__. Anything listed under self.flds would automatically be redirected to self.style_dict, anything else stays a normal attribute.

            The __*attr__ methods are a little tricky to customize though. __getattr__ is probably the easiest one, it only gets called when there is no "real" attribute with a certain name. However __setattr__ and __delattr__ are always called, no matter if the attribute is "real" or not. In cases where you don't want custom behavior, you need to manually redirect the method to the superclass:

            class DialogFormField(object):
                def __setattr__(self, name, value):
                    super(DialogFormField, self).__setattr__(name, value)
            

            You can't just use setattr, because that ends up calling your custom override again, and you're stuck in infinite recursion. (There's also __getattribute__, which has the same purpose as __getattr__, except that it is always called, not just for "not real" attributes.)

            By the way, try renaming your get_dict method to __dict__, and then run dict(DialogFormField(placeholder="hi there!")). ;)

            Phuket2 2 Replies Last reply Reply Quote 0
            • Phuket2
              Phuket2 @dgelessus last edited by

              @dgelessus , thanks for the info. I did do some playing with the *attr methods and getattribute method, but I was getting confused. As you mention, side effects start occurring. So I tried to do it in a way which I think I understand.

              Now, it's sort of working I will try again.

              With your comment about dict, not sure if I am doing something wrong or you wanted me to learn something :)
              I did as you said regarding dict, but got the error message that DialogFormField is not iterable.
              So I added an iter method as

              def __iter__(self):
              		for attr in self.flds:
              			yield (attr , getattr(self, attr))
              

              Then print dict(DialogFormField()) prints the dict :)

              It was also nice to see the below work.

              for item in DialogFormField():
              		print item
              

              I know it's basic. But it's not for me, exciting to see classes work in naturally with Python as the built in classes. Gives you a new appreciation for the possibilities for elegant solutions that can be created with classes.

              Again, thanks for your comments. I know I am a little off track from Pythonista. While its a learning exercise for me, I really think there is a place for a class like this that can help clean up parameter creation, but in a generic way as possible.

              1 Reply Last reply Reply Quote 0
              • Phuket2
                Phuket2 @dgelessus last edited by

                @dgelessus , I was having problems working out your suggestions. I think I got the functionality though, without overriding *attr methods.
                But I am starting to question the wisdom of creating the class in the first place. It's difficult sometimes. You think you are on to something cool, then you are not :)
                Oh, well. Needs more thought on my part.

                # coding: utf-8
                
                
                import ui
                import dialogs
                import sys
                
                
                _fld_attrs = {
                						'type': None,
                						'key' : None,
                						'value' : '',
                						'title' : None,
                						'tint_color': None,
                						'icon' : None,
                						'placeholder': '',
                						'autocorrection' : False,
                						'autocapitalization' : False,		
                					}
                					
                	
                class DialogFormField (object):
                	def __init__(self, **kwargs):
                		'''
                			DialogFormField
                			Just start of an idea to create an easy way to give more comlicated params to functions/methods some form of structured params. i could be off on the wrong track. But while the params look easy enough to a lot of libs, in practice they make for a lot code. also dot notation not avalible etc...
                			Again, is not finished... just exploring
                		'''
                		self.__dict__.update(_fld_attrs)
                			
                		# set the attrs 
                		for k in kwargs:
                			if hasattr(self, k):
                				setattr(self, k, kwargs[k])
                			
                	def __iter__(self):
                		for attr in self.__dict__:
                			yield (attr , getattr(self, attr))
                		
                		
                
                if __name__ == '__main__':
                	flds = []
                	lst = ['First Name', 'Last Name', 'Age']
                	for f in lst:
                		flds.append(dict(DialogFormField(title = f + ':', type = 'text' , placeholder = 'Enter ' + f , key = f, tint_color = 'red')))
                	
                
                	results = dialogs.form_dialog(title = 'Test', fields = flds)
                	
                	print results
                	
                	
                
                1 Reply Last reply Reply Quote 0
                • dgelessus
                  dgelessus last edited by

                  Nevermind, __dict__ is actually not the special method for "convert to dictionary". Thought I was being smart there. The proper way to make your class dictionary-compatible would be to make it iterable (like you did) and implement all the mapping methods like keys, values, items, etc.

                  Phuket2 1 Reply Last reply Reply Quote 0
                  • Phuket2
                    Phuket2 @dgelessus last edited by

                    @dgelessus , still good learning experience:)

                    1 Reply Last reply Reply Quote 0
                    • Phuket2
                      Phuket2 last edited by

                      I wil just declare I am an idiot. My lack of knowledge takes me on stupid journeys.if I had looked at dict class in more detail i would not been trying to write this class. Have dictviews also. But it's all been a learning process. After doing this, I feel a lot better equipped to try and understand dicts 100%

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post
                      Powered by NodeBB Forums | Contributors