summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/python/SConscript8
-rw-r--r--src/python/m5/SimObject.py1
-rw-r--r--src/python/m5/main.py2
-rw-r--r--src/python/m5/util/__init__.py32
-rw-r--r--src/python/m5/util/attrdict.py (renamed from src/python/m5/attrdict.py)11
-rw-r--r--src/python/m5/util/jobfile.py (renamed from util/pbs/jobfile.py)373
-rw-r--r--src/python/m5/util/misc.py (renamed from src/python/m5/util.py)28
-rw-r--r--src/python/m5/util/multidict.py (renamed from src/python/m5/multidict.py)0
-rw-r--r--src/python/m5/util/orderdict.py (renamed from util/stats/orderdict.py)0
-rw-r--r--util/batch/jobfile.py539
10 files changed, 218 insertions, 776 deletions
diff --git a/src/python/SConscript b/src/python/SConscript
index b39c9ea9c..0785b4307 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -36,18 +36,20 @@ Source('swig/pyobject.cc')
PySource('m5', 'm5/__init__.py')
PySource('m5', 'm5/SimObject.py')
-PySource('m5', 'm5/attrdict.py')
PySource('m5', 'm5/convert.py')
PySource('m5', 'm5/event.py')
PySource('m5', 'm5/main.py')
-PySource('m5', 'm5/multidict.py')
PySource('m5', 'm5/params.py')
PySource('m5', 'm5/proxy.py')
PySource('m5', 'm5/simulate.py')
PySource('m5', 'm5/smartdict.py')
PySource('m5', 'm5/stats.py')
PySource('m5', 'm5/ticks.py')
-PySource('m5', 'm5/util.py')
+PySource('m5.util', 'm5/util/__init__.py')
+PySource('m5.util', 'm5/util/attrdict.py')
+PySource('m5.util', 'm5/util/jobfile.py')
+PySource('m5.util', 'm5/util/misc.py')
+PySource('m5.util', 'm5/util/multidict.py')
SwigSource('m5.internal', 'swig/core.i')
SwigSource('m5.internal', 'swig/debug.i')
diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py
index d1aec44b3..41ed3df9e 100644
--- a/src/python/m5/SimObject.py
+++ b/src/python/m5/SimObject.py
@@ -32,7 +32,6 @@ import sys, types
import proxy
import m5
from util import *
-from multidict import multidict
# These utility functions have to come first because they're
# referenced in params.py... otherwise they won't be defined when we
diff --git a/src/python/m5/main.py b/src/python/m5/main.py
index cbdd65492..5c3324224 100644
--- a/src/python/m5/main.py
+++ b/src/python/m5/main.py
@@ -33,7 +33,7 @@ import os
import socket
import sys
-from attrdict import attrdict
+from util import attrdict
import defines
import traceflags
diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py
new file mode 100644
index 000000000..f82de696a
--- /dev/null
+++ b/src/python/m5/util/__init__.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2008 The Hewlett-Packard Development Company
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+from attrdict import attrdict, optiondict
+from misc import *
+from multidict import multidict
+import jobfile
diff --git a/src/python/m5/attrdict.py b/src/python/m5/util/attrdict.py
index 4ee7f1b8c..44479c456 100644
--- a/src/python/m5/attrdict.py
+++ b/src/python/m5/util/attrdict.py
@@ -26,7 +26,7 @@
#
# Authors: Nathan Binkert
-__all__ = [ 'attrdict' ]
+__all__ = [ 'attrdict', 'optiondict' ]
class attrdict(dict):
def __getattr__(self, attr):
@@ -44,6 +44,15 @@ class attrdict(dict):
return self.__delitem__(attr)
return super(attrdict, self).__delattr__(attr, value)
+class optiondict(attrdict):
+ def __getattr__(self, attr):
+ try:
+ return super(optiondict, self).__getattr__(attr)
+ except AttributeError:
+ #d = optionsdict()
+ #setattr(self, attr, d)
+ return None
+
if __name__ == '__main__':
x = attrdict()
x.y = 1
diff --git a/util/pbs/jobfile.py b/src/python/m5/util/jobfile.py
index fd19b3bf5..5e015c4ad 100644
--- a/util/pbs/jobfile.py
+++ b/src/python/m5/util/jobfile.py
@@ -28,157 +28,70 @@
import sys
-class ternary(object):
- def __new__(cls, *args):
- if len(args) > 1:
- raise TypeError, \
- '%s() takes at most 1 argument (%d given)' % \
- (cls.__name__, len(args))
-
- if args:
- if not isinstance(args[0], (bool, ternary)):
- raise TypeError, \
- '%s() argument must be True, False, or Any' % \
- cls.__name__
- return args[0]
- return super(ternary, cls).__new__(cls)
-
- def __bool__(self):
- return True
-
- def __neg__(self):
- return self
-
- def __eq__(self, other):
- return True
-
- def __ne__(self, other):
- return False
-
- def __str__(self):
- return 'Any'
-
- def __repr__(self):
- return 'Any'
-
-Any = ternary()
-
-class Flags(dict):
- def __init__(self, *args, **kwargs):
- super(Flags, self).__init__()
- self.update(*args, **kwargs)
-
- def __getattr__(self, attr):
- return self[attr]
-
- def __setattr__(self, attr, value):
- self[attr] = value
-
- def __setitem__(self, item, value):
- return super(Flags, self).__setitem__(item, ternary(value))
-
- def __getitem__(self, item):
- if item not in self:
- return False
- return super(Flags, self).__getitem__(item)
-
- def update(self, *args, **kwargs):
- for arg in args:
- if isinstance(arg, Flags):
- super(Flags, self).update(arg)
- elif isinstance(arg, dict):
- for key,val in kwargs.iteritems():
- self[key] = val
- else:
- raise AttributeError, \
- 'flags not of type %s or %s, but %s' % \
- (Flags, dict, type(arg))
-
- for key,val in kwargs.iteritems():
- self[key] = val
-
- def match(self, *args, **kwargs):
- match = Flags(*args, **kwargs)
-
- for key,value in match.iteritems():
- if self[key] != value:
- return False
-
- return True
-
-def crossproduct(items):
- if not isinstance(items, (list, tuple)):
- raise AttributeError, 'crossproduct works only on sequences'
-
- if not items:
- yield None
- return
-
- current = items[0]
- remainder = items[1:]
-
- if not hasattr(current, '__iter__'):
- current = [ current ]
-
- for item in current:
- for rem in crossproduct(remainder):
- data = [ item ]
- if rem:
- data += rem
- yield data
-
-def flatten(items):
- if not isinstance(items, (list, tuple)):
- yield items
- return
-
- for item in items:
- for flat in flatten(item):
- yield flat
+from attrdict import attrdict, optiondict
+from misc import crossproduct, flatten
class Data(object):
def __init__(self, name, desc, **kwargs):
self.name = name
self.desc = desc
- self.system = None
- self.flags = Flags()
- self.env = {}
- for k,v in kwargs.iteritems():
- setattr(self, k, v)
+ self.__dict__.update(kwargs)
def update(self, obj):
if not isinstance(obj, Data):
raise AttributeError, "can only update from Data object"
- self.env.update(obj.env)
- self.flags.update(obj.flags)
- if obj.system:
- if self.system and self.system != obj.system:
+ for k,v in obj.__dict__.iteritems():
+ if not k.startswith('_'):
+ self.__dict__[k] = v
+ if hasattr(self, 'system') and hasattr(obj, 'system'):
+ if self.system != obj.system:
raise AttributeError, \
"conflicting values for system: '%s'/'%s'" % \
(self.system, obj.system)
- self.system = obj.system
def printinfo(self):
if self.name:
print 'name: %s' % self.name
if self.desc:
print 'desc: %s' % self.desc
- if self.system:
- print 'system: %s' % self.system
+ try:
+ if self.system:
+ print 'system: %s' % self.system
+ except AttributeError:
+ pass
def printverbose(self):
- print 'flags:'
- keys = self.flags.keys()
- keys.sort()
- for key in keys:
- print ' %s = %s' % (key, self.flags[key])
- print 'env:'
- keys = self.env.keys()
+ for key in self:
+ val = self[key]
+ if isinstance(val, dict):
+ import pprint
+ val = pprint.pformat(val)
+ print '%-20s = %s' % (key, val)
+ print
+
+ def __contains__(self, attr):
+ if attr.startswith('_'):
+ return False
+ return attr in self.__dict__
+
+ def __getitem__(self, key):
+ if key.startswith('_'):
+ raise KeyError, "Key '%s' not found" % attr
+ return self.__dict__[key]
+
+ def __iter__(self):
+ keys = self.__dict__.keys()
keys.sort()
for key in keys:
- print ' %s = %s' % (key, self.env[key])
- print
+ if not key.startswith('_'):
+ yield key
+
+ def optiondict(self):
+ result = optiondict()
+ for key in self:
+ result[key] = self[key]
+ return result
def __str__(self):
return self.name
@@ -186,88 +99,84 @@ class Data(object):
class Job(Data):
def __init__(self, options):
super(Job, self).__init__('', '')
- self.setoptions(options)
- self.checkpoint = False
- opts = []
+ config = options[0]._config
for opt in options:
- cpt = opt.group.checkpoint
- if not cpt:
- self.checkpoint = True
- continue
- if isinstance(cpt, Option):
- opt = cpt.clone(suboptions=False)
- else:
- opt = opt.clone(suboptions=False)
+ if opt._config != config:
+ raise AttributeError, \
+ "All options are not from the same Configuration"
- opts.append(opt)
+ self._config = config
+ self._groups = [ opt._group for opt in options ]
+ self._options = options
- if not opts:
- self.checkpoint = False
+ self.update(self._config)
+ for group in self._groups:
+ self.update(group)
- if self.checkpoint:
- self.checkpoint = Job(opts)
+ self._is_checkpoint = True
- def clone(self):
- return Job(self.options)
+ for option in self._options:
+ self.update(option)
+ if not option._group._checkpoint:
+ self._is_checkpoint = False
- def __getattribute__(self, attr):
- if attr == 'name':
- names = [ ]
- for opt in self.options:
- if opt.name:
- names.append(opt.name)
- return ':'.join(names)
+ if option._suboption:
+ self.update(option._suboption)
+ self._is_checkpoint = False
- if attr == 'desc':
- descs = [ ]
- for opt in self.options:
- if opt.desc:
- descs.append(opt.desc)
- return ', '.join(descs)
+ names = [ ]
+ for opt in self._options:
+ if opt.name:
+ names.append(opt.name)
+ self.name = ':'.join(names)
- return super(Job, self).__getattribute__(attr)
+ descs = [ ]
+ for opt in self._options:
+ if opt.desc:
+ descs.append(opt.desc)
+ self.desc = ', '.join(descs)
- def setoptions(self, options):
- config = options[0].config
- for opt in options:
- if opt.config != config:
- raise AttributeError, \
- "All options are not from the same Configuration"
+ self._checkpoint = None
+ if not self._is_checkpoint:
+ opts = []
+ for opt in options:
+ cpt = opt._group._checkpoint
+ if not cpt:
+ continue
+ if isinstance(cpt, Option):
+ opt = cpt.clone(suboptions=False)
+ else:
+ opt = opt.clone(suboptions=False)
- self.config = config
- self.groups = [ opt.group for opt in options ]
- self.options = options
+ opts.append(opt)
- self.update(self.config)
- for group in self.groups:
- self.update(group)
+ if opts:
+ self._checkpoint = Job(opts)
- for option in self.options:
- self.update(option)
- if option._suboption:
- self.update(option._suboption)
+ def clone(self):
+ return Job(self._options)
def printinfo(self):
super(Job, self).printinfo()
- if self.checkpoint:
- print 'checkpoint: %s' % self.checkpoint.name
- print 'config: %s' % self.config.name
- print 'groups: %s' % [ g.name for g in self.groups ]
- print 'options: %s' % [ o.name for o in self.options ]
+ if self._checkpoint:
+ print 'checkpoint: %s' % self._checkpoint.name
+ print 'config: %s' % self._config.name
+ print 'groups: %s' % [ g.name for g in self._groups ]
+ print 'options: %s' % [ o.name for o in self._options ]
super(Job, self).printverbose()
class SubOption(Data):
def __init__(self, name, desc, **kwargs):
super(SubOption, self).__init__(name, desc, **kwargs)
- self.number = None
+ self._number = None
class Option(Data):
def __init__(self, name, desc, **kwargs):
super(Option, self).__init__(name, desc, **kwargs)
self._suboptions = []
self._suboption = None
- self.number = None
+ self._number = None
def __getattribute__(self, attr):
if attr == 'name':
@@ -282,24 +191,23 @@ class Option(Data):
desc.append(self._suboption.desc)
return ', '.join(desc)
-
return super(Option, self).__getattribute__(attr)
def suboption(self, name, desc, **kwargs):
subo = SubOption(name, desc, **kwargs)
- subo.config = self.config
- subo.group = self.group
- subo.option = self
- subo.number = len(self._suboptions)
+ subo._config = self._config
+ subo._group = self._group
+ subo._option = self
+ subo._number = len(self._suboptions)
self._suboptions.append(subo)
return subo
def clone(self, suboptions=True):
option = Option(self.__dict__['name'], self.__dict__['desc'])
option.update(self)
- option.group = self.group
- option.config = self.config
- option.number = self.number
+ option._group = self._group
+ option._config = self._config
+ option._number = self._number
if suboptions:
option._suboptions.extend(self._suboptions)
option._suboption = self._suboption
@@ -319,21 +227,21 @@ class Option(Data):
def printinfo(self):
super(Option, self).printinfo()
- print 'config: %s' % self.config.name
+ print 'config: %s' % self._config.name
super(Option, self).printverbose()
class Group(Data):
def __init__(self, name, desc, **kwargs):
super(Group, self).__init__(name, desc, **kwargs)
self._options = []
- self.checkpoint = False
- self.number = None
+ self._number = None
+ self._checkpoint = False
def option(self, name, desc, **kwargs):
opt = Option(name, desc, **kwargs)
- opt.config = self.config
- opt.group = self
- opt.number = len(self._options)
+ opt._config = self._config
+ opt._group = self
+ opt._number = len(self._options)
self._options.append(opt)
return opt
@@ -349,7 +257,7 @@ class Group(Data):
def printinfo(self):
super(Group, self).printinfo()
- print 'config: %s' % self.config.name
+ print 'config: %s' % self._config.name
print 'options: %s' % [ o.name for o in self._options ]
super(Group, self).printverbose()
@@ -362,40 +270,39 @@ class Configuration(Data):
def group(self, name, desc, **kwargs):
grp = Group(name, desc, **kwargs)
- grp.config = self
- grp.number = len(self._groups)
+ grp._config = self
+ grp._number = len(self._groups)
self._groups.append(grp)
return grp
- def groups(self, flags=Flags(), sign=True):
- if not flags:
- return self._groups
-
- return [ grp for grp in self._groups if sign ^ grp.flags.match(flags) ]
+ def groups(self):
+ return self._groups
def checkchildren(self, kids):
for kid in kids:
- if kid.config != self:
+ if kid._config != self:
raise AttributeError, "child from the wrong configuration"
def sortgroups(self, groups):
- groups = [ (grp.number, grp) for grp in groups ]
+ groups = [ (grp._number, grp) for grp in groups ]
groups.sort()
return [ grp[1] for grp in groups ]
- def options(self, groups = None, checkpoint = False):
+ def options(self, groups=None, checkpoint=False):
if groups is None:
groups = self._groups
self.checkchildren(groups)
groups = self.sortgroups(groups)
if checkpoint:
- groups = [ grp for grp in groups if grp.checkpoint ]
+ groups = [ grp for grp in groups if grp._checkpoint ]
optgroups = [ g.options() for g in groups ]
else:
optgroups = [ g.subopts() for g in groups ]
+ if not optgroups:
+ return
for options in crossproduct(optgroups):
for opt in options:
- cpt = opt.group.checkpoint
+ cpt = opt._group._checkpoint
if not isinstance(cpt, bool) and cpt != opt:
if checkpoint:
break
@@ -427,19 +334,19 @@ class Configuration(Data):
return False
- def checkpoints(self, groups = None):
+ def checkpoints(self, groups=None):
for options in self.options(groups, True):
job = Job(options)
if self.jobfilter(job):
yield job
- def jobs(self, groups = None):
+ def jobs(self, groups=None):
for options in self.options(groups, False):
job = Job(options)
if self.jobfilter(job):
yield job
- def alljobs(self, groups = None):
+ def alljobs(self, groups=None):
for options in self.options(groups, True):
yield Job(options)
for options in self.options(groups, False):
@@ -454,7 +361,7 @@ class Configuration(Data):
def job(self, options):
self.checkchildren(options)
- options = [ (opt.group.number, opt) for opt in options ]
+ options = [ (opt._group._number, opt) for opt in options ]
options.sort()
options = [ opt[1] for opt in options ]
job = Job(options)
@@ -462,7 +369,7 @@ class Configuration(Data):
def printinfo(self):
super(Configuration, self).printinfo()
- print 'groups: %s' % [ g.name for g in self._grouips ]
+ print 'groups: %s' % [ g.name for g in self._groups ]
super(Configuration, self).printverbose()
def JobFile(jobfile):
@@ -492,8 +399,7 @@ def JobFile(jobfile):
(jobfile, type(conf), Configuration)
return conf
-if __name__ == '__main__':
- from jobfile import *
+def main(conf=None):
import sys
usage = 'Usage: %s [-b] [-c] [-v] <jobfile>' % sys.argv[0]
@@ -504,9 +410,6 @@ if __name__ == '__main__':
except getopt.GetoptError:
sys.exit(usage)
- if len(args) != 1:
- raise AttributeError, usage
-
both = False
checkpoint = False
verbose = False
@@ -519,21 +422,29 @@ if __name__ == '__main__':
if opt == '-v':
verbose = True
- jobfile = args[0]
- conf = JobFile(jobfile)
+ if conf is None:
+ if len(args) != 1:
+ raise AttributeError, usage
+ conf = JobFile(args[0])
+ else:
+ if len(args) != 0:
+ raise AttributeError, usage
if both:
- gen = conf.alljobs()
+ jobs = conf.alljobs()
elif checkpoint:
- gen = conf.checkpoints()
+ jobs = conf.checkpoints()
else:
- gen = conf.jobs()
+ jobs = conf.jobs()
- for job in gen:
- if not verbose:
+ for job in jobs:
+ if verbose:
+ job.printinfo()
+ else:
cpt = ''
- if job.checkpoint:
- cpt = job.checkpoint.name
+ if job._checkpoint:
+ cpt = job._checkpoint.name
print job.name, cpt
- else:
- job.printinfo()
+
+if __name__ == '__main__':
+ main()
diff --git a/src/python/m5/util.py b/src/python/m5/util/misc.py
index 28b8b1b94..094e3ed9a 100644
--- a/src/python/m5/util.py
+++ b/src/python/m5/util/misc.py
@@ -56,4 +56,32 @@ def applyOrMap(objOrSeq, meth, *args, **kwargs):
else:
return [applyMethod(o, meth, *args, **kwargs) for o in objOrSeq]
+def crossproduct(items):
+ if not isinstance(items, (list, tuple)):
+ raise AttributeError, 'crossproduct works only on sequences'
+ if not items:
+ yield None
+ return
+
+ current = items[0]
+ remainder = items[1:]
+
+ if not hasattr(current, '__iter__'):
+ current = [ current ]
+
+ for item in current:
+ for rem in crossproduct(remainder):
+ data = [ item ]
+ if rem:
+ data += rem
+ yield data
+
+def flatten(items):
+ if not isinstance(items, (list, tuple)):
+ yield items
+ return
+
+ for item in items:
+ for flat in flatten(item):
+ yield flat
diff --git a/src/python/m5/multidict.py b/src/python/m5/util/multidict.py
index b5cd700ef..b5cd700ef 100644
--- a/src/python/m5/multidict.py
+++ b/src/python/m5/util/multidict.py
diff --git a/util/stats/orderdict.py b/src/python/m5/util/orderdict.py
index 3f755d299..3f755d299 100644
--- a/util/stats/orderdict.py
+++ b/src/python/m5/util/orderdict.py
diff --git a/util/batch/jobfile.py b/util/batch/jobfile.py
deleted file mode 100644
index b78d7f3e1..000000000
--- a/util/batch/jobfile.py
+++ /dev/null
@@ -1,539 +0,0 @@
-# Copyright (c) 2006 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Kevin Lim
-
-import sys
-
-class ternary(object):
- def __new__(cls, *args):
- if len(args) > 1:
- raise TypeError, \
- '%s() takes at most 1 argument (%d given)' % \
- (cls.__name__, len(args))
-
- if args:
- if not isinstance(args[0], (bool, ternary)):
- raise TypeError, \
- '%s() argument must be True, False, or Any' % \
- cls.__name__
- return args[0]
- return super(ternary, cls).__new__(cls)
-
- def __bool__(self):
- return True
-
- def __neg__(self):
- return self
-
- def __eq__(self, other):
- return True
-
- def __ne__(self, other):
- return False
-
- def __str__(self):
- return 'Any'
-
- def __repr__(self):
- return 'Any'
-
-Any = ternary()
-
-class Flags(dict):
- def __init__(self, *args, **kwargs):
- super(Flags, self).__init__()
- self.update(*args, **kwargs)
-
- def __getattr__(self, attr):
- return self[attr]
-
- def __setattr__(self, attr, value):
- self[attr] = value
-
- def __setitem__(self, item, value):
- return super(Flags, self).__setitem__(item, ternary(value))
-
- def __getitem__(self, item):
- if item not in self:
- return False
- return super(Flags, self).__getitem__(item)
-
- def update(self, *args, **kwargs):
- for arg in args:
- if isinstance(arg, Flags):
- super(Flags, self).update(arg)
- elif isinstance(arg, dict):
- for key,val in kwargs.iteritems():
- self[key] = val
- else:
- raise AttributeError, \
- 'flags not of type %s or %s, but %s' % \
- (Flags, dict, type(arg))
-
- for key,val in kwargs.iteritems():
- self[key] = val
-
- def match(self, *args, **kwargs):
- match = Flags(*args, **kwargs)
-
- for key,value in match.iteritems():
- if self[key] != value:
- return False
-
- return True
-
-def crossproduct(items):
- if not isinstance(items, (list, tuple)):
- raise AttributeError, 'crossproduct works only on sequences'
-
- if not items:
- yield None
- return
-
- current = items[0]
- remainder = items[1:]
-
- if not hasattr(current, '__iter__'):
- current = [ current ]
-
- for item in current:
- for rem in crossproduct(remainder):
- data = [ item ]
- if rem:
- data += rem
- yield data
-
-def flatten(items):
- if not isinstance(items, (list, tuple)):
- yield items
- return
-
- for item in items:
- for flat in flatten(item):
- yield flat
-
-class Data(object):
- def __init__(self, name, desc, **kwargs):
- self.name = name
- self.desc = desc
- self.system = None
- self.flags = Flags()
- self.env = {}
- for k,v in kwargs.iteritems():
- setattr(self, k, v)
-
- def update(self, obj):
- if not isinstance(obj, Data):
- raise AttributeError, "can only update from Data object"
-
- self.env.update(obj.env)
- self.flags.update(obj.flags)
- if obj.system:
- if self.system and self.system != obj.system:
- raise AttributeError, \
- "conflicting values for system: '%s'/'%s'" % \
- (self.system, obj.system)
- self.system = obj.system
-
- def printinfo(self):
- if self.name:
- print 'name: %s' % self.name
- if self.desc:
- print 'desc: %s' % self.desc
- if self.system:
- print 'system: %s' % self.system
-
- def printverbose(self):
- print 'flags:'
- keys = self.flags.keys()
- keys.sort()
- for key in keys:
- print ' %s = %s' % (key, self.flags[key])
- print 'env:'
- keys = self.env.keys()
- keys.sort()
- for key in keys:
- print ' %s = %s' % (key, self.env[key])
- print
-
- def __str__(self):
- return self.name
-
-class Job(Data):
- def __init__(self, options):
- super(Job, self).__init__('', '')
- self.setoptions(options)
-
- self.checkpoint = False
- opts = []
- for opt in options:
- cpt = opt.group.checkpoint
- if not cpt:
- self.checkpoint = True
- continue
- if isinstance(cpt, Option):
- opt = cpt.clone(suboptions=False)
- else:
- opt = opt.clone(suboptions=False)
-
- opts.append(opt)
-
- if not opts:
- self.checkpoint = False
-
- if self.checkpoint:
- self.checkpoint = Job(opts)
-
- def clone(self):
- return Job(self.options)
-
- def __getattribute__(self, attr):
- if attr == 'name':
- names = [ ]
- for opt in self.options:
- if opt.name:
- names.append(opt.name)
- return ':'.join(names)
-
- if attr == 'desc':
- descs = [ ]
- for opt in self.options:
- if opt.desc:
- descs.append(opt.desc)
- return ', '.join(descs)
-
- return super(Job, self).__getattribute__(attr)
-
- def setoptions(self, options):
- config = options[0].config
- for opt in options:
- if opt.config != config:
- raise AttributeError, \
- "All options are not from the same Configuration"
-
- self.config = config
- self.groups = [ opt.group for opt in options ]
- self.options = options
-
- self.update(self.config)
- for group in self.groups:
- self.update(group)
-
- for option in self.options:
- self.update(option)
- if option._suboption:
- self.update(option._suboption)
-
- def printinfo(self):
- super(Job, self).printinfo()
- if self.checkpoint:
- print 'checkpoint: %s' % self.checkpoint.name
- print 'config: %s' % self.config.name
- print 'groups: %s' % [ g.name for g in self.groups ]
- print 'options: %s' % [ o.name for o in self.options ]
- super(Job, self).printverbose()
-
-class SubOption(Data):
- def __init__(self, name, desc, **kwargs):
- super(SubOption, self).__init__(name, desc, **kwargs)
- self.number = None
-
-class Option(Data):
- def __init__(self, name, desc, **kwargs):
- super(Option, self).__init__(name, desc, **kwargs)
- self._suboptions = []
- self._suboption = None
- self.number = None
-
- def __getattribute__(self, attr):
- if attr == 'name':
- name = self.__dict__[attr]
- if self._suboption is not None:
- name = '%s:%s' % (name, self._suboption.name)
- return name
-
- if attr == 'desc':
- desc = [ self.__dict__[attr] ]
- if self._suboption is not None and self._suboption.desc:
- desc.append(self._suboption.desc)
- return ', '.join(desc)
-
-
- return super(Option, self).__getattribute__(attr)
-
- def suboption(self, name, desc, **kwargs):
- subo = SubOption(name, desc, **kwargs)
- subo.config = self.config
- subo.group = self.group
- subo.option = self
- subo.number = len(self._suboptions)
- self._suboptions.append(subo)
- return subo
-
- def clone(self, suboptions=True):
- option = Option(self.__dict__['name'], self.__dict__['desc'])
- option.update(self)
- option.group = self.group
- option.config = self.config
- option.number = self.number
- if suboptions:
- option._suboptions.extend(self._suboptions)
- option._suboption = self._suboption
- return option
-
- def subopts(self):
- if not self._suboptions:
- return [ self ]
-
- subopts = []
- for subo in self._suboptions:
- option = self.clone()
- option._suboption = subo
- subopts.append(option)
-
- return subopts
-
- def printinfo(self):
- super(Option, self).printinfo()
- print 'config: %s' % self.config.name
- super(Option, self).printverbose()
-
-class Group(Data):
- def __init__(self, name, desc, **kwargs):
- super(Group, self).__init__(name, desc, **kwargs)
- self._options = []
- self.checkpoint = False
- self.number = None
-
- def option(self, name, desc, **kwargs):
- opt = Option(name, desc, **kwargs)
- opt.config = self.config
- opt.group = self
- opt.number = len(self._options)
- self._options.append(opt)
- return opt
-
- def options(self):
- return self._options
-
- def subopts(self):
- subopts = []
- for opt in self._options:
- for subo in opt.subopts():
- subopts.append(subo)
- return subopts
-
- def printinfo(self):
- super(Group, self).printinfo()
- print 'config: %s' % self.config.name
- print 'options: %s' % [ o.name for o in self._options ]
- super(Group, self).printverbose()
-
-class Configuration(Data):
- def __init__(self, name, desc, **kwargs):
- super(Configuration, self).__init__(name, desc, **kwargs)
- self._groups = []
- self._posfilters = []
- self._negfilters = []
-
- def group(self, name, desc, **kwargs):
- grp = Group(name, desc, **kwargs)
- grp.config = self
- grp.number = len(self._groups)
- self._groups.append(grp)
- return grp
-
- def groups(self, flags=Flags(), sign=True):
- if not flags:
- return self._groups
-
- return [ grp for grp in self._groups if sign ^ grp.flags.match(flags) ]
-
- def checkchildren(self, kids):
- for kid in kids:
- if kid.config != self:
- raise AttributeError, "child from the wrong configuration"
-
- def sortgroups(self, groups):
- groups = [ (grp.number, grp) for grp in groups ]
- groups.sort()
- return [ grp[1] for grp in groups ]
-
- def options(self, groups = None, checkpoint = False):
- if groups is None:
- groups = self._groups
- self.checkchildren(groups)
- groups = self.sortgroups(groups)
- if checkpoint:
- groups = [ grp for grp in groups if grp.checkpoint ]
- optgroups = [ g.options() for g in groups ]
- else:
- optgroups = [ g.subopts() for g in groups ]
- for options in crossproduct(optgroups):
- for opt in options:
- cpt = opt.group.checkpoint
- if not isinstance(cpt, bool) and cpt != opt:
- if checkpoint:
- break
- else:
- yield options
- else:
- if checkpoint:
- yield options
-
- def addfilter(self, filt, pos=True):
- import re
- filt = re.compile(filt)
- if pos:
- self._posfilters.append(filt)
- else:
- self._negfilters.append(filt)
-
- def jobfilter(self, job):
- for filt in self._negfilters:
- if filt.match(job.name):
- return False
-
- if not self._posfilters:
- return True
-
- for filt in self._posfilters:
- if filt.match(job.name):
- return True
-
- return False
-
- def checkpoints(self, groups = None):
- for options in self.options(groups, True):
- job = Job(options)
- if self.jobfilter(job):
- yield job
-
- def jobs(self, groups = None):
- for options in self.options(groups, False):
- job = Job(options)
- if self.jobfilter(job):
- yield job
-
- def alljobs(self, groups = None):
- for options in self.options(groups, True):
- yield Job(options)
- for options in self.options(groups, False):
- yield Job(options)
-
- def find(self, jobname):
- for job in self.alljobs():
- if job.name == jobname:
- return job
- else:
- raise AttributeError, "job '%s' not found" % jobname
-
- def job(self, options):
- self.checkchildren(options)
- options = [ (opt.group.number, opt) for opt in options ]
- options.sort()
- options = [ opt[1] for opt in options ]
- job = Job(options)
- return job
-
- def printinfo(self):
- super(Configuration, self).printinfo()
- print 'groups: %s' % [ g.name for g in self._grouips ]
- super(Configuration, self).printverbose()
-
-def JobFile(jobfile):
- from os.path import expanduser, isfile, join as joinpath
- filename = expanduser(jobfile)
-
- # Can't find filename in the current path, search sys.path
- if not isfile(filename):
- for path in sys.path:
- testname = joinpath(path, filename)
- if isfile(testname):
- filename = testname
- break
- else:
- raise AttributeError, \
- "Could not find file '%s'" % jobfile
-
- data = {}
- execfile(filename, data)
- if 'conf' not in data:
- raise ImportError, 'cannot import name conf from %s' % jobfile
- conf = data['conf']
- import jobfile
- if not isinstance(conf, Configuration):
- raise AttributeError, \
- 'conf in jobfile: %s (%s) is not type %s' % \
- (jobfile, type(conf), Configuration)
- return conf
-
-if __name__ == '__main__':
- from jobfile import *
- import sys
-
- usage = 'Usage: %s [-b] [-c] [-v] <jobfile>' % sys.argv[0]
-
- try:
- import getopt
- opts, args = getopt.getopt(sys.argv[1:], '-bcv')
- except getopt.GetoptError:
- sys.exit(usage)
-
- if len(args) != 1:
- raise AttributeError, usage
-
- both = False
- checkpoint = False
- verbose = False
- for opt,arg in opts:
- if opt == '-b':
- both = True
- checkpoint = True
- if opt == '-c':
- checkpoint = True
- if opt == '-v':
- verbose = True
-
- jobfile = args[0]
- conf = JobFile(jobfile)
-
- if both:
- gen = conf.alljobs()
- elif checkpoint:
- gen = conf.checkpoints()
- else:
- gen = conf.jobs()
-
- for job in gen:
- if not verbose:
- cpt = ''
- if job.checkpoint:
- cpt = job.checkpoint.name
- print job.name, cpt
- else:
- job.printinfo()