Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Gary Poster wrote: On Nov 21, 2005, at 12:29 PM, Jean-Marc Orliaguet wrote: There is another place where there seems to be two different patterns too: sometimes we have: import zope.schema name = zope.schema.TextLine(...) and sometimes: from zope.schema import TextLine name = TextLine(...) FWIW, a third is from zope import schema which I often do for zope.component, zope.interface, zope.event, and zope.schema. I'm not weighing in on the style issues. I like this third style option, import the last module, and then use the dot notation, and I tend to move towards this pattern in most of my code. Sometimes of course importing the one class is more convenient. Rarely do I use the full dot notation. The benefit of the third option is that it cuts down on your imports and keeps some namespace information in your code without having to do a lot of typing nonetheless. For cases like schema and for instance, hurry.query, there are cases where the same name in the module is referenced many times in the same file, and in that case I may be more inclined to import the name directly without any module prefix. I don't think using any of these patterns is a big style problem (I'm much less opinionated about this than about code in __init__.py); it's hard to recommend a single practice, so perhaps we shouldn't. Regards, Martijn ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Martijn Faassen wrote: I don't think using any of these patterns is a big style problem (I'm much less opinionated about this than about code in __init__.py); it's hard to recommend a single practice, so perhaps we shouldn't. +1 Regards, Dominik begin:vcard fn:Dominik Huber n:Huber;Dominik email;internet:[EMAIL PROTECTED] tel;work:++41 56 534 77 30 x-mozilla-html:FALSE version:2.1 end:vcard ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Gary Poster wrote: On Nov 21, 2005, at 12:29 PM, Jean-Marc Orliaguet wrote: There is another place where there seems to be two different patterns too: sometimes we have: import zope.schema name = zope.schema.TextLine(...) and sometimes: from zope.schema import TextLine name = TextLine(...) FWIW, a third is from zope import schema which I often do for zope.component, zope.interface, zope.event, and zope.schema. I'm not weighing in on the style issues. FWIW: - For obscure things that are used only a few times in a module, and especially for things that are used only during module import, I prefer the first form. This makes the code easier to read because you don't have to refer to the imports. It also tends to make the imports shorter and easier to manage. - For popular modules like component, interface, and schema, I strongly prefer the thirs option because it keeps the imports simpler, and falls between the two extremes. A variation of the the third option that I also like for similar reasons as above occurs when importing sibling modules within the same package. For example, suppose we have modules foo and interfaces within mypackege. In foo, if I wanted to get to interfaces, I would use: from zope import interface from mypackage import interfaces class Foo: interface.implements(interfaces.IFoo) This gives us the same effect as if we had done a relative import of interfaces: import interfaces without breaking the no-relative-import rule. - I prefer the second form for well-known objects that are used a lot. For cases that fall between these extremes, I tend to prefer the first form. I think this is a matter of taste and art. I'm not very keen to legislate this. :) Jim -- Jim Fulton mailto:[EMAIL PROTECTED] Python Powered! CTO (540) 361-1714http://www.python.org Zope Corporation http://www.zope.com http://www.zope.org ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Jim Fulton wrote at 2005-11-21 09:43 -0500: ... A Python convention is that a leading underscore indicates privateness. - what about import paths inside a same package: relative or absolute? from mypackage.interfaces import ISomeInterface or: from interfaces import ISomeInterface Absolute always. Until the Python import mechanism is fixed, *always* use absolute imports. But, this will make refactoring (moving modules around in the package hierarchy) more difficult. -- Dieter ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
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. 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. If interface definitions are to be 'private' then they can be in the implementation code, but such privacy is very, very rare in practice. 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 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 tend to stick all my interfaces in interfaces.py. I believe keeping interfaces at least somewhat separate from implementation is valuable. 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. You can posit documentation tools that create such a list of all interfaces, but I like my code being inviting to all comers, whether or not they have particular tools. If you really like the other pattern of sticking interfaces together with implementation code, then perhaps don't import them into interfaces.py and don't add an interfaces.py at all. This way things will at least be clearly defined in one place only. I don't really think the public/private divide between interfaces is strong enough to worry too much about hiding certain interfaces. 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. * use interfaces.py and put interfaces there unless there's a very good reason it should be private (which is rare). Regards, Martijn ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Am 21.11.2005 um 12:15 schrieb Martijn Faassen: 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. * use interfaces.py and put interfaces there unless there's a very good reason it should be private (which is rare). I'm in support of all the suggestions Martijn has written. As a small addition I sometimes use a subdirectory interfaces with some modules, when I have many classes with different concerns in a namespace. But in the interfaces subdirectory I use __init__.py to import everything, so that for interface imports elsewhere it looks all the same. with regards, __Janko ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
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:[EMAIL PROTECTED] Python Powered! CTO (540) 361-1714http://www.python.org Zope Corporation http://www.zope.com http://www.zope.org ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Janko Hauser wrote: Am 21.11.2005 um 12:15 schrieb Martijn Faassen: 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. * use interfaces.py and put interfaces there unless there's a very good reason it should be private (which is rare). I'm in support of all the suggestions Martijn has written. As a small addition I sometimes use a subdirectory interfaces with some modules, when I have many classes with different concerns in a namespace. But in the interfaces subdirectory I use __init__.py to import everything, so that for interface imports elsewhere it looks all the same. I strongly suspect that when you do this, you should really split the package up. Jim -- Jim Fulton mailto:[EMAIL PROTECTED] Python Powered! CTO (540) 361-1714http://www.python.org Zope Corporation http://www.zope.com http://www.zope.org ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Martijn Faassen wrote: Hi there, Hi Martijn, Jean-Marc Orliaguet wrote: 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. If interface definitions are to be 'private' then they can be in the implementation code, but such privacy is very, very rare in practice. 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. This is where I'm standing: I have lots of interfaces that don't make an API. There are used by a bunch of classes to make it possible to register adapters, interface types, utilities, etc. There are more or less like marker interfaces, or schema definitions that are not supposed to be used publicly. They are private interfaces that are used to glue together components but in a way internal to the application. By having them in interfaces.py I feel that I'm making them more official than they need to be, they're is some sort of extra ceremony in it. For the public API, it feels like the right place to have them, but it is a commitment as well, and there is no way to make a statement like don't use these interfaces, they are subject to changes. I don't like the underscore imports either. I think there should be two different patterns based on the nature of the interfaces that get defined (private / public) regards /JM ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
OK, so to summarize this thread: - __init__.py files are empty unless for the convenient import of other modules located in the same package or in a subpackage? - public interfaces are stored in interfaces.py - private interfaces are written along with the implementation code - what about file names with an underscore at the beginning? They are used in zope.schema for instance - what about import paths inside a same package: relative or absolute? from mypackage.interfaces import ISomeInterface or: from interfaces import ISomeInterface regards /JM ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Jean-Marc Orliaguet wrote: OK, so to summarize this thread: - __init__.py files are empty unless for the convenient import of other modules located in the same package or in a subpackage? Actually, primarily for convenient import by external packages. - public interfaces are stored in interfaces.py - private interfaces are written along with the implementation code - what about file names with an underscore at the beginning? They are used in zope.schema for instance A Python convention is that a leading underscore indicates privateness. - what about import paths inside a same package: relative or absolute? from mypackage.interfaces import ISomeInterface or: from interfaces import ISomeInterface Absolute always. Until the Python import mechanism is fixed, *always* use absolute imports. Jim -- Jim Fulton mailto:[EMAIL PROTECTED] Python Powered! CTO (540) 361-1714http://www.python.org Zope Corporation http://www.zope.com http://www.zope.org ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Jim Fulton wrote: Jean-Marc Orliaguet wrote: OK, so to summarize this thread: - __init__.py files are empty unless for the convenient import of other modules located in the same package or in a subpackage? Actually, primarily for convenient import by external packages. yes indeed, but no cross imports between packages that are siblings. and in both cases the import is done using absolute paths. - public interfaces are stored in interfaces.py - private interfaces are written along with the implementation code - what about file names with an underscore at the beginning? They are used in zope.schema for instance A Python convention is that a leading underscore indicates privateness. but it doesn't inforce it, so another social contract for interfaces like: interfaces.py means public, otherwise it means private might do as well. - what about import paths inside a same package: relative or absolute? from mypackage.interfaces import ISomeInterface or: from interfaces import ISomeInterface Absolute always. Until the Python import mechanism is fixed, *always* use absolute imports. Jim that's definitely not the way it is currently... do a: $ grep -r from interfaces import Zope3/src /JM ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Jean-Marc Orliaguet wrote: Jim Fulton wrote: Jean-Marc Orliaguet wrote: OK, so to summarize this thread: - __init__.py files are empty unless for the convenient import of other modules located in the same package or in a subpackage? Actually, primarily for convenient import by external packages. yes indeed, but no cross imports between packages that are siblings. Huh? Why? I'm not at all sure I know what you mean. and in both cases the import is done using absolute paths. All imports should be absolute. ... Absolute always. Until the Python import mechanism is fixed, *always* use absolute imports. ... that's definitely not the way it is currently... do a: $ grep -r from interfaces import Zope3/src Dang. That code should be fixed. Jim -- Jim Fulton mailto:[EMAIL PROTECTED] Python Powered! CTO (540) 361-1714http://www.python.org Zope Corporation http://www.zope.com http://www.zope.org ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Jean-Marc Orliaguet wrote: OK, so to summarize this thread: - __init__.py files are empty unless for the convenient import of other modules located in the same package or in a subpackage? I'm typically okay with this, though I suspect it can in some cases lead to circular imports you may not otherwise get, and makes finding what's defined harder than if you directly import from the place things are defined. It does make things more convenient however, in some cases. - public interfaces are stored in interfaces.py - private interfaces are written along with the implementation code Right. And point taken from both you and Jim: sometimes you have private interfaces and you don't want to commit to supporting too much API. - what about file names with an underscore at the beginning? They are used in zope.schema for instance Hm, if I see a module with an underscore I definitely don't feel very inclined to import *anything* in it from my own code. I don't use underscore modules a lot in my code, though sometimes if some code is only implementation detail to support some other module, it's not a bad thing to do. - what about import paths inside a same package: relative or absolute? from mypackage.interfaces import ISomeInterface or: from interfaces import ISomeInterface I prefer absolute. It makes changing the package root harder, but this is not common in practice, and it is much less error-prone in the end as any namespace issues are avoided. If I call my module 'xml' and I do a relative import I may have a problem; I don't want to even think about it :). When Python grows a way to do explicit relative imports then I'll think again. Thanks for this thread! I hope this information will be put on some web page somewhere eventually. Regards, Martijn ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Jim Fulton wrote: yes indeed, but no cross imports between packages that are siblings. Huh? Why? I'm not at all sure I know what you mean. the question is what relation between the importer and the imported are OK: if I add such imports in __init__.py, I should only import from packages located in the same folder or in subfolders but not from sibling folders or from parent folders. with a directory structure like: root/ - packageA |__ packageB - packageC in packageA.__init__.py it is OK to add: from root.packageA.somefile import somemodule to make it possible for external packages to import somemodule as: from root.packageA import somemodule it is OK to write in packageA.__init__.py : from root.packageA.packageB.somefile import someothermodule to import it as: from root.packageA import someothermodule but it is not OK to put the same imports in packageC (a sibling), which be some sort or cross import between packages that are not parent / child to one another. This easily leads to circular imports. so what I mean is : parents import from children to make it possible for external packages to import directly from the parents. /JM ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
Jean-Marc Orliaguet wrote: Jim Fulton wrote: yes indeed, but no cross imports between packages that are siblings. Huh? Why? I'm not at all sure I know what you mean. the question is what relation between the importer and the imported are OK: if I add such imports in __init__.py, I should only import from packages located in the same folder or in subfolders but not from sibling folders or from parent folders. Ah. Right. Agreed. with a directory structure like: root/ - packageA |__ packageB - packageC in packageA.__init__.py it is OK to add: from root.packageA.somefile import somemodule to make it possible for external packages to import somemodule as: from root.packageA import somemodule it is OK to write in packageA.__init__.py : from root.packageA.packageB.somefile import someothermodule to import it as: from root.packageA import someothermodule but it is not OK to put the same imports in packageC (a sibling), which be some sort or cross import between packages that are not parent / child to one another. This easily leads to circular imports. so what I mean is : parents import from children to make it possible for external packages to import directly from the parents. Yup. Jim -- Jim Fulton mailto:[EMAIL PROTECTED] Python Powered! CTO (540) 361-1714http://www.python.org Zope Corporation http://www.zope.com http://www.zope.org ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
There is another place where there seems to be two different patterns too: sometimes we have: import zope.schema name = zope.schema.TextLine(...) and sometimes: from zope.schema import TextLine name = TextLine(...) any reason to use one or the other (speed, verbosity, avoiding circular imports, ...) ? /JM ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com
Re: [Zope3-dev] __init__.py interfaces.py guidelines?
On Nov 21, 2005, at 12:29 PM, Jean-Marc Orliaguet wrote: There is another place where there seems to be two different patterns too: sometimes we have: import zope.schema name = zope.schema.TextLine(...) and sometimes: from zope.schema import TextLine name = TextLine(...) FWIW, a third is from zope import schema which I often do for zope.component, zope.interface, zope.event, and zope.schema. I'm not weighing in on the style issues. Gary ___ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com