[Zope3-dev] __init__.py interfaces.py guidelines?

Jim Fulton jim at zope.com
Mon Nov 21 07:27:59 EST 2005


Martijn Faassen wrote:
> Hi there,
> 
> Jean-Marc Orliaguet wrote:
>  > are there any guidelines / best practises for setting the contents of
> 
>> __init__.py, interfaces.py, and the packages that they import or that 
>> they expose? there are too many alternatives and too many ways of 
>> ending up doing circular imports and I'd like to have a consistent 
>> pattern for reducing that risk.
>>
>> but there doesn't seem to be a 100% clear pattern to follow when 
>> looking at the zope3 code base:
>>
>> some packages in have all the implementation code in __init__.py, 
>> others have it in a file and the imports are done in __init__.py, 
>> others import files starting with an underscore (to make them private 
>> I suppose).
> 
> 
> I personally very much prefer __init__.py to be as empty as possible. I 
> like namespace packages. For me it's always a doubletake when I realize 
> most of the implementation of some Zope 3 package I'm trying to 
> understand is actually hiding out in __init__.py, so I don't like this 
> practice.

I agree.  We used to make an exception for packages that *only* had one
.py file, but I don't really see having many of these, so I'd prefer
empty __init__, except when exporting names for import convenience.

>> some packages have an interfaces.py file others have a "interfaces" 
>> folder, others have the interface definitions in the implementation 
>> code itself ...
> 
> 
> The pattern changed over time during Zope 3 development. In my current 
> opinion, interfaces.py should usually be able to accomodate all the 
> interfaces of a package.

I agree.

 > If interface definitions are to be 'private'
> then they can be in the implementation code, but such privacy is very, 
> very rare in practice.

In particular, I'd like to promote the idea that interfaces modules
are only for public interfaces.  These are commitments.  Interfaces
used internally and subject to change should not be put in these modules.

>> Jim mentioned to me that only public and official interface 
>> definitions should be listed in 'interfaces', the others should be 
>> defined inline with the implementation - are there guidelines to follow?
> 
> 
> Don't know. I think the best rule would be to make the interface public 
> unless you have a very good reason not to do so, not the other way around.

I disagree.  Public interfaces are commitments. The fewer commitments
the better.

>> I like the inline option because it reduces the amount of imports and 
>> the risk for import cycles. Does it mean that interfaces should be 
>> defined inline with the code and those that are "official" be imported 
>> from intertaces.py? It sounds like a good pattern.
> 
> 
> With this pattern, the chances are increased people will point to the 
> interface through two different paths, and the chances are increased 
> that people forget to import things to interfaces.py even though they 
> should. It's also an extra indirection; people looking for the interface 
> referenced in some ZCML file discover that in fact they need to go to 
> another module yet again when they look it up.

I agree that public interfaces should be in interfaces.py.

In general, I hate it when people import things from modules other
than the modules in which they were defined.  The only exception to
this is packages, which should just be about namespaces.

> I tend to stick all my interfaces in interfaces.py. I believe keeping 
> interfaces at least somewhat separate from implementation is valuable. 

Yes

> It also makes for an easy place to go to to actually find out what 
> interfaces are defined by a package -- I don't have to go read all the 
> source code to see what interfaces exist.

If they aren't in interfaces.py, their none of your business anyway.

...

> My recommendations for any guidelines would be:
> 
> * use namespace packages, so nothing (or very minimal stuff only, like a 
> few imports) in __init__.py. I think this is recommended practice 
> outside of Zope 3 as well, so we should stick with this. Twisted seems 
> to have small or empty __init__.py packages for instance, and so does 
> PEAK, to compare with some other large frameworks in Python.

Yup

> * use interfaces.py and put interfaces there unless there's a very good 
> reason it should be private (which is rare).

Agreed. BTW, an alternative to private interfaces is to register
things for classes. Unfortunately, this doesn't always work.  You may need
private schemas for UI purposes.  Perhaps formlib's ability to define forms
without schemas will make this less important.  Also, there seems to be a bug
in proxy interface management that sometimes causes trouble when components
are registered for classes. I need to look into this.

Jim

-- 
Jim Fulton           mailto:jim at zope.com       Python Powered!
CTO                  (540) 361-1714            http://www.python.org
Zope Corporation     http://www.zope.com       http://www.zope.org


More information about the Zope3-dev mailing list