PageRenderTime 72ms CodeModel.GetById 5ms RepoModel.GetById 1ms app.codeStats 0ms

/TemaLib/tema/coverage/findnewcoverage.py

https://github.com/jaaskel9/tema-tg
Python | 725 lines | 619 code | 47 blank | 59 comment | 52 complexity | 4a5cfb9828a4aef84b4a263b37f21749 MD5 | raw file
  1. """
  2. findnewcoverage tries to find new things in the model.
  3. findnewcoverage can be used with weightguidance, gameguidance, or any guidance
  4. that uses either Requirement.getPercentage() or findnewcoverages own
  5. transitionPoints() method to guide itself.
  6. The "thing" or things findcoverage is trying to find is specified in the
  7. req string given to requirement() function.
  8. --- Examples of req strings:
  9. Find new action words:
  10. "findnew aw"
  11. Set the size of the aw tabulist. To only remember 100 latest action words:
  12. "findnew aw[tabusize:100]"
  13. Find new keyword or new state:
  14. "findnew kw or state"
  15. Set weights for requirements, here keywords are 2x more valuable than states.
  16. Also, only remember the 100 latest states.
  17. "findnew kw[weight:2] or state[weight:1,tabusize:100]"
  18. Find new actionword-stateproposition pairs:
  19. "findnew aw while stateprop"
  20. Find new action-stateproposition pairs and also new states:
  21. ('while' binds stronger than 'or')
  22. "findnew aw while stateprop or state"
  23. Parameters for the whole action-stateprop pair go after while:
  24. "findnew aw while[tabusize:100] stateprop"
  25. Find new ("state-wise unique") switches between apps A and B:
  26. "findnew switch[apps:A B]"
  27. Find new transitions of model components whose name contains Calendar:
  28. "findnew componenttransition[model:model.ext,components:.*Calendar.*]
  29. -----
  30. Common parameter names (accepted by all the reqs):
  31. tabusize:
  32. The size of the tabulist, ie. how many items the requirement remembers.
  33. If tabusize=100 and the 101th item is found, the first one is forgotten,
  34. and if the first one is found again, it will be considered new again.
  35. Either a natural number or "infinite" (default: "infinite").
  36. weight:
  37. The "value" of finding a new such item. Only relevant when there are more
  38. than one items connected with "or".
  39. Weight is either a number or "decreasing" (default: "decreasing").
  40. "decreasing" = 1/(N+1) where N is the number of items found so far.
  41. Only weightguidance understands custom weights, gameguidance etc. ignore em.
  42. Single reqs::
  43. aw:
  44. action words (unique by name)
  45. kw:
  46. keywords (unique by name)
  47. state:
  48. unique states
  49. transition:
  50. unique transitions = (source_state,action,dest_state)
  51. stateprop:
  52. unique state propositions
  53. switch:
  54. "state-wise" unique switches from one application to other.
  55. Special required params:
  56. apps:App1 App2 ...
  57. The apps we're trying to switch between.
  58. The appnames must contain the device name(??). Eg. "MyPhone/App1".
  59. componenttransition:
  60. unique transitions of the given model components.
  61. Special params:
  62. (either give both 'model' and 'components',
  63. or neither to search for all the component transitions)
  64. model:MODELFILENAME
  65. The parallel composition model, eg. target/combined-rules.ext
  66. components:C1 C2 ...
  67. the component names, whitespace-separated, may be regexp,
  68. eg. .*Switcher.* Note that the component names must be in the
  69. same format as in the model file, so there may be some device etc.
  70. stuff in front of the actual model name, eg. DeviceX/rm/ModelName
  71. ...
  72. """
  73. version = "0.0003"
  74. import re
  75. from tema.coverage.tabulist import TabuList
  76. from tema.coverage.coverage import Requirement, CombinedRequirement, ecoAnd
  77. def requirement(req, model=None):
  78. """ Returns a TabuRequirement object based on the req string.
  79. """
  80. if hasattr(requirement,"log"):
  81. TabuRequirement.log = requirement.log
  82. try:
  83. tabuTitle,tabuStr = req.split(None,1) # if no space, raises ValueError
  84. if tabuTitle.lower() != "findnew":
  85. raise ValueError("findnewcoverage req should start with 'findnew '")
  86. except ValueError:
  87. raise ValueError("Invalid tabu string: '%s'" % req)
  88. return TabuRequirement(tabuStr)
  89. _PARAM_PATTERN = r"(?:\[([^\]]*)\])?"
  90. _OR_PATTERN = r"\s+or\s*" + _PARAM_PATTERN + r"\s+"
  91. _RE_OR = re.compile(_OR_PATTERN, re.I)
  92. # accepting 'and' as 'while', for now...
  93. _WHILE_PATTERN = r"\s+(?:while)|(?:and)\s*" + _PARAM_PATTERN + r"\s+"
  94. _RE_WHILE = re.compile(_WHILE_PATTERN, re.I)
  95. _SINGLE_PATTERN = r"\s*([^\s\[]+)\s*" + _PARAM_PATTERN + r"\s*"
  96. _RE_SINGLE = re.compile(_SINGLE_PATTERN, re.I)
  97. class TabuRequirement(Requirement,object):
  98. """ """
  99. def __new__(cls,tabuStr,unused=None):
  100. # TODO: improve parsing, parentheses, etc.
  101. if _RE_OR.search(tabuStr):
  102. return object.__new__(OrTabuRequirement)
  103. if _RE_WHILE.search(tabuStr):
  104. return object.__new__(WhileTabuRequirement)
  105. if _RE_SINGLE.match(tabuStr):
  106. return SingleTabuRequirement.__new__(cls,tabuStr)
  107. raise ValueError("Invalid tabu string: '%s'" % tabuStr)
  108. def __init__(self,paramStr):
  109. # default params:
  110. self.setParameter("weight","decreasing")
  111. self._tabuList = TabuList()
  112. # user-given params:
  113. self.setParameterStr(paramStr)
  114. def setParameterStr(self,paramStr):
  115. if not paramStr:
  116. return
  117. for pair in paramStr.split(","):
  118. name,value = pair.split(":",1)
  119. self.setParameter(name,value)
  120. def setParameter(self,name,value):
  121. name = name.lower()
  122. if name in ("size","tabusize"):
  123. self._tabuList = TabuList( _parseSize(value) )
  124. elif name == "weight":
  125. if value in ("decreasing","decr"):
  126. self.weight = self._decreasingWeight
  127. else:
  128. self.weight = lambda: 1
  129. elif name == "name":
  130. self._name = value
  131. else:
  132. print __doc__
  133. raise ValueError(
  134. "Invalid param '%s' for %s"%(name,self.__class__.__name__))
  135. def getPercentage(self):
  136. """ Doesn't actually return "coverage" per se, but is a function that's
  137. getting closer and closer to 1 as new items are found.
  138. This means that the more items have been found,
  139. the less a new one improves coverage.
  140. """
  141. # the usual python floats have precision of ~16 digits,
  142. # -> tabulist sizes up to 16**10, so precision shouldn't be a problem
  143. return 1 - 1.0/(self._tabuList.lenUnique()+1)
  144. def getExecutionHint(self):
  145. raise NotImplementedError()
  146. def markExecuted(self,transition):
  147. # if using filterRelevant instead of filterNew, this would work a bit
  148. # differently in the case of a limited size tabulist.
  149. # not sure which is the best. see findnewcoverage_test.py.
  150. for item in self.filterNew(transition):
  151. #if self._tabuList._pushLevel == 0:
  152. # self.log("FOUND: %s" % (item,))
  153. self._tabuList.add(item)
  154. # subclasses must implement filterRelevant
  155. # this is the func that yields all the things in the transition that
  156. # the TabuRequirement is interested in. (eg. aw for aw-requirement, etc.)
  157. def filterRelevant(self,transition):
  158. raise NotImplementedError()
  159. def filterNew(self,transition):
  160. """ yields all the new things found by executing the transition """
  161. for item in self.filterRelevant(transition):
  162. if item not in self._tabuList:
  163. yield item
  164. def filterOld(self,transition):
  165. for item in self.filterRelevant(transition):
  166. if item in self._tabuList:
  167. yield item
  168. def transitionPoints(self,transition):
  169. """ how many points executing this transitition gives.
  170. point = (number of new items) * weight
  171. """
  172. p = 0
  173. for item in self.filterNew(transition):
  174. p += 1
  175. return p * self.weight()
  176. def weight(self):
  177. return self._weight
  178. def _decreasingWeight(self):
  179. return 1.0/(self._tabuList.lenUnique()+1)
  180. def push(self):
  181. self._tabuList.push()
  182. def pop(self):
  183. self._tabuList.pop()
  184. class SingleTabuRequirement(TabuRequirement):
  185. """ a single tabu requirement.
  186. the type is specified in the tabustring given to constructor."""
  187. def __new__(cls,tabuStr):
  188. typeStr,paramStr = _RE_SINGLE.findall(tabuStr)[0]
  189. if typeStr == "switch":
  190. return object.__new__(SwitchTabuRequirement)
  191. elif typeStr == "componenttransition":
  192. return object.__new__(ComponentTransitionTabuRequirement)
  193. else:
  194. # a simple, non-special SingleTabuRequirement whose filter
  195. # is simply determined by the type (no need for extra params).
  196. return object.__new__(SingleTabuRequirement)
  197. def __init__(self,tabuStr):
  198. typeStr,paramStr = _RE_SINGLE.findall(tabuStr)[0]
  199. self._name = typeStr.strip().lower()
  200. self._tabuFilter = tabuFilterByType(self._name)
  201. TabuRequirement.__init__(self,paramStr)
  202. def filterRelevant(self,transition):
  203. return self._tabuFilter(transition)
  204. class ComponentTransitionTabuRequirement(SingleTabuRequirement):
  205. """Finds new transitions of given model components.
  206. findnew componenttransition[model:MODELFILE,components=COMPONENTNAMES]
  207. MODELFILE = The parallel composition model, eg. target/combined-rules.ext
  208. COMPONENTNAMES = The names of the model components whose transitions we
  209. are searching.
  210. """
  211. def __init__(self,tabuStr):
  212. self._model = None
  213. self._components = []
  214. SingleTabuRequirement.__init__(self,tabuStr)
  215. def setParameter(self,name,value):
  216. if name == "components":
  217. self._components = value.strip().split()
  218. self._createFilter()
  219. elif name == "model":
  220. self._model = value
  221. self._createFilter()
  222. else:
  223. SingleTabuRequirement.setParameter(self,name,value)
  224. def _createFilter(self,raiseIfFails=False):
  225. if self._model and self._components:
  226. # Assumes that:
  227. # N first rows of _model file are the components in the parallel
  228. # composition. (Only) these rows match _RE_COMPONENT_FILE.
  229. # The components are in the same order as in the parallel state id.
  230. # These rows tell the name of model component file (relative to
  231. # the dir of model file).
  232. # The model component files contain "Transition_cnt = XX" line.
  233. # + propably something else...
  234. import os.path
  235. compFiles = {} # key: the index in parallel composition
  236. _RE_COMPONENT_FILE = re.compile('([^()=]*)="([^()]*)"')
  237. # the component filenames are relative to this path:
  238. modeldir = os.path.dirname(self._model)
  239. f = open(self._model)
  240. try:
  241. for num, line in enumerate(f):
  242. match = _RE_COMPONENT_FILE.match(line)
  243. if not match:
  244. break
  245. compname,filename = match.groups()
  246. for comp in self._components:
  247. if re.match(comp+"$",compname):
  248. self.log("Searching for transitions of component %i: %s" % (num,compname,))
  249. compFiles[num] = os.path.join(modeldir,filename)
  250. break # each component only once
  251. finally:
  252. f.close()
  253. # finding out the total num of transitions from component files
  254. numTrans = 0
  255. for num,filename in compFiles.iteritems():
  256. cf = open(filename)
  257. try:
  258. inHeader = False
  259. for line in cf:
  260. li = line.strip().lower()
  261. if inHeader:
  262. if li.startswith("transition_cnt"):
  263. numTrans += int(li.rsplit(None,1)[-1])
  264. break
  265. elif li.startswith("end header"):
  266. raise IOError(
  267. "No Transition_cnt in '''%s'''" % (
  268. filename,))
  269. elif li.startswith("begin header"):
  270. inHeader = True
  271. finally:
  272. cf.close()
  273. self._numTrans = numTrans
  274. compIndices = [i for i in compFiles.iterkeys()]
  275. self._tabuFilter = createComponentTransitionFilter(compIndices)
  276. else:
  277. # either 'model' or 'components' param is not given.
  278. # no need to panic yet, since the missing param may be coming.
  279. self._tabuFilter = createUndefinedFilter("componenttransition "\
  280. "needs both 'model' and 'components' params! (or neither to "\
  281. "find transitions of every component).")
  282. def getPercentage(self):
  283. return float(self._tabuList.lenUnique()) / self._numTrans
  284. class OperatorTabuRequirement(TabuRequirement):
  285. """ OperatorTabuRequirement delegates the push/pop/markExecuted/...
  286. calls to its children reqs.
  287. """
  288. def markExecuted(self,transition):
  289. TabuRequirement.markExecuted(self,transition)
  290. for r in self._requirements:
  291. r.markExecuted(transition)
  292. def push(self):
  293. for r in self._requirements:
  294. r.push()
  295. TabuRequirement.push(self)
  296. def pop(self):
  297. for r in self._requirements:
  298. r.pop()
  299. TabuRequirement.pop(self)
  300. class OrTabuRequirement(OperatorTabuRequirement):
  301. """ req1 or req2
  302. The coverage is improved if either req1 or req2 is improved.
  303. """
  304. def __init__(self, tabuStr):
  305. r1,paramStr,r2 = _RE_OR.split(tabuStr,1)
  306. self._requirements = [TabuRequirement(t) for t in [r1,r2]]
  307. self._name = "OR"
  308. TabuRequirement.__init__(self,paramStr)
  309. def filterRelevant(self, transition):
  310. """ Yields pairs (i,item), where item is something yielded by a filter
  311. of a req whose index is i.
  312. """
  313. for i,req in enumerate(self._requirements):
  314. for item in req.filterRelevant(transition):
  315. thatReqsItem = (i,item)
  316. yield thatReqsItem
  317. def transitionPoints(self, transition):
  318. return sum([r.transitionPoints(transition) for r in self._requirements])
  319. class WhileTabuRequirement(TabuRequirement):
  320. """ req1 while req2
  321. The coverage is improved if req1 and req2 are improved at the same time
  322. (= on the same transition execution).
  323. """
  324. def __init__(self, tabuStr):
  325. r1,paramStr,r2 = _RE_WHILE.split(tabuStr,1)
  326. self._requirements = [TabuRequirement(r) for r in [r1,r2]]
  327. self._name = "WHILE"
  328. TabuRequirement.__init__(self,paramStr)
  329. def filterRelevant(self, transition):
  330. """ Yields all the possible tuples of the form (y1,y2,...) where
  331. y1 is something yielded by the filter of my first requirement,
  332. and so on.
  333. Eg. if my reqs were "action" and "stateprop", I would yield
  334. all the action-stateprop pairs.
  335. """
  336. startsOfTuples = [ () ]
  337. for r in self._requirements:
  338. oneLongerStartsOfTuples = []
  339. for sot in startsOfTuples:
  340. for x in r.filterRelevant(transition):
  341. oneLongerStartsOfTuples.append( sot+(x,) )
  342. startsOfTuples = oneLongerStartsOfTuples
  343. # they're full tuples now
  344. for t in startsOfTuples:
  345. yield t
  346. class SwitchTabuRequirement(SingleTabuRequirement):
  347. """ switch[apps:A B C] """
  348. def __init__(self, tabuStr):
  349. typeStr,paramStr = _RE_SINGLE.findall(tabuStr)[0]
  350. self._fromApp = None
  351. self._fromState = None
  352. self._fromStack = []
  353. SingleTabuRequirement.__init__(self,tabuStr)
  354. self.setParameter('statewise',1)
  355. def setParameter(self,name,value):
  356. if name == "apps":
  357. self.log("APPS")
  358. appNames = value.split()
  359. self._tabuFilter = createAppNameFilter(appNames)
  360. # _actFilter deals with "X ACTIVATES Y" kinda switches
  361. self._actFilter = createActivatesFilter(appNames)
  362. elif name == "statewise":
  363. try: self._statewise = not not int(value)
  364. except ValueError:
  365. raise ValueError("statewise must be either 0 or 1")
  366. if self._statewise:
  367. self.filterRelevant = self._filterRelevantStatewise
  368. else:
  369. self.filterRelevant = self._filterRelevantAppwise
  370. else:
  371. SingleTabuRequirement.setParameter(self,name,value)
  372. def markExecuted(self, transition):
  373. TabuRequirement.markExecuted(self,transition)
  374. for fromApp in self._tabuFilter(transition):
  375. self._fromApp = fromApp
  376. self._fromState = transition.getDestState()
  377. break
  378. for fromApp,toApp in self._actFilter(transition):
  379. self._fromApp = toApp
  380. def _filterRelevantStatewise(self,transition):
  381. for toApp in self._tabuFilter(transition):
  382. if self._fromApp is not None and self._fromApp != toApp:
  383. yield (self._fromState,transition.getDestState())
  384. for fromApp,toApp in self._actFilter(transition):
  385. yield (transition.getSourceState(), transition.getDestState())
  386. def _filterRelevantAppwise(self,transition):
  387. for toApp in self._tabuFilter(transition):
  388. if self._fromApp is not None and self._fromApp != toApp:
  389. yield (self._fromApp, toApp)
  390. for fromApp,toApp in self._actFilter(transition):
  391. yield (fromApp, toApp)
  392. def push(self):
  393. self._fromStack.append( (self._fromApp,self._fromState) )
  394. TabuRequirement.push(self)
  395. def pop(self):
  396. self._fromApp,self._fromState = self._fromStack.pop()
  397. TabuRequirement.pop(self)
  398. def _parseSize(size):
  399. if size in ("","infinity","infinite","inf","unlimited"):
  400. retSize = None
  401. else:
  402. try:
  403. retSize = int(size) # may raise ValueError
  404. if retSize < 0: raise ValueError()
  405. except ValueError:
  406. raise ValueError("Invalid size: '%s'. "%size +
  407. "It should be a natural number or 'infinite'.")
  408. return retSize
  409. # "tabu filters" take a transition as a parameter.
  410. # if the transition is something the tabu filter is intrested in, it yields
  411. # something that identifies the thing they're tabuing.
  412. # Eg. destStateFilter yields the destination state of the transition.
  413. # yielding instead of returning because there may be multiple things to yield,
  414. # like in statePropFilter.
  415. def destStateFilter(transition):
  416. yield str(transition.getDestState())
  417. def sourceStateFilter(transition):
  418. yield str(transition.getSourceState())
  419. def transitionFilter(transition):
  420. yield transition
  421. def edgeFilter(transition):
  422. yield transition.getAction()
  423. def startAWFilter(transition):
  424. action = transition.getAction()
  425. if "start_aw" in str(action) and "TaskSwitcherGEN" not in str(action):
  426. yield action
  427. def sourceStateOfStartAWFilter(transition):
  428. for a in startAWFilter(transition):
  429. yield transition.getSourceState()
  430. def destStateOfStartAWFilter(transition):
  431. for a in startAWFilter(transition):
  432. yield transition.getSourceState()
  433. def endAWFilter(transition):
  434. action = transition.getAction()
  435. if "end_aw" in str(action) and "TaskSwitcherGEN" not in str(action):
  436. yield action
  437. def sourceStateOfEndAWFilter(transition):
  438. for a in endAWFilter(transition):
  439. yield transition.getSourceState()
  440. def destStateOfEndAWFilter(transition):
  441. for a in endAWFilter(transition):
  442. yield transition.getDestState()
  443. def wakeFilter(transition):
  444. if str(transition.getAction()).startswith("WAKEtsWAKE"):
  445. yield True
  446. def keywordFilter(transition):
  447. action = transition.getAction()
  448. if str(action).startswith("kw"): # or "kw_"?
  449. yield action
  450. def statePropFilter(transition):
  451. action = transition.getAction()
  452. # getStateProps() sometimes seems to return multiple equal stateProps.
  453. # yielding only one of each.
  454. props = set()
  455. for sp in transition.getSourceState().getStateProps():
  456. if "SleepState" not in str(sp):
  457. props.add( str(sp) )
  458. for spStr in props:
  459. yield spStr
  460. def statePropInclSleepFilter(transition):
  461. action = transition.getAction()
  462. # getStateProps() sometimes seems to return multiple equal stateProps.
  463. # yielding only one of each.
  464. props = set()
  465. for sp in transition.getSourceState().getStateProps():
  466. props.add( str(sp) )
  467. for spStr in props:
  468. yield spStr
  469. def createAppNameFilter(appNames):
  470. def appNameFilter(transition):
  471. aStr = str(transition.getAction())
  472. for app in appNames:
  473. if aStr.startswith(app):
  474. yield app
  475. return appNameFilter
  476. _RE_ACTIVATES = re.compile("(.*) ACTIVATES (.*)")
  477. def createActivatesFilter(appNames):
  478. def appNameFilter(transition):
  479. aStr = str(transition.getAction())
  480. if not " ACTIVATES " in aStr:
  481. return
  482. x, y = _RE_ACTIVATES.match(aStr).groups()
  483. if "/" in x:
  484. # if there's a device name in x, prepend it y also
  485. y = x.split("/",1)[0] + "/" + y
  486. a1, a2 = None, None
  487. for app in appNames:
  488. if x.startswith(app):
  489. a1 = app
  490. if y.startswith(app):
  491. a2 = app
  492. if a1 and a2 and (a1 != a2):
  493. yield (a1,a2)
  494. return appNameFilter
  495. def createWakeFilter(appNames):
  496. _wake_re = re.compile(
  497. r"WAKEtsWAKE<(%s).*>" %
  498. (r"|".join(["(?:%s)" % a for a in appNames])) )
  499. def wakeFilter(transition):
  500. for app in _wake_re.findall( str(transition.getAction()) ):
  501. yield app
  502. return wakeFilter
  503. def createSleepFilter(appNames):
  504. _sleep_re = re.compile(
  505. r"SLEEPts<(%s).*>" %
  506. (r"|".join([r"(?:%s)" % a for a in appNames])) )
  507. def sleepFilter(transition):
  508. for app in _sleep_re.findall( str(transition.getAction()) ):
  509. yield app
  510. return sleepFilter
  511. def createOfFilter(thisOf,ofThis):
  512. def ofFilter(transition):
  513. for unused in ofThis(transition):
  514. break
  515. else:
  516. return
  517. for item in thisOf(transition):
  518. yield item
  519. return ofFilter
  520. def createCompoFilter(filters):
  521. """ Takes some filters and returns a filter that yields all the possible
  522. tuples of the form (y1,y2,...) where y1 is something yielded by
  523. the first filter, and so on.
  524. Eg. createCompoFilter( [startAWFilter,statePropFilter] )
  525. returns a filter that yields all the (action,stateprop) pairs of
  526. the given transition.
  527. """
  528. def compoFilter(transition):
  529. startsOfTuples = [ () ]
  530. for filt in filters:
  531. oneLongerStartsOfTuples = []
  532. for sot in startsOfTuples:
  533. for x in filt(transition):
  534. oneLongerStartsOfTuples.append( sot+(x,) )
  535. startsOfTuples = oneLongerStartsOfTuples
  536. # they're full tuples now
  537. for t in startsOfTuples:
  538. yield t
  539. return compoFilter
  540. def createComponentTransitionFilter(comps=None):
  541. if comps is None:
  542. # all the components
  543. def componentTransitionFilter(transition):
  544. numComps = len(transition.getSourceState()._id)
  545. for n in xrange(numComps):
  546. # does the state of component n change?
  547. source = transition.getSourceState()._id[n]._id
  548. dest = transition.getDestState()._id[n]._id
  549. if source != dest:
  550. yield (n,source,str(transition.getAction()),dest)
  551. componentTransitionFilter.__doc__ = """
  552. Yields all the component transitions that are executed when
  553. the given (parallel) transition is executed."""
  554. else:
  555. # only the given component indices
  556. def componentTransitionFilter(transition):
  557. for n in comps:
  558. # does the state of component n change?
  559. source = transition.getSourceState()._id[n]._id
  560. dest = transition.getDestState()._id[n]._id
  561. if source != dest:
  562. yield (n,source,str(transition.getAction()),dest)
  563. componentTransitionFilter.__doc__ = """
  564. Yields all the transitions of components %s that are executed when
  565. the given (parallel) transition is executed.""" % (comps,)
  566. return componentTransitionFilter
  567. def createUndefinedFilter(text):
  568. def filter(*args):
  569. raise ValueError(text)
  570. return filter
  571. TABU_FILTERS = {
  572. "sourcestate": sourceStateFilter,
  573. "deststate": destStateFilter,
  574. "state": destStateFilter,
  575. "transition": transitionFilter,
  576. "edge": edgeFilter,
  577. "keyword": keywordFilter,
  578. "kw": keywordFilter,
  579. "stateprop": statePropFilter,
  580. "stateproposition": statePropFilter,
  581. "statepropinclsleep": statePropInclSleepFilter,
  582. "wake": wakeFilter,
  583. "end_aw": endAWFilter,
  584. "start_aw": startAWFilter,
  585. "aw": startAWFilter,
  586. #"action": startAWFilter, # 'action' is too ambiguous...
  587. "source_state_of_start_aw": createOfFilter(sourceStateFilter,startAWFilter),
  588. "source_state_of_end_aw": createOfFilter(sourceStateFilter,endAWFilter),
  589. "dest_state_of_start_aw": createOfFilter(destStateFilter,startAWFilter),
  590. "dest_state_of_end_aw": createOfFilter(destStateFilter,endAWFilter),
  591. "stateprop_of_endaw": createOfFilter(statePropFilter, endAWFilter),
  592. "componenttransition": createComponentTransitionFilter(),
  593. "switch": createUndefinedFilter("switch needs a param 'apps'")
  594. }
  595. def tabuFilterByType(filterName):
  596. if filterName in TABU_FILTERS:
  597. return TABU_FILTERS[filterName]
  598. raise ValueError("Invalid filter name: '%s'"%(filterName,))