Many Similar Dialogs For Date Entry

Rather than re-inventing the wheel, and having it out of round, I'd
appreciate your suggestions on how to optimally organize wxPython code when
different but similar types of data must be entered by the user.

   On one notebook page, a variable number of named mathematical curves need
to be defined. There are 18 curve types: 'Empty', 'Linear Increasing',
'Linear Decreasing', 'Growth S-Curve', 'Decay S-curve', 'Gaussian',
'Triangle', 'Left shoulder', 'Right shoulder', 'Trapezoid', 'Outcome
(Aggregated)', 'Singleton', 'Data', 'Beta', 'Transform', 'Truth series',
'Weighted beta', and 'Rectangle.' In addition to the name and shape, each
type has relevant data necessary to define it. Data types include the domain
ends, width, center, height, inflection point, direction (for the S-curves
and shouldered trapezoids), and so on.

   Creating 18 classes, each slightly different from the others is inelegant
and prone to be a maintenance nightmare. I suppose that one base class with
the others inheriting from it might work, but I've not written anything like
this in my short exposure to wxPython.

   I would appreciate advice and pointers to relevant examples or guidelines.
I did not see an obvious answer in the wPIA book.

Rich

···

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863

Rich,

  Rather than re-inventing the wheel, and having it out of round,

always a good idea!

Creating 18 classes, each slightly different from the others is inelegant
and prone to be a maintenance nightmare. I suppose that one base class with
the others inheriting from it might work

yes, that's what OO is about.

However, if what you are looking for is 18 slightly different Panels for entering the data, then subclassing could help, but would be a pain non-the-less.

What this calls for is dynamic GUI building. This is exactly why I'm not a fan of point-an-click GUI builders. In a case like this, you don't want to point and click your way to making 18 panels -- you want the panels to be generated by code.

I have a simple example of this that I've enclosed. It's a simple Unit converter. The Units and conversion factors are defined as data, then a Panel for each type of unit (length, velocity, etc) is created on the fly. This way I can just add new units to the data, and the whole thing just works. There are a couple of oddballs that are still written by hand and added in, but most of it works fine.

Your case is more complicated, but the same principle should work, define each curve in terms of it's name and parameters required. They should be similar enough that you can auto-build a panel to collect the data.

-Chris

Converter.py (11.6 KB)

UnitConversion.py (13.4 KB)

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Perhaps the one dialog class called with named arguments that are used to
present and return only the relevant fields. The dialog class then has a
series of if ... elif control statements.

Rich

···

On Thu, 1 Feb 2007, Rich Shepard wrote:

Creating 18 classes, each slightly different from the others is inelegant
and prone to be a maintenance nightmare. I suppose that one base class
with the others inheriting from it might work, but I've not written
anything like this in my short exposure to wxPython.

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863

Rich Shepard wrote:

···

On Thu, 1 Feb 2007, Rich Shepard wrote:

  Perhaps the one dialog class called with named arguments that are used to
present and return only the relevant fields. The dialog class then has a
series of if ... elif control statements.

Or use a dictionary, keyed on the argument names.

--
Don Dwiggins
Advanced Publishing Technology

What this calls for is dynamic GUI building. This is exactly why I'm not a fan of point-an-click GUI builders. In a case like this, you don't want to point and click your way to making 18 panels -- you want the panels to be generated by code.

Chris,

   I gave up on the automated tools a while ago. I do all the writing in
emacs. Now that I've discovered the speedbar I can quickly navigate to any
module, class, or function.

I have a simple example of this that I've enclosed. It's a simple Unit converter.

   I missed seeing this message yesterday and just now found it in the
archives. Please resend -- with attachment -- directly to me to avoid list
clutter.

   This dynamic dialog builder looks like an ideal solution. Better than what
I was starting to do. :slight_smile:

Many thanks,

Rich

···

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863

Don,

   Please show me an example of how the dictionary would be implemented. It
looks like something I ought to learn for future reference.

Thanks,

Rich

···

On Fri, 2 Feb 2007, Don Dwiggins wrote:

Perhaps the one dialog class called with named arguments that are used to
present and return only the relevant fields. The dialog class then has a
series of if ... elif control statements.

Or use a dictionary, keyed on the argument names.

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863

Python lacks a case statement, and nestings if/elif can get
cumbersome. The common idiom is to use a dictionary to map values to
callables.

Pseudo C/C+ code:

