What is Pyre?
From DANSE
The Pyre application framework puts various components together at run time to form, well, an application. The framework assumes responsibility for managing the components. It provides a uniform set of steps for constructing and initializing components; this allows the framework to provide guarantees about when components will be ready to use.
Historically, Pyre was created to bring a degree of order to the complex task of staging large (massively) parallel scientific simulations. Applications support a command-line, serial execution model; the framework includes another class that supports command-line parallel execution. Most of what works for serial applications follows for parallel applications, so learning about serial apps is a good way to get started. Moving forward with the DANSE project (and relatives!), the framework will still have much to offer (to jump ahead for a moment, components will be unchanged, but the things that manage and juxtapose components, currently instances of class Application or mpi.Application, will have to evolve).
- Components...
Here's a simple example component:
#!/usr/bin/env python
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 9/14/2004 version 0.0.1b
# mmckerns@caltech.edu
# (C) 2004 All Rights Reserved
#
# <LicenseText>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
__author__ = 'Mike McKerns'
from pyre.inventory.Component import Component
import os
class Template(Component):
'''pyre component template
Inventory:
foo -- string (default=None)
bar -- string (default=None)
Methods:
shuffle() --> shuffles foo and bar
printall() --> prints foo and bar'''
class Inventory(Component.Inventory):
'''Inventory declares and stores user modifiable variables'''
import pyre.inventory #for pythia0.6
foo = pyre.inventory.str('foo', default=None)
bar = pyre.inventory.str('bar', default=None)
# return
def config(self, **kwds):
'''configure the inventory'''
for key,value in kwds.items():
if key in ['foo','bar']:
if value.__class__() == '':
exec 'self.inventory.'+key+' = "'+value+'"'
else:
exec 'self.inventory.'+key+' = '+str(value)
return
def shuffle(self):
'''shuffles foo and bar; a example method'''
#pass inventory into local variables
foo = self.inventory.foo
bar = self.inventory.bar
#main code
self.inventory.foo = bar
self.inventory.bar = foo
return
def printall(self):
'''prints foo and bar; a example method'''
#pass inventory into local variables
foo = self.inventory.foo
bar = self.inventory.bar
#main code
print foo, bar
return
def __init__(self, name='Template', **kwds):
'''instantiate the application, and pass any keywords to config'''
Component.__init__(self, name, 'DummyTemplate')
self.config(**kwds)
return
def help(self):
print self.__doc__
return
# End of file
- Application...
A Pyre application is a Component with a run() method, and can have a "__main__" code block.
To make a Pyre application from a given component:
- substitute "pyre.inventory.Component" with "pyre.applications.Application"
- substitute all instances of "Component" with "Application"
- add a run() method (i.e. a code block for "def run(self):"
- delete the 'facility' name in __init__: "Component.__init__(self, name, facility)"
- add a "if __name__ == '__main__':" code block
- add a help() method (if one does not already exist)
We can convert our simple component to an application:
#!/usr/bin/env python
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# 9/14/2004 version 0.0.1b
# mmckerns@caltech.edu
# (C) 2004 All Rights Reserved
#
# <LicenseText>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
__author__ = 'Mike McKerns'
from pyre.applications.Application import Application
import os
class Template(Application):
'''pyre application template
Inventory:
foo -- string (default=None)
bar -- string (default=None)
mix -- boolean (default=False)
Methods:
shuffle() --> shuffles foo and bar
printall() --> prints foo and bar'''
class Inventory(Application.Inventory):
'''Inventory declares and stores user modifiable variables'''
import pyre.inventory #for pythia0.6
foo = pyre.inventory.str('foo', default=None)
bar = pyre.inventory.str('bar', default=None)
mix = pyre.inventory.bool('mix', default=False)
# return
def config(self, **kwds):
'''configure the inventory'''
for key,value in kwds.items():
if key in ['foo','bar','mix']:
if value.__class__() == '':
exec 'self.inventory.'+key+' = "'+value+'"'
else:
exec 'self.inventory.'+key+' = '+str(value)
return
def shuffle(self):
'''shuffles foo and bar; a example method'''
#pass inventory into local variables
foo = self.inventory.foo
bar = self.inventory.bar
#main code
self.inventory.foo = bar
self.inventory.bar = foo
return
def printall(self):
'''prints foo and bar; a example method'''
#pass inventory into local variables
foo = self.inventory.foo
bar = self.inventory.bar
#main code
print foo, bar
return
def run(self):
'''shuffle if required; the main method'''
self.printall()
if self.inventory.mix:
self.shuffle()
self.printall()
return
def __init__(self, name='Template', **kwds):
'''instantiate the application, and pass any keywords to config'''
Application.__init__(self, name)
self.config(**kwds)
return
def help(self):
print self.__doc__
return
# main
if __name__ == '__main__':
'''begin journaling services, and then run the main code block'''
import journal
mp = Template('test') #instance of class Template (named 'test')
journal.debug('test').activate() #activate journal for 'test'
mp.main() #launch the main code block ('Template.run')
# End of file
Notice that an additional inventory item, "mix", was added ("mix" only is used by the 'run' method).
- Inventory...
- Facility...
