Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Zope: Dev

traversal: different with and without a request

 

 

Zope dev RSS feed   Index | Next | Previous | View Threaded


ct at gocept

Oct 15, 2008, 8:42 AM

Post #1 of 15 (1514 views)
Permalink
traversal: different with and without a request

Hi,

we stumbled over an annoyance that took a while to debug:

Writing an ITraversable, we used zope.traversing.api.traverse() in a
test to verify our code. We registered the ITraversable as an
(non-multi) adapter and ended up with a working test.

In the actual system, we found that the traversable would not be used.
After investigation we found a conditional branch in the traverse()
function which would look for a multi-adapter if a request was around,
and a regular adapter if not.

We didn't anticipate this difference and it cost us some time, so we
wonder whether this has to be the way it is, or whether this could be
changed to behave more obvious and consistent.

Christian and Wolfgang

--
Christian Theune · ct [at] gocept
gocept gmbh & co. kg · forsterstraße 29 · 06112 halle (saale) · germany
http://gocept.com · tel +49 345 1229889 7 · fax +49 345 1229889 1
Zope and Plone consulting and development
Attachments: signature.asc (0.19 KB)


philipp at weitershausen

Oct 15, 2008, 9:02 AM

Post #2 of 15 (1476 views)
Permalink
Re: traversal: different with and without a request [In reply to]

Christian Theune wrote:
> we stumbled over an annoyance that took a while to debug:
>
> Writing an ITraversable, we used zope.traversing.api.traverse() in a
> test to verify our code. We registered the ITraversable as an
> (non-multi) adapter and ended up with a working test.
>
> In the actual system, we found that the traversable would not be used.
> After investigation we found a conditional branch in the traverse()
> function which would look for a multi-adapter if a request was around,
> and a regular adapter if not.
>
> We didn't anticipate this difference and it cost us some time, so we
> wonder whether this has to be the way it is, or whether this could be
> changed to behave more obvious and consistent.

zope.traversing is a mess.

First of all, its name is quite misleading. It should really be called
'zope.resolvepath' because it resolves TALES-like object paths. In fact,
it's pretty much only used by the PageTemplate machinery to hook it up
to the TALES engine (with one exception, see below). The request
shouldn't really be necessary for this kind of path resolution, I think.
The conditional multi-adaption sounds like a DWIM feature that I would
consider one of our many mistakes that we made in the beginnings of our
using the Component Architecture.

There is a process that actually needs the request and this process is
what I call traversal: breaking down a URL and finding a publishable
object. zope.traversing has (almost) nothing to do with it, the real
kind of traversal happens in the publisher and facilitates
IPublishTraverse adapters (rather than ITraversable). The only case when
the two kinds of "traversal" are intermingled is when ++namespaces++ are
involved. Then IPublishTraverse-style traversal uses ITraversable
adapters. This has long been considered a mistake but was never fixed.

I'm not sure my explanation are helpful ;). Did I mention it was a mess?
_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


marius at gedmin

Oct 15, 2008, 10:14 AM

Post #3 of 15 (1477 views)
Permalink
Re: traversal: different with and without a request [In reply to]

On Wed, Oct 15, 2008 at 06:02:55PM +0200, Philipp von Weitershausen wrote:
> Christian Theune wrote:
> > we stumbled over an annoyance that took a while to debug:
> >
> > Writing an ITraversable, we used zope.traversing.api.traverse() in a
> > test to verify our code. We registered the ITraversable as an
> > (non-multi) adapter and ended up with a working test.
> >
> > In the actual system, we found that the traversable would not be used.
> > After investigation we found a conditional branch in the traverse()
> > function which would look for a multi-adapter if a request was around,
> > and a regular adapter if not.
> >
> > We didn't anticipate this difference and it cost us some time, so we
> > wonder whether this has to be the way it is, or whether this could be
> > changed to behave more obvious and consistent.
>
> zope.traversing is a mess.

You can drop the ".traversing" bit and it'll still be true.

On the other hand Perl is a mess, yet it is quite successful.

> First of all, its name is quite misleading. It should really be called
> 'zope.resolvepath' because it resolves TALES-like object paths. In fact,
> it's pretty much only used by the PageTemplate machinery to hook it up
> to the TALES engine (with one exception, see below). The request
> shouldn't really be necessary for this kind of path resolution, I think.
> The conditional multi-adaption sounds like a DWIM feature that I would
> consider one of our many mistakes that we made in the beginnings of our
> using the Component Architecture.
>
> There is a process that actually needs the request and this process is
> what I call traversal: breaking down a URL and finding a publishable
> object.

