The Gaudi Framework  master (9f3f8895)
Loading...
Searching...
No Matches
GaudiKernel.Configurable Namespace Reference

Classes

class  _DefaultPropertiesCollectorHelper
class  Error
class  PropertyReference
class  Configurable
class  DummyDescriptor
class  ConfigurableGeneric
class  ConfigurableAlgorithm
class  ConfigurableService
class  ConfigurableAlgTool
class  ConfigurableAuditor
class  ConfigurableUser
class  CreateSequencesVisitor
class  SuperAlgorithm

Functions

 expandvars (data)
 appendPostConfigAction (function)
 removePostConfigAction (function)
 applyConfigurableUsers ()
 applyConfigurableUsers_old ()
 getNeededConfigurables ()
 purge ()
 makeSequences (expression)

Variables

list __all__
 log = logging.getLogger("Configurable")
list postConfigActions = []
bool _appliedConfigurableUsers_ = False

Function Documentation

◆ appendPostConfigAction()

appendPostConfigAction ( function)
Add a new callable ('function') to the list of post-configuration actions.
If the callable is already in the list, it is moved to the end of the list.
The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.

Definition at line 1568 of file Configurable.py.

1568def appendPostConfigAction(function):
1569 """
1570 Add a new callable ('function') to the list of post-configuration actions.
1571 If the callable is already in the list, it is moved to the end of the list.
1572 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1573 """
1574 try:
1575 postConfigActions.remove(function)
1576 except Exception:
1577 pass
1578 postConfigActions.append(function)
1579
1580

◆ applyConfigurableUsers()

applyConfigurableUsers ( )
Call the apply method of all the ConfigurableUser instances respecting the
dependencies. First the C.U.s that are not used by anybody, then the used
ones, when they are not used anymore.

Definition at line 1592 of file Configurable.py.

1592def applyConfigurableUsers():
1593 """
1594 Call the apply method of all the ConfigurableUser instances respecting the
1595 dependencies. First the C.U.s that are not used by anybody, then the used
1596 ones, when they are not used anymore.
1597 """
1598 # Avoid double calls
1599 global _appliedConfigurableUsers_, postConfigActions
1600 if _appliedConfigurableUsers_:
1601 return
1602 _appliedConfigurableUsers_ = True
1603
1604 def applicableConfUsers():
1605 """
1606 Generator returning all the configurables that can be applied in the
1607 order in which they can be applied.
1608 """
1609 # This is tricky...
1610 # We keep on looking for the first configurable that can be applied.
1611 # When we cannot find any, 'next()' raises a StopIteration that is
1612 # propagated outside of the infinite loop and the function, then handled
1613 # correctly from outside (it is the exception that is raised when you
1614 # exit from a generator).
1615 # Checking every time the full list is inefficient, but it is the
1616 # easiest way to fix bug #103803.
1617 # <https://savannah.cern.ch/bugs/?103803>
1618 while True:
1619 try:
1620 yield next(
1621 c
1622 for c in Configurable.allConfigurables.values()
1623 if c.isApplicable()
1624 )
1625 except StopIteration:
1626 break
1627
1628 debugApplyOrder = "GAUDI_DUBUG_CONF_USER" in os.environ
1629 for c in applicableConfUsers():
1630 if c._enabled:
1631 log.info("applying configuration of %s", c.name())
1632 if debugApplyOrder:
1633 sys.stderr.write(f"applying {c!r}")
1634 c.__apply_configuration__()
1635 log.info(c)
1636 else:
1637 log.info("skipping configuration of %s", c.name())
1638 c._applied = True # flag the instance as already applied
1639 if hasattr(c, "__detach_used__"):
1640 # tells the used configurables that they are not needed anymore
1641 c.__detach_used__()
1642
1643 # check for dependency loops
1644 leftConfUsers = [
1645 c
1646 for c in Configurable.allConfigurables.values()
1647 if hasattr(c, "__apply_configuration__") and c._enabled and not c._applied
1648 ]
1649 # if an enabled configurable has not been applied, there must be a dependency loop
1650 if leftConfUsers:
1651 raise Error(
1652 "Detected loop in the ConfigurableUser"
1653 " dependencies: %r" % [c.name() for c in leftConfUsers]
1654 )
1655 # ensure that all the Handles have been triggered
1656 known = set()
1657 unknown = set(Configurable.allConfigurables)
1658 while unknown:
1659 for k in unknown:
1660 if not known: # do not print during the first iteration
1661 log.debug("new configurable created automatically: %s", k)
1662 # this trigger the instantiation from handles
1663 Configurable.allConfigurables[k].properties()
1664 known.add(k)
1665 unknown -= known
1666 # Call post-config actions
1667 for action in postConfigActions:
1668 action()
1669
1670

