[PEAK] peak.web in October
Phillip J. Eby
pje at telecommunity.com
Fri Oct 22 22:54:51 EDT 2004
At 11:12 AM 10/5/04 -0400, Phillip J. Eby wrote:
>As some of you may have noticed from last week's flurry of checkins, I'm
>finally doing the peak.web refactoring I've been talking about off and on
>for the last several months. At this point, the plan is to complete at
>least these peak.web "Tier 1" features this month:
>
>[snip]
> * Overhaul PWT to use the new this:/content: attribute mechanism
> (Started; the needed XML parser is in a draft status)
>
> * Design and implement an XML dialect for site configuration, similar in
> functionality to Zope 3's ZCML, but with the capability of structuring a
> site or application's URL layout and "local" as well as "global"
> configuration. (Not started, but will use the same draft XML parser)
>
> * Create view registration mechanisms for both .ini files and .xml files
A quick status update... the main PWT overhaul is complete, but there are
numerous features still to be added. Specifically, most of the ones from
my "PWT: layout, macros, parameters, etc." post on Tuesday. However, as of
today, I've implemented the '/params' mechanism, the ability to invoke a
DOMlet from within another template, and the single vs. multi-value
parameter checking. I've also done some refactoring to support adding the
various page-level options (page-layout, fragment-layout, content-type, etc.
The XML sitemap dialect is now basically complete. I ended up changing
some of the attribute names around, and/or made slight changes to how they
worked. For example, to include one sitemap in another, you use a
'<location>' with an 'extends' attribute, that's a relative URL to the
sitemap you want to include. Anyway, there are a number of quirks and
limitations with respect to inclusion, that I still need to sort out. For
the most part, you can't really override anything except the class of the
location when you reuse a site map; you're pretty much limited to additions
for the moment. Still, this works for simple reuse of sitemap
segments. Also, I decided to forego the 'interfaces' attribute of the
'<allow>' element, as I couldn't settle on final semantics for it, and it's
just a convenient way to specify multiple attributes anyway, so you can
just list individual attributes for now. Finally, there is no easy way to
define views or pages on a location.
Apart from these missing features and limitations/quirks, peak.web is now
basically in its new shape, from a functional perspective. However, it
still has plenty of internal refactoring to go, as those missing features
are added and the quirks taken out. In fact, the main reason the features
aren't there, and the quirks are, is because this is the best I could do
without the needed refactorings. However, with the bulk of the
functionality in place, I can now do those refactorings backed up by a
broad array of tests.
Including functional tests, which may be quite informative if you want a
glimpse at what the future of peak.web looks like. For example, here's a
segment from one of the test sitemaps:
<location id="root" config="configure-test.ini">
<container object="{'123':123, 'abc':'abc', 'both':[123,'abc']}"/>
<content type="object">
<import module="peak.web.templates" as="pwt"/>
<view name="repr" expr="`ob`"/>
<view name="test-params"
expr="pwt.Replace(dataSpec=web.TraversalPath('/params/foo'))" />
<view name="index_html" resource="peak.web.tests/showobject"/>
</content>
<content type="int" location="repr at root" />
<content type="str" location="value at root">
<view name="value" expr="ob"/>
</content>
<content type="list">
<view name="index_html" resource="peak.web.tests/showlist"/>
</content>
</location>
The above is a simple site with only three working URLS: '123', 'abc', and
'both'. All objects have a 'repr' view that returns the repr() of the
object. Integers' absolute URL is computed using their repr, while
strings' absolute location is computed using their value. Two simple PWT
templates are used to render the default view (index_html) of objects in
general, and lists in particular.
If you want to see what this looks like in your browser, you can do the
following with a current CVS checkout of PEAK:
peak launch ref:sitemap at pkgfile:peak.web.tests/test-sitemap.xml
Or you can run it under CGI/FastCGI/etc. by replacing 'launch' with the
appropriate alternative command. The same will be true for any sitemap
files you create for your own applications. Essentially, you'll prepend
'ref:sitemap@' to a URL that points to your XML sitemap file. Anyway, if
you're running the 'test-sitemap', keep in mind that its root application
URL has no default view, so you'll have to add '123', 'abc', or 'both' onto
the end of the URL that comes up in your browser, in order to see the test
output.
Anyway, if you're creating your own sitemap, you can use the 'class'
attribute of 'location' tags to specify the class you'd like to use for a
given location. It should subclass 'web.Location', or at least implement
'web.IConfigurableLocation'. You can use a 'config' attribute to load an
.ini file into the location once it's created. The attribute can give
either an absolute URL, or one that's relative to the sitemap's URL.
The really awesome thing about this, now that I'm actually seeing it work,
is that it's looking like you can really create quite an elaborate
application, using only the templates, a sitemap, and a little bit of
Python glue to marry the UI to whatever your "domain model" is. And the
parts that make up that application are all resuable, skinnable, etc., to
make new apps. Indeed, I'm thinking that I could possibly make a simple
documentation tool, along the lines of 'pydoc'/'peak help', using hardly
anything but templates and a sitemap to configure the views.
In theory, it should be just as easy in Zope X3 to do these things, but in
practice I don't know if that's really the case, since as far as I know
ZCML doesn't let you really create a site map. I believe you have to do
that part actually in ZODB, not the file system. But maybe somebody who's
worked with Zope X3 more recently than I (Ulrich, perhaps?) can comment on
that.
Certainly, peak.web's support for "Specialists" is going to be
better. Basically, to create a specialist, you just do something like:
<location name="Customers" id="myapp.customers">
<import module="myapp.storage" as="stg" />
<import module="myapp.model" as="mdl" />
<container object="stg.CustomerDM()" />
<content type="mdl.Customer" location="cust_id at myapp.customers">
<view name="...etc...
</content>
</location>
And voila, there's your specialist. Well, it's missing any class-level
methods, but it's basically there. The above creates a location called
'Customers' inside the current location of the sitemap, and registers it
with a "location id" of 'myapp.customers', so that it can be found by any
component that needs to refer to its location. The location uses a
'CustomerDM' as one of its containers, so going to 'Customers/foo' will
attempt to look up 'foo' in the DM.
And when it finds a Customer object, then views defined in the 'content'
section will apply. (Normally, you'll define these content views at the
application's top level, or in an .ini file, rather than restricting them
to object under a particular location, but this is just an illustration.)
The 'location="cust_id at myapp.customers"' attribute says, "if you need the
URL of a mdl.Customer object, take its 'cust_id' and append it to the URL
of the location whose ID is 'myapp.customers'". In this case, that
location is the 'Customers' location, so if you have a Customer with a
'cust_id' of 'foo', then its canonical URL will be 'Customers/foo'
(preceded, of course, by whatever's the canonical URL of the parent
component of the 'Customers' location). Thus, whenever a template needs to
generate a link to a customer object, it can use something like:
<...this:url.href="." content:replace="fullname">Customer's full name
will go here</a>
And a link to e.g. '../../Customers/foo' might be generated, depending on
the current URL, and assuming that the template's current target object is
a mdl.Customer at this point in the template. Notice, by the way, that
peak.web generates relative URLs for links whenever possible, in order to
make it easier to generate "static file" sites that can be browsed
regardless of their current physical URL (in e.g. the filesystem).
Anyway, things are looking pretty spiffy, but I expect I'll be spending a
good bit of time to get this functional tier wrapped up by Halloween, as
there are still many quirks to remove and a lot of PWT features yet to be
added.
More information about the PEAK
mailing list