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.


    Thinking out aloud, code gen for ui attr.

    Pythonista
    1
    2
    1206
    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

      I mention in the comments of the code this is far from finished or polished. I am trying to get my head around a good uniform stradegy to implement some type of styles to any app I may write. I thought by writing this code, it will help me along the way. Just writes out a style class at the moment. Still thinking about the next steps. Will sleep on it.

      
      '''
      	this is sort of, just thinking out aloud code. i want a standard way to handle styles in all my projects.
      	i was thinking to have a style class for each ui element. 
      	you create the class, assign your attributes then you pass it to some helper functions or methods in the class. 
      	
      	this code, writes the classes to the console, which you could copy and paste into an empty script. 
      	
      	its no were finished yet. no helper functions etc...
      	
      	also some logic problems in handling some of the attributes. i have fudged it were i needed to just to get the code working. fudged working code , better than no code.
      	
      	only sharing this now because someone may have valuable feedback. maybe the feedback is  'stop you idiot, is a waste of time, it has been done before, and a lot better than this!' regardless all feedback is good.
      	
      	i have not wasted my time though, even if the code is cluncky, i have learnt a lot by attempting it.
      '''
      import ui
      import sys
      
      _INDENT_LEVEL_0 = ' ' * 0
      _INDENT_LEVEL_1 =' ' * 2
      _INDENT_LEVEL_2 = _INDENT_LEVEL_1 * 2
      
      __NO_BASE = True
      
      ui_objects = [ui.View, ui.Button,ui.ButtonItem, ui.ImageView,ui.Label, ui.NavigationView, ui.ScrollView, ui.SegmentedControl, ui.Slider, ui.Switch, ui.TableView, ui.TableViewCell, ui.TextField, ui.TextView, ui.WebView,  ui.DatePicker]
      
      _HEADER = '''
      import datetime
      '''
      					
      
      def write_out(str):
      	# i am writing to the console, can write to a file ect...
      	print str
      
      def get_non_callable_attr_list(obj):
      	'''
      		if this function performs correctly, a list of attributes for the given object will be returned in a list. i say if, meaning if i have stepped over the attributes that should not be returned correctly.
      		
      	'''
      	attr_list = []
      	attributes = dir(obj)
      	for attr in attributes:
      		if not callable(getattr(obj, attr)) and attr[:2] != '__' :
      			attr_list.append(attr)
      	return attr_list
      	
      def write_cls_to_console(obj, base_attr):
      	'''
      		this function does most the work. iterates over the already filtered attributes of an object, creates the object from the ui base object, then eval's' each attribute so we can write the default values to the class. 
      		had to fudge some values. more than i would have liked to. its ok, will go back and find a better stradegy to deal with the execptions. i say fudge, but i believe they are correct fudges. some attributes need special handling, i have just done a crappy linear job of handling them at the moment. there is awlays tomorrow.
      	'''
      	attributes = get_non_callable_attr_list(obj)
      	
      	#this is a funny way to get the class name. it was the easiest i could come up with without adding more data. i tried a lot of different ways, i could not get it. however, i think there must be a better way...
      	class_name = obj.__doc__.split(' ', 1)[0]
      	
      	write_out( _INDENT_LEVEL_0 + 'class ' + class_name + '_Style' + '(object):')
      	
      	write_out(_INDENT_LEVEL_1 +  'def __init__(self):')
      	added_attr = 0
      	for attr in attributes:
      		#if attr not in base_attr:
      		
      		# i was initally thinking to make a base class of attributes based on the attributes of ui.View and have each class inherit from the base class. i could see quickly this was not smart. i could have still done it with a call to the superclass to init the vars of the superclass, but in my mind self defeating. the commented if statement above would only write the attributes in each class whose attribte did not appear in ui.View 
      		
      		if __NO_BASE:
      			#create an actual instance of the object, so we can get the default attr settings using eval.
      			new_obj = obj()
      			
      			# i know this try is bad. i am not sure why its failing at the moment... so we will move on. the first fail was on NavigationView, i am sure a few others fail also...
      			try:
      				x = eval('new_obj.' + attr) 
      			except :
      				x = 'None'
      			
      			# another crappy check. if the eval equates to a memory object, we set to None
      			if x:
      				if 'object at' in str(x): x = None
      			
      			# yet another crappy check. see if len == 0
      			#flex and autoresizing come back as ''
      			if type(x) == str:
      				if not len(x) : x = "''"
      			
      			# last check.... i hope, will rethink these checks and redo the logic later
      			if attr == 'text': x = "''"
      				
      			# and yet another execption...sh*t
      			# only used for datepicker...
      			if attr == 'date': x = 'datetime.datetime.today()'
      			
      			write_out(_INDENT_LEVEL_2 + 'self.' + attr + ' = ' + str(x))
      			
      			added_attr += 1
      			
      	if added_attr == 0:
      		write_out(_INDENT_LEVEL_1 +  'pass')
      	
      
      # this list not being used now. just creating a list of ui.View attributes. i was going to filter these attributes out if each class and inherit from a base class. does not make sense though.
      ui_View_attr = get_non_callable_attr_list(ui.View)
      
      # from here we just output the ui classes in the list ui_objects. i have used a function so the output can be easily be written to a file etc..
      
      write_out(_HEADER)
      for obj in ui_objects:
      	write_cls_to_console(obj, ui_View_attr)
      	write_out('\n') # blank line please ;)
      
      1 Reply Last reply Reply Quote 0
      • Phuket2
        Phuket2 last edited by

        Not sure if this code useful to anyone. I got a bit closer to the ui elements and attributes by writing it. I am still a beginner, so if you are a beginner also, please be careful of my code. I have tried to be careful, but I only know what I know.

        
        import ui
        import sys
        import console
        
        
        '''
        	UIClassAttrInfo
        	this is a test class, collecting attribute information about ui elements. not meant for runtime, more a tool, not necessarily useful. 
        '''
        _nl = "\n"
        _sp = ' '
        
        # list of the standard ui elements
        _ui_objects = [ui.View, ui.Button,ui.ButtonItem, ui.ImageView,ui.Label, ui.NavigationView, ui.ScrollView, ui.SegmentedControl, ui.Slider, ui.Switch, ui.TableView, ui.TableViewCell, ui.TextField, ui.TextView, ui.WebView,  ui.DatePicker]
        
        # a list of attributes that can not filtered out automatically, but should not be exposed in this class. well, thats my opion, maybe wrong
        # if you dont ignore subviews, a error will occur
        # if you dont ignore, transform, content_view and text_label you will get an object reference in memory for the attr. seems like better to leave these out.
        # seems to be no references to autoresizing in the documentation.
        #i am guessing bg_color is in for backward compatibility. 
        
        _attr_ignore = ['superview', 'subviews', 'transform','content_view', 'image_view', 'text_label','on_screen', 'autoresizing', 'bg_color' ]
        
        # a entry of attribute:value will replace the default attribute. 
        _attr_override = {'font' : ('<system>', 18),
                          'tint_color' : "'white'",
                          'date':None,
                          
                          }
        
        class UIClassAttrInfo(object):
        	def __init__(self, ui_element):
        		
        		if ui_element == ui.NavigationView:
        			# this needs to be done for ,
        			# ui.NavigationView, otherwise,big fail
        			self.obj = ui_element(ui.View())
        		else:
        			self.obj = ui_element()
        			
        		obj = self.obj
        		
        		# mangle a class name from obj
        		self.class_name = obj.__doc__.split(' ')[0]
        		
        		# get the settable attr names from ui.View
        		self.uiView_attr = self.get_attr_names(ui.View())
        		
        		# get the settable attr from the passed obj
        		self.attr = self.get_attr_names(obj)
        		
        		#get the settable attr of obj that are not in ui.View
        		self.u_attr = self.get_u_attr(self.uiView_attr,self.attr)
        		
        		self.attr_values = self.get_attr_values(obj, self.attr)
        		
        		
        	def get_attr_names(self, obj):
        		'''
        			get the settable attrs from the obj passed in. _attr_ignore, is looked up before adding the attr
        		'''
        		attr_list=[]
        		attributes = dir(obj)
        		for attr in attributes:
        			if attr in _attr_ignore:
        				# _attr_ignore, a list of attrs to ignore
        				pass
        			else: 
        				try:
        					if not callable(getattr(obj,attr)) and attr[:2] != '__' :
        						attr_list.append(attr)
        				except Exception as e:
        					print '*' * 100 # make it obvious, Fail
        					print 'we should not get here', 'get_attr_names', attr
        					print e
        					sys.exit(0) # do a hard exit! big fail
        		return attr_list
        		
        	def get_u_attr( self, view_attr, obj_attr):
        		# uses sets to get the attrs that are in the obj but not in the ui.View 
        		# could be useful
        		return list(set.difference(set(obj_attr), set(view_attr)))
        		
        	def get_attr_values(self, obj, attrs):
        		'''
        			make and return a dict of attr with the default values
        		'''
        		lst = []
        		
        		for attr in attrs:
        			if attr in _attr_override:
        				lst.append((attr, _attr_override[attr] ))
        			else:
        				try:
        					x = eval('obj.' + attr) 
        					lst.append((attr, x))
        				except Exception as e:
        					print '*' * 100 # make it obvious, Fail
        					print 'we should not get here', 'make_attr_val', attr
        					sys.exit(0)
        					print e
        				
        		return lst
        		
        	def a_write_method(self):
        		# an example of how this class could write out attribute classes. 
        		
        		print 'class ' + self.class_name + 'AttrInfo(' + 'object' + '):'
        		
        		print _sp * 2 + 'def __init__(' + 'self ):'
        		
        		print _sp * 4 + 'self.attr_list =' + str(self.attr)
        		
        		print _nl
        		
        		print _sp * 4 + 'self.attr_list_u =' + str(self.u_attr)
        		print _nl
        		
        		#write of the attr names with default values
        		for t in self.attr_values:
        			attr , val = t
        			print _sp * 4 + 'self.' + attr + ' = ' + str( str(val) if len(str(val)) > 0 else "''")
        		
        		print _nl
        		
        		
        		
        if __name__=='__main__':
        	
        	for obj in _ui_objects:
        		# only collect the attribute
        		cls_info  = UIClassAttrInfo(obj)
        		#write to the console
        		cls_info.a_write_method()
        	
        	console.hud_alert('completed')
        
        1 Reply Last reply Reply Quote 0
        • First post
          Last post
        Powered by NodeBB Forums | Contributors