On Fri, 19 Jan 2007, Grant Baillie wrote:
We can almost certainly replace a lot of the initialValue uses with
defaultValue, especially for values that aren't references. There's some risk
there, because the return value Item.hasLocalAttributeValue() is different in
the two cases, and some code (ICalendar/sharing, maybe) could rely on that.
So far as reflists go, there are really two approaches in use right now:
1) Use defaultValue=None in your attribute.
(Example: EventStamp.modifications or EventStamp.occurrences)
Then, always make sure you can deal with None when iterating over myAttr. If
you have a biref, let the repository take care of setting up the biref where
possible, by always assigning to the "other" end. This avoids a lot of
checking for None, and initializing the attribute to [] (or set() or {} as
appropriate).
I could add support for new None-style reflist value, such as Nil, which can
be iterated, thereby saving everyone from having to first check whether they
have None or a valid ref list.
Currently, I already have such a value, Nil, but it is expressly meant to be
NOT persistable. I could add another one, called Empty, of the same type
that can.
Nil works as follows:
- Nil is not true
- len(Nil) == 0
- Nil() -> None
- 'blah' in Nil -> False
- iter(Nil) -> iterator that stops right away
- Nil is immutable
2) Use initialValue=[]
(Example: Reminder.reminderItems)
As you noticed, this leads to an extra attribute assignment every time you
create the Item. It does, however, make for simpler code: you assume that
attribute always exists, and just iterate over it, call
add()/remove()/whatever on it, and all's well. Unfortunately, it also has the
downside that initialValues don't always get set (if items are imported via
sharing, __init__ and initialValues are bypassed), which leads to bugs.
Yes, that's one problem. The other problem is that an initialValue, when set,
is a local value and having lots of empty local values eventually adds up too.
(As an aside, there's a movement afoot -- mainly PJE's work -- to have
initialValues in Stamp subclasses only be set up when the stamps are actually
added. This would probably cut down on some of the empty collection values in
your report. cf.
That would be great and probably address a large part of what my original mail
was about.
Anyway, is there a way to have the best of 1) and 2)? i.e. have something
that behaved like defaultValue=[], until you tried to modify the collection?
i.e. in code:
class MyItem(schema.Item):
... myAttr = schema.Sequence(schema.Item, magicValue=[])
...
x = MyItem(...)
list(x.myAttr)
[]
x.hasLocalAttributeValue('myAttr')
False
x.myAttr.add(x)
x.hasLocalAttributeValue('myAttr')
True
x.myAttr.first()
<MyItem ....>
I sure could add something like that beyond what I described above. Have a
sort of Nil value that knows what to do when one attempts to append to it.
In fact, shouldn't all many-valued attributes behave this way?
That could be useful in many cases, yes.
Is what we're discussing here something I should implement now or are we just
discussing various ideas, nice-to-haves ?
Personally, I have no objections to implementing these now.
Let me know...
Andi..
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Open Source Applications Foundation "chandler-dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/chandler-dev