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.
dialogs.form_dialog - I am having a problem with the result
-
@omz, I am just playing with the dialogs.form_dialog. Just putting a wrapper around it. But the result returned from the function is only the last field filled in. I am really not sure if I am using it wrong or if there is a bug. I am trying to be a little smarter than I normally am, and that maybe what is making it go wrong. But at least from what I can see, it should work.
import dialogs from collections import namedtuple _form_fields = ['type', 'title', 'value', 'key', 'tint_color', 'icon', 'placeholder', 'autocorrection', 'autocapitalization'] DlgFld = namedtuple('DlgFld', _form_fields) DlgFld.__new__.__defaults__ = ('text', '', '', None, '', None, '', False, False) class UIFormSection(object): def __init__(self, section='General', footer=None, *args, **kwargs): self.section = section self.footer = footer self.flds = [] def add_field(self, **kwargs): self.flds.append(DlgFld(**kwargs)) def get_section(self): return (self.section, [f._asdict() for f in self.flds], self.footer) class UIFormDialog(object): def __init__(self, title='My Dialog', *args, **kwargs): self.sections = [] self.title = title def add_section(self, sec_obj): self.sections.append(sec_obj) def show(self): section_lst = [s.get_section() for s in self.sections] x = dialogs.form_dialog(title=self.title, sections=section_lst) return x if __name__ == '__main__': # create a my dialog object dlg = UIFormDialog('Users Toops') # create a section for the dialog and add fields to it... sec_user = UIFormSection('User Details') sec_user.add_field(type='text', title='First Name', placeholder='Enter First Name', autocapitalization=True) sec_user.add_field(type='text', title='Last Name', placeholder='Enter Last Name', autocapitalization=True) sec_user.add_field(type='number', title='Age', placeholder='Enter Age') sec_user.add_field(type='password', title='password', placeholder='Users Password') sec_user.add_field(type='switch', title='Related') # create another section and fields sec_troops = UIFormSection('Troops') sec_troops.add_field(type='number', title='Infantry', placeholder='Enter the number of Infantry troops') sec_troops.add_field(type='number', title='Ranged', placeholder='Enter the number of Ranged troops') sec_troops.add_field(type='number', title='Cavalry', placeholder='Enter the number of Cav troops') dlg.add_section(sec_user) dlg.add_section(sec_troops) result = dlg.show() print(result)
-
@Phuket2 Perhaps because all fields have the same key named "None"
If you give a different key name to each field, it's ok -
@cvp , thanks you are right. It's a little tricky. I removed the 'key' param from the namedtuple to get it to work. I am sure there is another way also. If key is not defined at all then the title is used as the key. If key is None, then the condition is not met for it to use the title.
I will see if I can make it smarter so I can include the key param.
Thanks again -
@Phuket2 I just did the same...
-
@cvp , maybe this is a very easy problem to overcome if you are a python expert. I am not sure. But it seems that relying on attrs existence to set a another attr can limit pythons language abilities. I am not sure that is a correct statement or not. But would have been nice if it just workeked with key set to None
-
@Phuket2 In dialogs.py, if key parameter does not exist, it uses title, but nothing is foreseen if key is none...
-
@cvp , yes. That was my meaning. Just makes me think that if I have a API the same way, then it could limit how ppl use it. In this case seems hard to use nametuples as an intermediary data type to pass to the API. I am not trying to split hairs here, just trying to learn something. Eg. Is it a good pattern to check for the existence of a param to make decisions or maybe to do both check for the existence and None. It's tricky.
-
@Phuket2 Sorry, I can't help, I never used nametuples...
-
You have already identified the problem and may be you have solutions. Anyway here are some suggestions.
-
Use a wrapper function on _asdict to remove key if its value is None
-
The documented way to process default values is to use _replace function.
import dialogs from collections import namedtuple _form_fields = ['type', 'title', 'value', 'key', 'tint_color', 'icon', 'placeholder', 'autocorrection', 'autocapitalization'] DlgFld = namedtuple('DlgFld', _form_fields) #DlgFld.__new__.__defaults__ = ('text', '', '', None, '', None, '', False, False) default_dlgfld = DlgFld('text', '', '', None, '', None, '', False, False) def as_dict_removekeyifnone(f): f1 = f._asdict() if f1['key'] is None: del f1['key'] return f1 class UIFormSection(object): def __init__(self, section='General', footer=None, *args, **kwargs): self.section = section self.footer = footer self.flds = [] def add_field(self, **kwargs): self.flds.append(default_dlgfld._replace(**kwargs)) def get_section(self): return (self.section, [as_dict_removekeyifnone(f) for f in self.flds], self.footer) class UIFormDialog(object): def __init__(self, title='My Dialog', *args, **kwargs): self.sections = [] self.title = title def add_section(self, sec_obj): self.sections.append(sec_obj) def show(self): section_lst = [s.get_section() for s in self.sections] x = dialogs.form_dialog(title=self.title, sections=section_lst) return x if __name__ == '__main__': # create a my dialog object dlg = UIFormDialog('Users Toops') # create a section for the dialog and add fields to it... sec_user = UIFormSection('User Details') sec_user.add_field(type='text', title='First Name', key='First Name', placeholder='Enter First Name', autocapitalization=True) sec_user.add_field(type='text', title='Last Name', key='Last Name', placeholder='Enter Last Name', autocapitalization=True) sec_user.add_field(type='number', title='Age', placeholder='Enter Age') sec_user.add_field(type='password', title='password', placeholder='Users Password') sec_user.add_field(type='switch', title='Related') # create another section and fields sec_troops = UIFormSection('Troops') sec_troops.add_field(type='number', title='Infantry', placeholder='Enter the number of Infantry troops') sec_troops.add_field(type='number', title='Ranged', placeholder='Enter the number of Ranged troops') sec_troops.add_field(type='number', title='Cavalry', placeholder='Enter the number of Cav troops') dlg.add_section(sec_user) dlg.add_section(sec_troops) result = dlg.show() print(result)
-
-
@enceladus , thanks for taking the time to explain. The defaults look at lot better the way you have done them (I think I seen the way I used in stackflow one time and have used that way, goes to show you should look at multiple sources). I understand your dict attr del, I just question @omz reasoning behind this approach. Not to be a smart ass. Just to learn. I do all sort of weird things at times (well all the time). It just really points out to me how important it is to think about inferences/rules made with Params. Look, maybe what @omz has done is actually very Pythonetic, I am certainly in no position to correct him.
Anyway, thanks again. I am just playing with this wrapper around dialogs.form_dialog. I am going to try to add some persistence to it using shelve I think. Sure I will run into more troubles, so I will be back :) -
This post is deleted!