b - In the Atom syndication format, UUIDs are necessary for two things.
One, the overall feed has a UUID. This is easy - I'm storing them in a
site-local named utility, indexed by the feed annotation object.
What do yuo mean "indexed by"?
Hand the utility a feed annotation, get back a uuid for the feed.
Also, is this UUID not just another aspect of feed "metadata" and thus a
candidate for the container annotation?
This was the original plan, but I was convinced to go with the more
generalized solution of a uuid utility. I guess I can cache it in the
container annotation, but that's an optimization and tangential to this
I don't think it's tangental. When we discussed this before, I was under
the impression you wanted to have automatically assigned UUIDs to
content objects. That sounded like something which should (a) be
external to that object and (b) be centralised, with a key-reference
type functionality in the same way as zope.app.intid, to allow semantics
like "I have a UUID, now where is the object that it belongs to".
I still thing this sounds like useful, general behaviour.
However, now we are also talking about UUIDs of "feeds", which are
implemented as views. I'm assuming the same feed gets the same UUID each
time (if it does not, then you just generate it in the view,
dynamically, which is simple).
If the feed needs metadata, and this metadata is context-specific, then
storing that metadata in an annotation on the feed source (the
container) seems sensible. However, the feed UUID is then just another
part of that metadata.
The advantage of the utility approach is that it can generalised a lot.
You can index based on generic container events, for example. If the
feed/annotation is being managed explicitly, then why bother trying to
fire "contentish" events and dealing with things like key-references for
something which is in an annotation of an object?
The only reason I'd see for a central utility keeping track of UUIDs and
feeds would be if you needed some kind of global UUID-to-feed lookup
If you do choose to just treat the feed UUID as metadata, there is of
course no reason why you can't share the UUID-generating code between
the feed annotation and the more general global UUID registry/id utility.
each entry in a feed has a UUID. A content item that is an entry (a
file, in the current case) can, however, be in multiple feeds and needs
a different UUID in each. Thus, I need to be able to look up UUIDs by
the content object that will be rendered as a feed entry and look them
up relative to the feed, rather than globally.
That sounds to me like you want a composite UUID - a UUID utility gives each
content item a UUID (which is not feed-specific, and stays in line with the
general concept of a content object UUID). The one you put in the feed is
the feed's UUID and the object's UUID are combined. You could possibly use
some kind of hash if you needed to.
I considered this. I have a certain understanding of what I'm doing that
precludes the combinatorial UUID approach, but no one I talk to seems to
grasp it, so I think I will air it here so we can discuss it.
I am using RFC 4122 type 1 UUIDs. These are (practically) guaranteed
universally unique, as they are based on spatial (MAC address) and
temporal (CPU clock time) location. They have safeguards built in for
things like multiple CPUs and resetting the CPU clock.
However, they are only (practically) guaranteed universally unique if
*everyone* follows the same algorithm. If you use a different algorithm
for computing your UUIDs, then they may collide with my RFC 4122 ones,
since your algorithm doesn't compute them the same way and thus may use
different, supposedly unique information included in a different way
that results in the same UUID that I generate. Highly unlikely, but
vastly more likely than if we all follow the RFC. Thus, to me, part of
being a good citizen of the UUID world is to follow the exact RFC 4122
algorithm, so we can all get along without collisions.
There is no provision in RFC 4122 for combining two UUIDs to generate a
third, still unique, UUID. So, in my mind, combining two UUIDs, by
whatever method, results in a relative UID, not a UUID.
Granted, I live in a fantasy world where everyone plays by the same RFC
4122 rules. Still, it's a nice world and I want to do what I can to
encourage others to join me in it. So, I want to generate
strictly-compliant RFC 4122 UUIDs for use in my product (and my utility
makes it easy for others to use them elsewhere in Zope).
Thus I take the hard road, here. Is there a flaw in my reasoning?
I understand this problem, and it makes sense. I think it's a good line
to take. However, does the spec say the UUID *has* to be RFC 4122 type
1? If not, then a plain concatenation (no hash) of a UUID, with some
separator that's not going to be output by the UUID seems valid enough
to me. If you have two universally unique ids, then a combination of
them must also be universally unique.
If the spec says it must be that exact format, or you're religiously
bent on them, you'll need a different approach. You then essentially
need a UUID that doesn't describe an object, but which describes an
(object, feed) combination.
Are the *only* inputs to the RFC 4122 algorithm MAC address and system
clock? If there are more inputs, e.g. an arbitrary object id, you could
use them, I think.
You could of course annotate each and every item in the container with a
list of FeedIdentity objects or something like that and let each one of
those have a UUID, but that seems lame, inefficient and difficult to
keep up-to-date and in sync.
You could have a different approach, whereby you have a utility like:
def register(feed, obj):
"""Register the given object for the given feed, return a UUID
def get_object(feed, uuid):
"""Find an object given a feed and an object UUID
def get_uuid(feed, obj):
"""Find an object's UUID in the given feed
The idea here is that each time you look up an object or register it
with the utility to obtain a UUID, you pass the object *and* the feed.
Internally, this utility would need to store something like a dict (with
keys for each feed) of dicts (with keys for object UUIDs) of keyrefs.
This is a different API to zope.app.intid, and quite feed-specific but
Now, notice each method here basically takes a feed as a key. That
smells annotation/adaptation to me. So you could do this:
feed_uuid = Attribute("Feed's UUID")
title = Attribute("Feed title")
feed_uuid = None
title = u""
let's say we have a container 'parent', and we need a new feed
configured for this:
>>> KEY = 'vice.feed.metadata'
>>> annotations = IAnnotations(parent)
>>> feed = annotations.setdefault(KEY, Feed())
Now, 'feed' is a persistent object in an annotation on 'parent'. If you
need to keep feeds in a PersistentList or OOBTree under that key, do
Then you can store object UUIDs for a feed in annotations on that object.
>>> feed_annotations = IAnnotations(feed)
The problem is how to register all necessary objects with the
feed_annations. You could do this lazily (create a new UUID only when
needed, and flush old ones sometimes) or try to keep it all up to date
with events (in which case look at the events zope.app.intid needs to
keep track of).
Zope3-users mailing list