I've seen these two called object traversal and URL traversal
respectively.

> zope.traversing has (almost) nothing to do with it, the real
> kind of traversal happens in the publisher and facilitates
> IPublishTraverse adapters (rather than ITraversable). The only case when
> the two kinds of "traversal" are intermingled is when ++namespaces++ are
> involved. Then IPublishTraverse-style traversal uses ITraversable
> adapters. This has long been considered a mistake but was never fixed.
>
> I'm not sure my explanation are helpful ;). Did I mention it was a mess?

Marius Gedminas
--
Please do not even think about automatically normalizing file names
anywhere. There is absolutely no need for introducing such nonsense, and
deviating from the POSIX requirement that filenames be opaque byte
strings is a Bad Idea[TM] (also known as NTFS).
-- Markus Kuhn
Attachments: signature.asc (0.18 KB)


shane at hathawaymix

Oct 15, 2008, 10:24 AM

Post #4 of 15 (1486 views)
Permalink
Re: traversal: different with and without a request [In reply to]

Philipp von Weitershausen wrote:
> First of all, its name is quite misleading. It should really be called
> 'zope.resolvepath' because it resolves TALES-like object paths. In fact,
> it's pretty much only used by the PageTemplate machinery to hook it up
> to the TALES engine (with one exception, see below). The request
> shouldn't really be necessary for this kind of path resolution, I think.
> The conditional multi-adaption sounds like a DWIM feature that I would
> consider one of our many mistakes that we made in the beginnings of our
> using the Component Architecture.
>
> There is a process that actually needs the request and this process is
> what I call traversal: breaking down a URL and finding a publishable
> object. zope.traversing has (almost) nothing to do with it, the real
> kind of traversal happens in the publisher and facilitates
> IPublishTraverse adapters (rather than ITraversable). The only case when
> the two kinds of "traversal" are intermingled is when ++namespaces++ are
> involved. Then IPublishTraverse-style traversal uses ITraversable
> adapters. This has long been considered a mistake but was never fixed.
>
> I'm not sure my explanation are helpful ;). Did I mention it was a mess?

This is very useful information that would have saved me a lot of
confusion years ago. Is this written somewhere permanent, at least?
Everyone who does anything at all with ITraversable or IPublishTraverse
needs to understand this, at least until traversal is redesigned.

Shane

_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


philipp at weitershausen

Oct 15, 2008, 11:11 AM

Post #5 of 15 (1469 views)
Permalink
Re: traversal: different with and without a request [In reply to]

El 15 Oct 2008, a las 19:24 , Shane Hathaway escribió:
> Philipp von Weitershausen wrote:
>> First of all, its name is quite misleading. It should really be
>> called
>> 'zope.resolvepath' because it resolves TALES-like object paths. In
>> fact,
>> it's pretty much only used by the PageTemplate machinery to hook it
>> up
>> to the TALES engine (with one exception, see below). The request
>> shouldn't really be necessary for this kind of path resolution, I
>> think.
>> The conditional multi-adaption sounds like a DWIM feature that I
>> would
>> consider one of our many mistakes that we made in the beginnings of
>> our
>> using the Component Architecture.
>>
>> There is a process that actually needs the request and this process
>> is
>> what I call traversal: breaking down a URL and finding a publishable
>> object. zope.traversing has (almost) nothing to do with it, the real
>> kind of traversal happens in the publisher and facilitates
>> IPublishTraverse adapters (rather than ITraversable). The only case
>> when
>> the two kinds of "traversal" are intermingled is when ++namespaces+
>> + are
>> involved. Then IPublishTraverse-style traversal uses ITraversable
>> adapters. This has long been considered a mistake but was never
>> fixed.
>>
>> I'm not sure my explanation are helpful ;). Did I mention it was a
>> mess?
>
> This is very useful information that would have saved me a lot of
> confusion years ago. Is this written somewhere permanent, at least?

Not that I know of. The documentation of zope.traversing would
probably be a good place to put it.

_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


dieter at handshake

Oct 15, 2008, 11:34 AM

Post #6 of 15 (1484 views)
Permalink
Re: traversal: different with and without a request [In reply to]

