[sugar] Re: Python Style Guide

Ian Bicking ianb
Fri Nov 17 11:41:08 EST 2006


Johan Dahlin wrote:
>>>  >__init__.py files should generally contain no substantive code.
>>> Instead they should import from >other modules. Importing from other
>>> modules is done so that a package can provide a front-facing >set of
>>> objects and functions it exports, without exposing each of the
>>> internal modules in the >package. Note however that this causes the
>>> submodules to be eagerly imported; if this is likely to >cause
>>> unnecessary overhead then the import in __init__.py should be
>>> reconsidered.
>>>
>>> Can you give an example of this? I think it would be useful to have it
>>> on the guide too. Is it part of PEP-8 in any way?
>> This was my addition.  __init__.py can be a little tricky, because it
>> will swallow ImportErrors and maybe some other errors.  (This way if you
>> __init__.py is broken, the entire package won't become unusable.)  For
>> this reason I prefer not to put too much into those files.  Also I must
>> admit an Emacs bias, where I like it when files tend to have more unique
>> names than __init__; but I that's not a real justification ;)
> 
> As an fellow Emacs user I used to share your opinion about unique filenames
> until I found that default emacs configuration is utterly broken.
> Add this to your .emacs and you'll be happy:
> 
> (setq uniquify-buffer-name-style 'post-forward-angle-brackets)

Huh; reading this page that does indeed sound like a better style 
http://www.delorie.com/gnu/docs/emacs/emacs_180.html -- but it isn't 
making any effect in my Emacs, and C-H v doesn't give any documentation 
for it :(

> However I consider unique filename a plus but not a necessity, it's nice to
> be able to refer to a file, eg: 'I think the bug is in base.py' without
> having to mention the domain/context of the module.

Yes; this is the more convincing argument.

>> As for the imports, if you have:
>>
>>   mypkg/__init__.py
>>   mypkg/main.py
>>
>> And in __init__.py you have:
>>
>>   from mypkg.main import MyProvider
>>
>> Then other people can do:
>>
>>   from mypkg import MyProvider
>>
> 
> In generally I dislike this kind of aliasing, because it makes it breaks
> the assumption that an object a.b.c can be found in a/b/c.py, eg adding
> a consistent import style makes it possible to map:
> 
> from foo.bar.baz import noogie
> 
> to the noogie object in foo/bar/baz.py
> 
> Which I consider more important then removing a couple of characters in the
> line you import an object.
> 
> After all, you're only going to write the code once, but lots of people are
> going to read and try to understand the code.

Well, it is still trackable, especially if you follow the "no two import 
*" rule (and of course preferably not even one); it means you'll have to 
visit another file before finding the object, but you will get there.

And of course if it means not breaking backward compatibility you 
definitely should use this style -- e.g., if you moved from a module to 
a package, and factored your objects into different modules.

Also, I think there's reason to think of a packages "public" API, and 
that does not consist of every module in the package.  Some people are 
very conscientious about naming all their internal modules with leading 
_'s (CherryPy, for example)... which is actually reasonable, but 
something I've never done.  I tend to use documentation to indicate 
publicness.

Using imports in __init__ make that publicness more clear.  But I 
wouldn't argue strongly for it, unless you were maintaining a public 
interface in which case I'd argue strongly for it.

Also, while the import makes it harder to track a name back from the 
source, in tracebacks it's always correct regardless of how many imports 
were involved in attaining the object.

>>> *> Is _() always defined?
>>>
>>> Nope, I think you need to import it from gettext.
>> OK; are we just using plain gettext for everything?  I've been
>> encountering places where people use fancier _'s, but I think that's
>> because in server-side apps you might be supporting multiple language
>> simultaneously, which isn't an issue for OLPC.
>>
>> In some of these cases people often put _ in __builtins__.  Which seems
>> convenient, except you end up doing this for portability:
> 
> Putting it in __builtins__ break source code analyzers such as pyflakes,
> pychecker.
> 
> Modifying __builtins__ is always a bad idea, as it surprises people
> not very familiar with the code.

I wouldn't really argue for that, but it has been a pattern I've seen 
for _ in particular.  I think part of the reason is that there are 
multiple _ implementations, and which one is used is often 
deployment-specific.  So importing from any particular module isn't 
really right, unless you expect that module to be monkeypatched based on 
the deployment.

My vague impression is that _ needs a better implementation than 
gettext's, with more consideration of threadlocal languages, 
registration of providers, and whatever else people are adding into 
their _ implementations.  But without much experience in the subject 
it's only something I'm detecting by smell ;)


-- 
Ian Bicking | ianb at colorstudy.com | http://blog.ianbicking.org


More information about the Sugar-devel mailing list