void processID(int id) {
switch id {
  case SWITCH_ONE:
   process_one();break;
  case SWITCH_TWO:
   process_two();break
}

Python with nested if:

def processID(id):
  if id == SWITCH_ONE:
    process_one()
  elif id == SWITCH_TWO:
    process_two()

Python with dictionary:

def processID(id):
  mapper = {
    SWITCH_ONE:process_one,
    SWITCH_TWO:process_two
  }
  mapper[id]()

···

On 2/2/07, Rich Shepard <rshepard@appl-ecosys.com> wrote:

On Fri, 2 Feb 2007, Don Dwiggins wrote:

>> Perhaps the one dialog class called with named arguments that are used to
>> present and return only the relevant fields. The dialog class then has a
>> series of if ... elif control statements.

> Or use a dictionary, keyed on the argument names.

Don,

   Please show me an example of how the dictionary would be implemented. It
looks like something I ought to learn for future reference.

Thanks,

Rich Shepard wrote:

···

On Fri, 2 Feb 2007, Don Dwiggins wrote:

Perhaps the one dialog class called with named arguments that are used to
present and return only the relevant fields. The dialog class then has a
series of if ... elif control statements.

Or use a dictionary, keyed on the argument names.

Don,

  Please show me an example of how the dictionary would be implemented. It
looks like something I ought to learn for future reference.

It's been said that the proper way to spell "switch ... case" in Pyhton is NOT if..elif...elif, but rather a dictionary. Here's a simple example:

A little more googling might find you more.

-Chris

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Python lacks a case statement,

   Tell me about it! I really miss the switch statement which my C
applications always use extensively.

Python with dictionary:

def processID(id):
mapper = {
  SWITCH_ONE:process_one,
  SWITCH_TWO:process_two
}
mapper[id]()

   Gotcha', thanks.

Rich

···

On Fri, 2 Feb 2007, Chris Mellon wrote:

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863

Thanks, Chris. Chris M's example made it very clear.

Rich

···

On Fri, 2 Feb 2007, Christopher Barker wrote:

It's been said that the proper way to spell "switch ... case" in Pyhton is
NOT if..elif...elif, but rather a dictionary. Here's a simple example:

Switch statements in Python

A little more googling might find you more.

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863

If your inputs are strings of the right form (or can be turned into
such strings), you can use them to construct function (or method)
names directly:

    def process(cmd):
        action = globals().get("process_cmd_%s" % cmd)
        if not action:
     print "Invalid command"
     return
        action ()

      paul

···

On Fri, 2 Feb 2007, Chris Mellon wrote:

>> Python lacks a case statement,

> Tell me about it! I really miss the switch statement which my C
> applications always use extensively.

>> Python with dictionary:
>>
>> def processID(id): mapper = { SWITCH_ONE:process_one,
>> SWITCH_TWO:process_two } mapper[id]()

Paul,

   Yes, they are strings; choices from a wx.RadioBox(). This would save one
step since a dictionary would end up calling a function in any case. No?

Thanks,

Rich

···

On Fri, 2 Feb 2007, Paul Koning wrote:

If your inputs are strings of the right form (or can be turned into such
strings), you can use them to construct function (or method) names
directly:

    def process(cmd):
        action = globals().get("process_cmd_%s" % cmd)
        if not action:
     print "Invalid command"
     return
        action ()

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863

The approach of creating function names directly from the "switch"
inputs works so long as the strings are limited to valid Python symbol
name constituents. For example, strings with spaces or periods in
them would not work, nor strings with unprintable characters or
non-ASCII Unicode.

(I once worked around that by creating alternate names in the class
dictionary, via a metaclass, but that's going a bit far for most
purposes... :slight_smile: )

      paul

···

On Fri, 2 Feb 2007, Paul Koning wrote:

>> If your inputs are strings of the right form (or can be turned
>> into such strings), you can use them to construct function (or
>> method) names directly:
>>
>> def process(cmd): action = globals().get("process_cmd_%s" % cmd)
>> if not action: print "Invalid command" return action ()

> Paul,

> Yes, they are strings; choices from a wx.RadioBox(). This would
> save one step since a dictionary would end up calling a
> function in any case. No?

Rich Shepard wrote:

···

On Fri, 2 Feb 2007, Christopher Barker wrote:

It's been said that the proper way to spell "switch ... case" in Pyhton is
NOT if..elif...elif, but rather a dictionary. Here's a simple example:

Switch statements in Python

A little more googling might find you more.

  Thanks, Chris. Chris M's example made it very clear.

The dictionary idiom actually gives you a bit more power than the switch statement. For example, the definition of the dictionary can be located away from the point of invocation (or, if it's used repeatedly, from the points of invocation), and can even be imported from another module. Also, entries can be dynamically added to or removed from the dictionary.

--
Don Dwiggins
Advanced Publishing Technology

I have not properly implemented the syntax for selecting the appropriate
dialog box, based on the curve shape selected in the radio box. The result
is nothing: no error thrown by python, no dialog box display, no idea where
I am in the code. I've put in print statements and run the application using
_winpdb.py.

   When I press the "Add" button, it just sits there and looks back at me.
I'm rather stymied since I cannot get output to learn just where I am in the
code.

   Here is the revised dictionary in the method, and one of the functions
that I'm trying to call via data entry:

   def OnFzySetAdd(self, event):
     self.name = self.fzySet.GetValue()
     self.parent = self.parVar.GetValue()
     self.shape = self.fzySetType.GetStringSelection()
     print self.shape, '\n'

     # dictionary as a switch statement:
     switch = {'Linear Increasing': linup,
               'Linear Decreasing': lindwn,
     # ...
               'Rectangle': rect}
     if self.shape in switch:
       switch[self.shape]()

   def linup():
     self.dir = 'increasing'
     newLup = lineUpDlg()
     result = newLup.ShowModal()
     if result == wx.ID_OK:
       self.fzySetList.Append(name)
       stmt1 = """insert into fuzzyset (name, parent, shape, left_edge,
                                        right_edge, direction) values
                                        (?,?,?,?,?,?)"""
       self.appData.cur.execute(stmt1,(self.name, self.parent, self.shape, float(self.left),
                                       float(self.right), self.dir))
     newLup.Destroy()

Rich

···

On Fri, 2 Feb 2007, Chris Mellon wrote:

Python with dictionary:

def processID(id):
mapper = {
  SWITCH_ONE:process_one,
  SWITCH_TWO:process_two
}
mapper[id]()

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863

Moving the docstring outside the method solved this problem. Perhaps the
docstring was not well formatted, or there may be another issue, but it now
works.

Rich

···

On Mon, 5 Feb 2007, Rich Shepard wrote:

When I press the "Add" button, it just sits there and looks back at me.
I'm rather stymied since I cannot get output to learn just where I am in
the code.

--
Richard B. Shepard, Ph.D. | The Environmental Permitting
Applied Ecosystem Services, Inc. | Accelerator(TM)
<http://www.appl-ecosys.com> Voice: 503-667-4517 Fax: 503-667-8863