[Baypiggies] Entry points help

Glen Jarvis glen at glenjarvis.com
Wed Feb 13 02:00:59 CET 2013


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/baypiggies/attachments/20130212/56fde872/attachment.html>


More information about the Baypiggies mailing list