[Zope3-dev] Re: Source API

Stuart Bishop stuart at stuartbishop.net
Tue Sep 6 01:08:24 EDT 2005


Gary Poster wrote:

> The use case we are trying to address with the iterable source 
> interface is that we want to be able to distinguish between sources 
> that should be searched, and those that should be displayed as  explicit
> choices.  I'll call these 'searchable' and 'showable'  sources and
> widgets below.  I'll discuss a few of the possible  approaches to the
> problem.
> 
> One way is to register searchable widgets for all source fields.  If 
> you want a showable widget for a given source, you need to confirm  that
> the source supports __iter__ and then register a showable widget  for
> the combinations of source plus each field type that uses the  source
> (i.e., Choice, Tuple, Set, etc.).  That's a bit heavy when you  have a
> reasonable number of these sources in your application.  You  could also
> do this kind of story with a custom widget for each form,  but that
> would be even more impractical and annoying with heavy  source usage.
> 
> Another way would be to have an interface that marks a source as 
> 'showable'.  You could then register searchable widgets for standard, 
> non-showable source fields; and showable widgets for fields marked as 
> showable.  This is convenient.  If you make the decision actually in 
> the software, you are making the decision at the wrong level (it is 
> configuration), but if you declare the showable interface on the  source
> with zcml, it is closer to being in the right location.  It  still feels
> problematic though: what if the source is used for  display in multiple
> formats--HTML vs. rich client, for instance?   What if a source has
> variable options during the lifetime of the  application, and sometimes
> is appropriate to be shown as a  searchable, and sometimes as a showable?

This is the way we solved this issue in Launchpad. We make our vocabularies
that should be searchable implement IHugeVocabulary, which also has a search
method that is used by a custom widget (currently a popup window that lets
you interactively search and populates the real control in the parent window
using Javascript, but this is really a placeholder until we get something
inline going). This custom widget is used for all IHugeVocabularies.

This is good, because it means the UI is consisent between our development
boxes (with little sample data, eg. 50 people) and the staging and
production boxes (real data, eg. over 40000 people). It also means that our
page tests are testing the UI that will exist on production rather than
something quite different.

> The last way I'll discuss is the way we chose, but did not follow 
> through on completely.  In this one, you mark the source as iterable  in
> the software, and make iterable sources also specify a len.  In  this
> case, you *can* (but we don't yet) register an intermediary  adapter for
> these iterable sources.  If the len is beneath whatever  limit you
> desire (for the given kind of request), you can return a  showable
> widget, and otherwise return a searchable widget.  Note that  if a
> source is iterable but is too big to quickly calculate its  length, that
> almost certainly is going to suggest a searchable  widget, rather than a
> showable widget.

I can see this being useful as a safety net for when a developer forgets to
use a marker interface to say 'this should be searchable' (and if we were
implementing it, if this safety net kicked in a warning would be emitted).

So if you have a Source that should always be searchable, it would just
implement ISource. I can't think of any use cases for needing to iterate
over one of these.

And if you have a Source that can be iterated over or rendered as a select
or list of radio buttons, you would implement IIterableSource. I can't think
of any use cases for this case not being able to calculate the length.

So the only thing I think needs changing here is the documentation
suggesting returning maxint from __len__.

It was more problematic in the Vocabulary code, because IVocabulary extended
IIterableVocabulary, forcing all vocabularies to implement that interface.
Sources give us the opportunity to reverse and fix that, making
IIterableSource extend ISource.

The docstrings don't make it clear what an ISourceQueriables is supposed to
achieve, how one is constructed or how it is to be used.

I would imagine that the interfaces should look like:

class ISourceItem(Interface):
    key = TextLine('Unique key', required=True)
    title = TextLine('Descriptive text to display to users. Plain text.')
    value = Attribute('Object represented by this ISourceItem')

class ISource(Interface):
    context = Attribute(
        "context the source is bound to. Generally an IChoiceField"
        )
    def __contains__(key):
        """Returns true if the key exists in this source"""

    def __getitem__(key):
        """Returns the ISourceItem for this key"""

    def search(query):
        """Return a sequence of ISourceItem matching the given query.

           query is a Unicode string or None. The meaning of this query
           is ISource specific.
        """

class IIterableSource(ISource):
    def __iter__():
        """Iterate over all ISourceItems"""

    # This method needs to be renamed count or size if it needs
    # to support returning 'length unknown'
    def __len__():
        """Number of ISourceItems"""


The default widget for an ISource would be a simple text entry where the
user enters the key.

The default widget for an IIterableSource would be a <select> of <option
value="key">title</option>, with a fallback to the default ISource widget if
__len__() > 200 (or some arbitrary constant).

I wouldn't like to use the title as the key, because the title might be
changed where as keys should be unchanging (or at least more so).

I think the ISourceItem is important, as it allows people to extend what is
being returned by their sources. In particular, we would have
IIterableSource sources that return IRichSourceItem which also provides a
snippet() method or view. This would provide an XHTML fragment which would
be used to render a list of radio buttons or check boxes with markup in the
descriptive text.

-- 
Stuart Bishop <stuart at stuartbishop.net>
http://www.stuartbishop.net/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: OpenPGP digital signature
Url : http://mail.zope.org/pipermail/zope3-dev/attachments/20050906/1b56f9fc/signature-0001.bin


More information about the Zope3-dev mailing list