◆ applyConfigurableUsers_old()

applyConfigurableUsers_old ( )
Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
backward compatibility for configurations that where relying (implicitly) on
bug #103803, or on a specific (non guaranteed) order of execution.

@see applyConfigurableUsers()

Definition at line 1671 of file Configurable.py.

1671def applyConfigurableUsers_old():
1672 """
1673 Obsolete (buggy) implementation of applyConfigurableUsers(), kept to provide
1674 backward compatibility for configurations that where relying (implicitly) on
1675 bug #103803, or on a specific (non guaranteed) order of execution.
1676
1677 @see applyConfigurableUsers()
1678 """
1679 # Avoid double calls
1680 global _appliedConfigurableUsers_, postConfigActions
1681 if _appliedConfigurableUsers_:
1682 return
1683 _appliedConfigurableUsers_ = True
1684
1685 debugApplyOrder = "GAUDI_DUBUG_CONF_USER" in os.environ
1686 confUsers = [
1687 c
1688 for c in Configurable.allConfigurables.values()
1689 if hasattr(c, "__apply_configuration__")
1690 ]
1691 applied = True # needed to detect dependency loops
1692 while applied and confUsers:
1693 newConfUsers = [] # list of conf users that cannot be applied yet
1694 applied = False
1695 for c in confUsers:
1696 if hasattr(c, "__users__") and c.__users__:
1697 newConfUsers.append(c) # cannot use this one yet
1698 else: # it does not have users or the list is empty
1699 applied = True
1700 # the ConfigurableUser is enabled if it doesn't have an _enabled
1701 # property or its value is True
1702 enabled = (not hasattr(c, "_enabled")) or c._enabled
1703 if enabled:
1704 log.info("applying configuration of %s", c.name())
1705 if debugApplyOrder:
1706 sys.stderr.write(f"applying {c!r}")
1707 c.__apply_configuration__()
1708 log.info(c)
1709 else:
1710 log.info("skipping configuration of %s", c.name())
1711 if hasattr(c, "__detach_used__"):
1712 # tells the used configurables that they are not needed anymore
1713 c.__detach_used__()
1714 confUsers = newConfUsers # list of C.U.s still to go
1715 if confUsers:
1716 # this means that some C.U.s could not be applied because of a dependency loop
1717 raise Error(
1718 "Detected loop in the ConfigurableUser "
1719 " dependencies: %r" % [c.name() for c in confUsers]
1720 )
1721 # ensure that all the Handles have been triggered
1722 known = set()
1723 unknown = set(Configurable.allConfigurables)
1724 while unknown:
1725 for k in unknown:
1726 if not known: # do not print during the first iteration
1727 log.debug("new configurable created automatically: %s", k)
1728 # this trigger the instantiation from handles
1729 Configurable.allConfigurables[k].properties()
1730 known.add(k)
1731 unknown -= known
1732 # Call post-config actions
1733 for action in postConfigActions:
1734 action()
1735
1736

◆ expandvars()

expandvars ( data)
Expand environment variables "data".
Data can be string, list, tuple and dictionary. For collection, all the
contained strings will be manipulated (recursively).

Definition at line 82 of file Configurable.py.

