[Baypiggies] Entry points help

Jake Alheid shakefu at gmail.com
Wed Feb 13 03:49:57 CET 2013


Ooh, I found some of the elusive documentation:
http://pythonhosted.org/distribute/pkg_resources.html?highlight=iter_entry_points#convenience-api

Good luck!
--
Jake Alheid
http://about.me/jake


On Tue, Feb 12, 2013 at 6:47 PM, Glen Jarvis <glen at glenjarvis.com> wrote:

> I'm still reading this and need to play with your examples. But, I think
> this is EXACTLY what I needed.
>
> Thank you!!!!
>
> G
>
> On Feb 12, 2013, at 6:41 PM, Jake Alheid <shakefu at gmail.com> wrote:
>
> If you want 3rd parties to be able to register runners, then entry points
> is a good way to go. However, since your example looks like you have
> control over all the files, you might want to look at runpy (
> http://docs.python.org/2/library/runpy.html#runpy.run_module) to import
> your runner's module dictionary, which can then be called. Something like:
>
> def get_runner(name):
>     return runpy.run_module('baypiggies.' + name)
>
> get_runner('fruit')['chew']()
>
> The documentation is really terrible for setuptools... I can't remember
> what I originally read that helped me grok what was going.
>
> If you really want to use entry points for this, you want to define it in
> your setup.py, and do something like:
>
> entry_points = {
>     'baypiggies':[
>         'fruit = baypiggies.fruit',
>         'meta = baypiggies.meat',
>         'mock = baypiggies.mock',
>     ],
> },
>
>  This just registers those namespaces (modules in this case) with
> setuptools/pkg_resources for later consumption. You consume using
> iter_entry_points:
>
> def get_runner_module(name):
>     """ Return a module for `name`. """
>     # This looks for the first entry point with `name` in the 'baypiggies'
>     for entry in pkg_resources.iter_entry_points('baypiggies', name):
>         # Return the loaded module or object, or raise ImportError
>         return entry.load()
>
> If you don't want the module in sys.modules, use runpy instead, and
> replace the last line with:
>
>         # Return the module's namespace dictionary
>         return runpy.run_module(entry.module_name)
>
> Of course, using entry_points will also allow third party packages to
> register with your runner using the 'baypiggies' entry point. You could
> allow for that, and get a list of all registered names, like:
>
> def get_registered_names():
>     names = []
>     for entry in pkg_resources.iter_entry_points('baypiggies'):
>         names.append(entry.name)
>     return names
>
> Hope this helps!
> --
> Jake Alheid
> http://about.me/jake
>
>
> On Tue, Feb 12, 2013 at 5:00 PM, Glen Jarvis <glen at glenjarvis.com> wrote:
>
>> I have a directory like this:
>>
>> baypiggies
>>    - __init__.py
>>    - fruit.py
>>    - meat.py
>>    - mock.py
>>    - runner.py
>>
>> My runner.py is the main entry point and it is used to dynamically chose
>> which of these other files to import.
>>
>> # pylint: disable=C0103,R0904
>>
>> """A sample dynamically loaded example with endpoints
>>
>> ./runner.py --backend=fruit
>> """
>>
>> from optparse import OptionParser
>>
>>
>> entry_points = {
>>     'fruit': dict(
>>         thump = ('fruit', 'thump'),
>>         eat = ('fruit', 'eat'),
>>         chew = ('fruit', 'chew'),
>>     ),
>>     'meat': dict(
>>         thump = ('meat', 'thump'),
>>         eat = ('meat', 'eat'),
>>         chew = ('meat', 'chew'),
>>     ),
>>     'mock': dict(
>>         thump = ('mock', 'thump'),
>>         eat = ('mock', 'eat'),
>>         chew = ('mock', 'chew'),
>>     ),
>>     'custom1': dict(
>>         thump = ('myns.mypkg.mymodule', 'thump'),
>>         eat = ('myns.mypkg.mymodule', 'eat'),
>>         chew = ('myns.mypkg.mymodule', 'chew'),
>>     ),
>> }
>>
>> def import_entry_points(entries):
>>
>>     """Dynamically import the functions for the specified backend
>>
>>     entry_points is a global dictionary whos keys correspond to each
>>     of the different types of backends that we can support. The variable
>>     options.backend specifies which of the backends that will be used
>>     during this program run.
>>
>>     The value of entry_points (for options.backend) is another
>>     dictionary which map the functions needed to the modules from where
>>     we will import these modules. We only want to import the backend
>>     modules that will be used (and not have unnecessary dependencies).
>>
>>     This module will replace the values in this inner dictionary with
>>     the imported functions. This way, the functions are imported and
>>     available when needed.
>>     """
>>
>>     for entry in entries:
>>         module, name = entries[entry]
>>         _temp = __import__(module, globals(), locals(), [name], 0)
>>         entries[entry] = getattr(_temp, entry)
>>
>>
>> def run(backend="mock"):
>>     print "Running, backend: ", backend
>>     import_entry_points(entry_points[backend])
>>
>>     import pprint
>>     pprint.pprint(entry_points)
>>
>>     print "THUMPING..."
>>     entry_points[backend]["thump"]()
>>
>>     print "EATING..."
>>     entry_points[backend]["eat"]()
>>
>>     print "CHEWING..."
>>     # Chew five times
>>     entry_points[backend]["chew"](5)
>>
>> if __name__ == "__main__":
>>     parser = OptionParser()
>>     parser.add_option("-b", "--backend", dest="backend",
>>                       default="mock",
>>                       help="Choose which backend to run.")
>>
>>     (options, args) = parser.parse_args()
>>     run(options.backend)
>>
>>
>>
>> Now, as you can see, the backends are loaded dynamically depending upon
>> the command line options (let's only import what we need).
>>
>> prompt> python runner.py
>> Running, backend:  mock
>> {'custom1': {'chew': ('myns.mypkg.mymodule', 'chew'),
>>              'eat': ('myns.mypkg.mymodule', 'eat'),
>>              'thump': ('myns.mypkg.mymodule', 'thump')},
>>  'fruit': {'chew': ('fruit', 'chew'),
>>            'eat': ('fruit', 'eat'),
>>            'thump': ('fruit', 'thump')},
>>  'meat': {'chew': ('meat', 'chew'),
>>           'eat': ('meat', 'eat'),
>>           'thump': ('meat', 'thump')},
>>  'mock': {'chew': <function chew at 0x10c3e1aa0>,
>>           'eat': <function eat at 0x10c3e1a28>,
>>           'thump': <function thump at 0x10c3e19b0>}}
>> THUMPING...
>> Pretend to thump
>> EATING...
>> Pretend to eat
>> CHEWING...
>> Prentend to chew
>>
>>
>> And, totally new/different backend if I choose the option:
>>
>>
>> Running, backend:  fruit
>> {'custom1': {'chew': ('myns.mypkg.mymodule', 'chew'),
>>              'eat': ('myns.mypkg.mymodule', 'eat'),
>>              'thump': ('myns.mypkg.mymodule', 'thump')},
>>  'fruit': {'chew': <function chew at 0x103a11aa0>,
>>            'eat': <function eat at 0x103a11a28>,
>>            'thump': <function thump at 0x103a119b0>},
>>  'meat': {'chew': ('meat', 'chew'),
>>           'eat': ('meat', 'eat'),
>>           'thump': ('meat', 'thump')},
>>  'mock': {'chew': ('mock', 'chew'),
>>           'eat': ('mock', 'eat'),
>>           'thump': ('mock', 'thump')}}
>> THUMPING...
>> Thumping fruit...
>> EATING...
>> Eating fruit.. very healthy....
>> CHEWING...
>> Fruit chew  0
>> Fruit chew  1
>> Fruit chew  2
>> Fruit chew  3
>> Fruit chew  4
>>
>>
>>
>> Here are examples of my backends:
>>
>>
>>
>>
>> """An empty mock (Currently not implemented)"""
>>
>>
>> def thump():
>>
>>     print "Pretend to thump"
>>
>>
>> def eat():
>>
>>     print "Pretend to eat"
>>
>>
>> def chew(number_of_times):
>>
>>     print "Prentend to chew"
>>
>>
>>
>>
>> Here's the mock one (by default):
>>
>>
>> def thump():
>>
>>     print "Pretend to thump"
>>
>>
>> def eat():
>>
>>     print "Pretend to eat"
>>
>>
>> def chew(number_of_times):
>>
>>     print "Prentend to chew"
>>
>>
>>
>>
>>
>> So, I'm supposed to be using entry points from the setuptools library
>> (instead of the above). But, I've googled and get stuck. I just don't see
>> how to use it (and use it without doing a setup each time).:
>>
>>
>> http://stackoverflow.com/questions/774824/explain-python-entry-points/9615473#9615473
>>
>> Can someone help me by example? I'm confused...
>>
>>
>> Cheers,
>>
>>
>> Glen
>> --
>>
>> "Pursue, keep up with, circle round and round your life as a dog does his
>> master's chase. Do what you love. Know your own bone; gnaw at it, bury it,
>> unearth it, and gnaw it still."
>>
>> --Henry David Thoreau
>>
>> _______________________________________________
>> Baypiggies mailing list
>> Baypiggies at python.org
>> To change your subscription options or unsubscribe:
>> http://mail.python.org/mailman/listinfo/baypiggies
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/baypiggies/attachments/20130212/abf110c6/attachment-0001.html>


More information about the Baypiggies mailing list