Christian Theune wrote at 2008-10-15 17:42 +0200:
>we stumbled over an annoyance that took a while to debug:
>
>Writing an ITraversable, we used zope.traversing.api.traverse() in a
>test to verify our code. We registered the ITraversable as an
>(non-multi) adapter and ended up with a working test.
>
>In the actual system, we found that the traversable would not be used.
>After investigation we found a conditional branch in the traverse()
>function which would look for a multi-adapter if a request was around,
>and a regular adapter if not.
>
>We didn't anticipate this difference and it cost us some time, so we
>wonder whether this has to be the way it is, or whether this could be
>changed to behave more obvious and consistent.

The request may have important information to control traversal, e.g.
a layer. On the other hand, when no request is available (e.g. in a
script), you cannot use one. Thus, the current behaviour may cover
useful use cases.

Maybe, you should not trust your tests stupidly -- unless they emulate
the actual system sufficently ;-)



--
Dieter
_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


philipp at weitershausen

Oct 15, 2008, 12:16 PM

Post #7 of 15 (1479 views)
Permalink
Re: traversal: different with and without a request [In reply to]

Dieter Maurer wrote:
> Christian Theune wrote at 2008-10-15 17:42 +0200:
>> we stumbled over an annoyance that took a while to debug:
>>
>> Writing an ITraversable, we used zope.traversing.api.traverse() in a
>> test to verify our code. We registered the ITraversable as an
>> (non-multi) adapter and ended up with a working test.
>>
>> In the actual system, we found that the traversable would not be used.
>> After investigation we found a conditional branch in the traverse()
>> function which would look for a multi-adapter if a request was around,
>> and a regular adapter if not.
>>
>> We didn't anticipate this difference and it cost us some time, so we
>> wonder whether this has to be the way it is, or whether this could be
>> changed to behave more obvious and consistent.
>
> The request may have important information to control traversal, e.g.
> a layer. On the other hand, when no request is available (e.g. in a
> script), you cannot use one. Thus, the current behaviour may cover
> useful use cases.

True. The request (=layer) is indeed necessary to resolve paths in the
++view++ aka @@ namespace.
_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


ct at gocept

Oct 15, 2008, 12:35 PM

Post #8 of 15 (1476 views)
Permalink
Re: traversal: different with and without a request [In reply to]

On Wed, 2008-10-15 at 20:34 +0200, Dieter Maurer wrote:
> Christian Theune wrote at 2008-10-15 17:42 +0200:
> >we stumbled over an annoyance that took a while to debug:
> >
> >Writing an ITraversable, we used zope.traversing.api.traverse() in a
> >test to verify our code. We registered the ITraversable as an
> >(non-multi) adapter and ended up with a working test.
> >
> >In the actual system, we found that the traversable would not be used.
> >After investigation we found a conditional branch in the traverse()
> >function which would look for a multi-adapter if a request was around,
> >and a regular adapter if not.
> >
> >We didn't anticipate this difference and it cost us some time, so we
> >wonder whether this has to be the way it is, or whether this could be
> >changed to behave more obvious and consistent.
>
> The request may have important information to control traversal, e.g.
> a layer. On the other hand, when no request is available (e.g. in a
> script), you cannot use one. Thus, the current behaviour may cover
> useful use cases.

I'm not arguing that the behaviour wouldn't be useful in some cases, I'm
just arguing it's not obvious. Philipp's pointer to the whole area being
messy is correct. This might be a good sprint topic.

> Maybe, you should not trust your tests stupidly -- unless they emulate
> the actual system sufficently ;-)

I only found this because I'm not trusting my tests blindly and I both
tested automatically and manually to verify that the test actually does
test what I want. ;)

Christian

--
Christian Theune · ct [at] gocept
gocept gmbh & co. kg · forsterstraße 29 · 06112 halle (saale) · germany
http://gocept.com · tel +49 345 1229889 7 · fax +49 345 1229889 1
Zope and Plone consulting and development
Attachments: signature.asc (0.19 KB)


ct at gocept

Oct 17, 2008, 1:37 AM

Post #9 of 15 (1452 views)
Permalink
Re: traversal: different with and without a request [In reply to]