82def expandvars(data):
83 """
84 Expand environment variables "data".
85 Data can be string, list, tuple and dictionary. For collection, all the
86 contained strings will be manipulated (recursively).
87 """
88 import os.path
89
90 typ = type(data)
91 if typ is str:
92 return os.path.expandvars(data)
93 elif typ in [list, tuple]:
94 collect = []
95 for i in data:
96 collect.append(expandvars(i))
97 return typ(collect)
98 elif typ is dict:
99 collect = {}
100 for k in data:
101 collect[expandvars(k)] = expandvars(data[k])
102 return collect
103 return data
104
105

◆ getNeededConfigurables()

getNeededConfigurables ( )
Function to select all and only the configurables that have to be used in
GaudiPython.AppMgr constructor.
This is needed because in Athena the implementation have to be different (the
configuration is used in a different moment).

Definition at line 1737 of file Configurable.py.

1737def getNeededConfigurables():
1738 """
1739 Function to select all and only the configurables that have to be used in
1740 GaudiPython.AppMgr constructor.
1741 This is needed because in Athena the implementation have to be different (the
1742 configuration is used in a different moment).
1743 """
1744 return sorted(
1745 k
1746 for k, v in Configurable.allConfigurables.items()
1747 if v.getGaudiType() != "User"
1748 ) # Exclude ConfigurableUser instances
1749
1750

◆ makeSequences()

makeSequences ( expression)
Convert a control flow expression to nested GaudiSequencers.

Definition at line 1829 of file Configurable.py.

1829def makeSequences(expression):
1830 """
1831 Convert a control flow expression to nested GaudiSequencers.
1832 """
1833 if not isinstance(expression, ControlFlowNode):
1834 raise ValueError(
1835 f"ControlFlowNode instance expected, got {type(expression).__name__}"
1836 )
1837 visitor = CreateSequencesVisitor()
1838 expression.visitNode(visitor)
1839 return visitor.sequence
1840
1841

◆ purge()

purge ( )
Clean up all configurations and configurables.

Definition at line 1751 of file Configurable.py.

1751def purge():
1752 """
1753 Clean up all configurations and configurables.
1754 """
1755 for c in Configurable.allConfigurables.values():
1756 c.__class__.configurables.clear()
1757 Configurable.allConfigurables.clear()
1758 # FIXME: (MCl) this is needed because instances of ConfigurableGeneric are not
1759 # migrated to the correct class when this is known.
1760 ConfigurableGeneric.configurables.clear()
1761 import os.path
1762 import sys
1763
1764 from .ProcessJobOptions import _included_files
1765
1766 for file in _included_files:
1767 dirname, basname = os.path.split(file)
1768 basname, ext = os.path.splitext(basname)
1769 if basname in sys.modules:
1770 del sys.modules[basname]
1771 _included_files.clear()
1772
1773

◆ removePostConfigAction()

removePostConfigAction ( function)
Remove a callable from the list of post-config actions.
The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.

Definition at line 1581 of file Configurable.py.

1581def removePostConfigAction(function):
1582 """
1583 Remove a callable from the list of post-config actions.
1584 The list is directly accessible as 'GaudiKernel.Configurable.postConfigActions'.
1585 """
1586 postConfigActions.remove(function)
1587
1588

Variable Documentation

◆ __all__

list GaudiKernel.Configurable.__all__
private
Initial value:
= [
"Configurable",
"ConfigurableAlgorithm",
"ConfigurableAlgTool",
"ConfigurableAuditor",
"ConfigurableService",
"ConfigurableUser",
"VERBOSE",
"DEBUG",
"INFO",
"WARNING",
"ERROR",
"FATAL",
"appendPostConfigAction",
"removePostConfigAction",
]

Definition at line 54 of file Configurable.py.

◆ _appliedConfigurableUsers_

bool GaudiKernel.Configurable._appliedConfigurableUsers_ = False
protected

Definition at line 1589 of file Configurable.py.

◆ log

GaudiKernel.Configurable.log = logging.getLogger("Configurable")

Definition at line 79 of file Configurable.py.

◆ postConfigActions

list GaudiKernel.Configurable.postConfigActions = []

Definition at line 1565 of file Configurable.py.