[Python-ideas] Adding an "export" decorator in (e.g.) functools
Chris Angelico
rosuav at gmail.com
Fri May 9 09:38:18 CEST 2014
(By the way: You responded to two different posts in yours, and didn't
cite either of them. Please keep the original-poster line, such as
you'll see on the next non-blank line.)
On Fri, May 9, 2014 at 5:12 PM, Bill Winslow <bunslow at gmail.com> wrote:
>> But your given implementation seems to have a problem: how can
>> you import that into another module?
>
> And thus I am caught as not having actually tested this -- you are of course
> correct. Having a statement at the bottom defining "__all__" as you suggest
> would (partially) defeat the point, which is to make it easy for the
> programmer to state what should be public, that is, it shouldn't be
> necessary to muck with __all__. I'm trying to avoid the
> magicness/arbitraryness of assignments to __all__.
I don't mind the concept of one-line directives to specify things. In
the same way that you would put "import socket" at the top if you use
sockets, you put "__all__ = export.get_all()" at the bottom to capture
all the __all__ entries. It still deduplicates and brings the
information right to where the function's defined, so there is some
value in it.
> I'll try and think up an alternative implementation that would work as
> advertised when imported from another module. (Note that if the code itself
> were copy and pasted, the function would work fine, yet importing it fails
> -- something I have not yet encountered in Python. This also suggests one
> trivial solution -- import a function that instead exec()'s the definition
> above.) I suspect I might have to learn something about import internals to
> come up with a (better-than-the-trivial) solution. (Copy and pasting code is
> of course unacceptable as well.)
For the exec method to work, it would have to be passed a reference to
globals() for the calling module, so you can simplify it. I don't know
how useful it would be, but this ought to work:
# my_tools.py
def make_all(globls, listname="__all__"):
globls[listname] = []
def grabber(obj):
globls[listname].append(obj)
return obj
return grabber
# your module
import my_tools
export = make_all(globals())
def _private_func_1(): pass
def _private_func_2(): pass
@export
def public_func_1(): pass
@export
def public_func_2(): pass
This is still a bit magical, in that you assign to the name "export"
and it actually is for setting __all__, but it's better than exec :)
ChrisA
More information about the Python-ideas
mailing list