On Wed, 2008-10-15 at 18:02 +0200, Philipp von Weitershausen wrote:
> Christian Theune wrote:
> > we stumbled over an annoyance that took a while to debug:
> >
> > Writing an ITraversable, we used zope.traversing.api.traverse() in a
> > test to verify our code. We registered the ITraversable as an
> > (non-multi) adapter and ended up with a working test.
> >
> > In the actual system, we found that the traversable would not be used.
> > After investigation we found a conditional branch in the traverse()
> > function which would look for a multi-adapter if a request was around,
> > and a regular adapter if not.
> >
> > We didn't anticipate this difference and it cost us some time, so we
> > wonder whether this has to be the way it is, or whether this could be
> > changed to behave more obvious and consistent.
>
> zope.traversing is a mess.
>
> First of all, its name is quite misleading. It should really be called
> 'zope.resolvepath' because it resolves TALES-like object paths. In fact,
> it's pretty much only used by the PageTemplate machinery to hook it up
> to the TALES engine (with one exception, see below). The request
> shouldn't really be necessary for this kind of path resolution, I think.
> The conditional multi-adaption sounds like a DWIM feature that I would
> consider one of our many mistakes that we made in the beginnings of our
> using the Component Architecture.
>
> There is a process that actually needs the request and this process is
> what I call traversal: breaking down a URL and finding a publishable
> object. zope.traversing has (almost) nothing to do with it, the real
> kind of traversal happens in the publisher and facilitates
> IPublishTraverse adapters (rather than ITraversable). The only case when
> the two kinds of "traversal" are intermingled is when ++namespaces++ are
> involved. Then IPublishTraverse-style traversal uses ITraversable
> adapters. This has long been considered a mistake but was never fixed.

URL traversal makes use of zope.traversing though.

--
Christian Theune · ct [at] gocept
gocept gmbh & co. kg · forsterstraße 29 · 06112 halle (saale) · germany
http://gocept.com · tel +49 345 1229889 7 · fax +49 345 1229889 1
Zope and Plone consulting and development
Attachments: signature.asc (0.19 KB)


philipp at weitershausen

Oct 17, 2008, 1:43 AM

Post #10 of 15 (1445 views)
Permalink
Re: traversal: different with and without a request [In reply to]

El 17 Oct 2008, a las 10:37 , Christian Theune escribió:
>> There is a process that actually needs the request and this process
>> is
>> what I call traversal: breaking down a URL and finding a publishable
>> object. zope.traversing has (almost) nothing to do with it, the real
>> kind of traversal happens in the publisher and facilitates
>> IPublishTraverse adapters (rather than ITraversable). The only case
>> when
>> the two kinds of "traversal" are intermingled is when ++namespaces+
>> + are
>> involved. Then IPublishTraverse-style traversal uses ITraversable
>> adapters. This has long been considered a mistake but was never
>> fixed.
>
> URL traversal makes use of zope.traversing though.

Yes, but only in the special case of ++namespace++ traversal. This is
what I said in the above paragraph already. zope.publisher itself
doesn't depend on zope.traversing and the default publication
implementation in zope.app.publication uses zope.traversing only for +
+namespace++ names (see usage of zope.traversing.namespace.nsParse in
zope
.app.publication.publicationtraverse.PublicationTraverse.traverseName).

_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


jim at zope

Oct 17, 2008, 6:02 AM

Post #11 of 15 (1461 views)
Permalink
Re: traversal: different with and without a request [In reply to]

On Oct 15, 2008, at 12:02 PM, Philipp von Weitershausen wrote:

> Christian Theune wrote:
>> we stumbled over an annoyance that took a while to debug:
>>
>> Writing an ITraversable, we used zope.traversing.api.traverse() in a
>> test to verify our code. We registered the ITraversable as an
>> (non-multi) adapter and ended up with a working test.
>>
>> In the actual system, we found that the traversable would not be
>> used.
>> After investigation we found a conditional branch in the traverse()
>> function which would look for a multi-adapter if a request was
>> around,
>> and a regular adapter if not.
>>
>> We didn't anticipate this difference and it cost us some time, so we
>> wonder whether this has to be the way it is, or whether this could be
>> changed to behave more obvious and consistent.
>
> zope.traversing is a mess.

That's a bit strong, but essentially true. It zope.traversing
deserves to be reworked if anyone has the time and energy.


> First of all, its name is quite misleading. It should really be
> called
> 'zope.resolvepath' because it resolves TALES-like object paths. In
> fact,
> it's pretty much only used by the PageTemplate machinery to hook it up
> to the TALES engine (with one exception, see below).

Historical note. Until we decided to use the location framework and
eschew traversal proxies, is was much more widely used.

It would be nice to deprecate zope.traversing and fold it into
zope.app.pagetemplate.

> The request
> shouldn't really be necessary for this kind of path resolution, I
> think.

It's needed for looking up views and resources, both of which are
commonly looked up in ZPT.

> The conditional multi-adaption sounds like a DWIM feature that I would
> consider one of our many mistakes that we made in the beginnings of
> our
> using the Component Architecture.

