[Zope3-dev] Schema, widget and form refactoring (was Re: [Zope3-checkins] CVS:Zope3/src/zope/schema - _bootstrapfields.py:1.19.2.1)

Garrett Smith garrett@mojave-corp.com
Tue, 22 Jul 2003 12:33:56 -0500


Fred L. Drake, Jr. wrote:
> Garrett Smith writes:
>  > This is Steve's position, so I won't speak for him. I think in
>  practice, > though, users of HTML forms will expect a blank string
>  to be considered > 'missing'. I realize that a) we haven't defined
>  'missing' (doing that as > we speak) and b) fields aren't used
> exclusively in HTML forms.=20
>=20
> General Python practice is to use None for missing values.  It's not
> clear that there's a meaningful special case here.

But you're not disputing the need for missing_value. You just want text
default to be None instead of <empty string>, correct?

>  > It would be nice to see a delineation in the API between values
>  that are > meant for objects and internal data used by the widget.
>  Currently, I > have these as getData and getUnconvertedData
>  respectively. >
>  > getUnconvertedData -> getUserInput?
>=20
> The current API never exposes unconverted data; let's avoid changing
> that.  All the convert/unconvert stuff in internal, provided for
> "convenient" subclassing.

The convert/unconvert is different from 'what the user typed into the
box' data. This should be public and in the API, IMO.

In fact, I'd argue that all of this conversion stuff should be handled
*outside* the widget -- and that the widget focusses only on UI issues.
These have become exceedingly intelligent widgets -- bad, IMO.

But I'm certainly not signing up for changing this now :-)

>  > I think widget's need to support another term: 'unspecified'. This
>  is > different from 'missing'. Missing means that we have data, and
>  it's > 'missing_value' (e.g. None, 0, '', etc.). 'unspecified' means
>  that this > widget has no input -- it's a no-op as far as any
>  'applyUpdates' are > concerned.
>=20
> I hope you're able to clarify this distinction.

This distinction arises in the fact that *all* of the widgets are
populated in preparation for the form submit processing, even those
widgets that don't have data in the form.

To be clear:

 IFoo:
   a=3DText()
   b=3DText()
   c=3DText()

If a form only submits a and b, c is 'unspecified' -- it's not there. It
doesn't have missing_value, it doesn't have default_value. It's
nonexistent and should certainly not trigger any changes to the field
value.

Okay...a and b *are* in the form. But a's value is translated as
'missing' for the object -- i.e. "I'm the user and I say -- set 'a' to
None"

In this case, a is specified as 'missing'.

The confusion is that these terms apply to different things:

- 'missing' applies to the field value wrt the object -- we know exactly
what the value is -- it's the 'missing_value' (None, etc.)

- 'unspecified' applies to the user input -- we have no idea what the
value is -- it's not there, and we're certainly *not* going to assume
that it should be the 'missing' value.

>  > In my branch, unspecified is True (for browser widgets) when that
>  > widget's field is not in the form:
>  >
>  >   widget.name not in widget.request.form
>=20
> That's not an acceptable test for complex widgets.  I think any
> interpretation of request data *must* go through the widget.

Okay...I see this. I think we need to create one of these complex
widgets asap and plug it into an ftest. It's going to pose problems, for
my branch, or the head.

> Since the widget API only deals with "converted" data and not the HTML
> form fields, there isn't a problem here.

Yep.

>  > Because a 'missing value' is a perfectly legal value to submit --
>  and to > return hasData as False is plain wrong here. The widget has
>  data -- it's > the missing value. It may turn out that 'missing'
>  should fail on the > 'required check' but that doesn't mean the
> widget doesn't have data.=20
>=20
> If there's a distinguished value for the domain that indicates
> "missing" distinct from other values, that's up to the type-specific
> conversions.  That's distinct from the widget-level concept of a value
> that's missing.

It's very distinct. And that's reflected in widget._missing and
field.missing_value. Here...

  Widget::Updating a Field
  ----------------------------------
  if value is specified in form:
      if user input equals my (widget's) _missing value:
         value =3D field's missing value
      else:
         value =3D converted and validated user input
      update field with value

Three points:

- A value is 'specified' if it's not in the form (for complex widgets,
this might be more complicated)

- A widget's _missing value is a form value that is interpreted as
field.missing_value (e.g. for text, it's an empty string, for checkbox
there's no such thing, for complex widgets...they have to make that
determination)

- A field's missing value is specified by the Field def...it's usually
None

These complex widgets are troubling -- there's a lot of assumptions that
widget 'user input' comes via a single form value. These assumptions are
not only in my branch.

 -- Garrett