[Zope3-dev] alternate format for configuration files

Jeremy Hylton jeremy@zope.com
Fri, 22 Mar 2002 14:49:58 -0500


I've been noodling with a different way to write Zope3 configuration
files, and I'd like to get some feedback.  

We had a Sprint this week were PythonLabs & friends spent some time
writing a simple product.  It was the first time I really looked at
the .zcml files and tried to understand what they do.  I found a few
things difficult:

    - There is a lot repetition in zcml.  I often type the same name
      over and over again.  Fred showed me how to use an XML entity
      reference (a macro) but that doesn't seem like a good solution.

    - The names of tags don't have obvious meanings.

    - There is no structure to the configurations.  It's just a
      sequence of directives at the same level and in an arbitrary
      order.  We found that we had many duplicate entries in different
      files, because there was no obvious place to put some things.

    - I think that the use of attributes makes for a lot of extra
      punctuation that is hard on the eyes.  This, of course, is a
      very subjective thing.

I find that EJB deployment descriptors, which are also based on XML.
I like these descriptors better because they are organized
hierarchically.  All the directives pertaining to a particular entity
bean are contained within the entity bean's top-level tag.

The use of hierarchy means that redundant typing is avoided and that
the names can be simpler and easier to understand.

I've also made the simplifying assumption that a Python dotted path
name is relative to ZopeProducts when it's used inside a Product
directive.

I've included two files below.  The first is my proposed new syntax.
It's a rough cut.  I probably have the hierarchy wrong and I may not
being doing the XML right.  The second is the existing zcml it's based
on.

Any comments?  Is it worth pursuing this approach?

Jeremy

<Zope>
<Product>
    <Name>JobBoard</Name>
    <Description>
        A JobBoard is a moderated collection of job postings.
    </Description>

    <Interface>
        <Class>JobBoardEx.IJobList</Class>

        <View>
            <Type>Browser</Type>
            <Name>traverse</Name>
            <Factory>JobBoardEx.JobList.JobListTraverse</Factory>
        </View>

        <View>
            <Type>Browser</Type>
            <Default/>
            <Name>summary</Name>
            <Factory>JobBoardEx.JobList.JobListTraverse</Factory>

            <Protect>
                <Permission>Zope.Public</Permission>
                <Methods>index, getApprovedJobs</Methods>
            </Protect>
        </View>

	<View>
            <Type>Browser</Type>
	    <Name>NewJob</Name>
	    <Factory>JobBoardEx.NewJob.NewJob</Factory>
	    <Protect>
	        <Permission>Zope.View</Permission>
		<Methods>index, preview, waiting, getJobView, cancel,
		    home, submit</Methods>
	    </Protect>
        </View>

 	<View>
            <Type>Browser</Type>
	    <Name>ApproveJobs</Name>
	    <Factory>JobBoardEx.ApproveJobs.ApproveJobs</Factory>
	    <Protect>
	        <Permission>Zope.View</Permission>
		<Methods>index, cancel, submit</Methods>
	    </Protect>
        </View>
    </Interface>

    <Content>
        <Name>JobList</Name>
        <Class>JobBoardEx.JobList.JobList</Class>

        <ZMI-Factory>
            <Permission>Zope.Public</Permission>
        </ZMI-Factory>

        <Protect>
            <Permission>Zope.Public</Permission>
            <Methods>query</Methods>
        </Protect>

    </Content>

    <Content>
        <Name>Job</Name>
        <Class>JobBoardEx.Job.Job</Class>

        <Protect>
            <Permission>Zope.Public</Permission>
            <Methods>*</Methods>
        </Protect>

        <View>
            <Type>Browser</Type>
            <Name>JobView</Name>
            <Factory>JobBoardEx.JobView.JobView</Factory>

            <Protect>
                <Permission>Zope.Public</Permission>
                <Methods>index, simpleView, getSubmitter,
                         getSummary, getDescription, getContact
                </Methods>
            </Protect>
        </View>

    </Content>
</Product>

-----------------------------------------------------------------------
The actual config this is based on:

<zopeConfigure
         xmlns='http://namespaces.zope.org/zope'
         xmlns:zmi='http://namespaces.zope.org/zmi'
         xmlns:security='http://namespaces.zope.org/security'
         xmlns:browser='http://namespaces.zope.org/browser'
>


<!-- *** Content classes *** -->

<!-- JobList -->

<zmi:factoryFromClass 
         name=".JobBoardEx.JobList." 
         permission_id="Zope.Public"
         title="JobList"
/>

<security:protectClass 
         name=".JobBoardEx.JobList."
         permission_id="Zope.Public"
	 methods="query"
/>

<!-- Job -->

<!-- This doesn't need a factory, since jobs are always created by
     Python code. -->

<security:protectClass
	name=".JobBoardEx.Job."
	permission_id="Zope.Public"
/>


<!-- *** Views *** -->

<!-- JobListTraverser -->

<browser:view
	for=".JobBoardEx.IJobList."
        name="_traverse"
        factory=".JobBoardEx.JobList.JobListTraverser" 
/>

<!-- JobListSummaryView -->

<browser:defaultView 
        for=".JobBoardEx.IJobList."
        name="summary"
        factory=".JobBoardEx.JobListView.JobListSummaryView"
/>

<security:protectClass 
        name=".JobBoardEx.JobListView.JobListSummaryView"
        permission_id="Zope.Public"
        methods="index, getApprovedJobs"
/>

<!-- JobView -->

<browser:view for=".JobBoardEx.IJob."
              name="JobView"
              factory=".JobBoardEx.JobView."
/>

<security:protectClass
	name=".JobBoardEx.JobView."
	permission_id="Zope.View"
	methods="index, simpleView, getSubmitter, getSummary,
	         getDescription, getContact"
/>


<!-- *** Actions *** -->

<!-- NewJob -->

<browser:view
	for=".JobBoardEx.IJobList."
	name="NewJob"
	factory=".JobBoardEx.NewJob."
/>

<security:protectClass
	name=".JobBoardEx.NewJob."
	permission_id="Zope.View"
	methods="index, preview, waiting, getJobView, cancel, home, submit"
/>

<!-- ApproveJobs -->

<browser:view
	for=".JobBoardEx.IJobList."
	name="ApproveJobs"
	factory=".JobBoardEx.ApproveJobs."
/>

<security:protectClass
	name=".JobBoardEx.ApproveJobs."
	permission_id="Zope.View"
	methods="index, cancel, submit"
/>

</zopeConfigure>