<shrug />

I'll note that the fix, in the context of ZPT is to always to a multi-
adapter lookup using the request.


> There is a process that actually needs the request and this process is
> what I call traversal: breaking down a URL and finding a publishable
> object. zope.traversing has (almost) nothing to do with it, the real
> kind of traversal happens in the publisher and facilitates
> IPublishTraverse adapters (rather than ITraversable).

Yup.

> The only case when
> the two kinds of "traversal" are intermingled is when ++namespaces++
> are
> involved. Then IPublishTraverse-style traversal uses ITraversable
> adapters. This has long been considered a mistake but was never fixed.

Yup. I would go so far as to call it a bug. Somebody please fix it. :)

Jim

--
Jim Fulton
Zope Corporation


_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


philipp at weitershausen

Oct 17, 2008, 6:16 AM

Post #12 of 15 (1457 views)
Permalink
Re: traversal: different with and without a request [In reply to]

El 17 Oct 2008, a las 15:02 , Jim Fulton escribió:
>> First of all, its name is quite misleading. It should really be
>> called
>> 'zope.resolvepath' because it resolves TALES-like object paths. In
>> fact,
>> it's pretty much only used by the PageTemplate machinery to hook it
>> up
>> to the TALES engine (with one exception, see below).
>
> Historical note. Until we decided to use the location framework and
> eschew traversal proxies, is was much more widely used.
>
> It would be nice to deprecate zope.traversing and fold it into
> zope.app.pagetemplate.

+1

>> The request shouldn't really be necessary for this kind of path
>> resolution, I think.
>
> It's needed for looking up views and resources, both of which are
> commonly looked up in ZPT.

Yeah, I forgot about that.

>> The conditional multi-adaption sounds like a DWIM feature that I
>> would
>> consider one of our many mistakes that we made in the beginnings of
>> our
>> using the Component Architecture.
>
> <shrug />
>
> I'll note that the fix, in the context of ZPT is to always to a
> multi-adapter lookup using the request.

Right. I'm fine with it always being a multi-adapter look-up.

_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


srichter at cosmos

Oct 17, 2008, 10:13 AM

Post #13 of 15 (1445 views)
Permalink
Re: traversal: different with and without a request [In reply to]

On Friday 17 October 2008, Jim Fulton wrote:
> It would be nice to deprecate zope.traversing and fold it into  
> zope.app.pagetemplate.

Just skimming the thread, wouldn't this make it harder for us to integrate
z3c.pt, which also needs those traversal APIs?

Regards,
Stephan
--
Stephan Richter
Web Software Design, Development and Training
Google me. "Zope Stephan Richter"
_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


jim at zope

Oct 17, 2008, 10:15 AM

Post #14 of 15 (1452 views)
Permalink
Re: traversal: different with and without a request [In reply to]

On Oct 17, 2008, at 1:13 PM, Stephan Richter wrote:

> On Friday 17 October 2008, Jim Fulton wrote:
>> It would be nice to deprecate zope.traversing and fold it into
>> zope.app.pagetemplate.
>
> Just skimming the thread, wouldn't this make it harder for us to
> integrate
> z3c.pt, which also needs those traversal APIs?


Yup. Actually, this wants to be in zope.tales. Does z3c.pt use
zope.tales?

Jim

--
Jim Fulton
Zope Corporation


_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )


wichert at wiggy

Oct 17, 2008, 4:00 PM

Post #15 of 15 (1457 views)
Permalink
Re: traversal: different with and without a request [In reply to]

Previously Jim Fulton wrote:
>
> On Oct 17, 2008, at 1:13 PM, Stephan Richter wrote:
>
> > On Friday 17 October 2008, Jim Fulton wrote:
> >> It would be nice to deprecate zope.traversing and fold it into
> >> zope.app.pagetemplate.
> >
> > Just skimming the thread, wouldn't this make it harder for us to
> > integrate
> > z3c.pt, which also needs those traversal APIs?
>
>
> Yup. Actually, this wants to be in zope.tales. Does z3c.pt use
> zope.tales?

No.

Wichert.

--
Wichert Akkerman <wichert [at] wiggy> It is simple to make things.
http://www.wiggy.net/ It is hard to make things simple.
_______________________________________________
Zope-Dev maillist - Zope-Dev [at] zope
http://mail.zope.org/mailman/listinfo/zope-dev
** No cross posts or HTML encoding! **
(Related lists -
http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )

Zope dev RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.