1 """Copyright (c) 2005-2016, University of Oxford.
4 University of Oxford means the Chancellor, Masters and Scholars of the
5 University of Oxford, having an administrative office at Wellington
6 Square, Oxford OX1 2JD, UK.
8 This file is part of Chaste.
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 * Neither the name of the University of Oxford nor the names of its
18 contributors may be used to endorse or promote products derived from this
19 software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 Various helpful utility functions/classes used by PyCml.
39 from xml.dom
import Node
45 __all__ = [
'OnlyWarningsFilter',
'OnlyDebugFilter',
'OnlyTheseSourcesFilter',
'NotifyHandler',
47 'Colourable',
'DFS',
'Sentinel',
'unitary_iterator',
48 'amara_parse',
'element_path',
'element_path_cmp',
'element_xpath',
'brief_xml',
49 'call_if',
'max_i',
'prid',
'add_dicts',
50 'open_output_stream',
'close_output_stream']
59 """A filter that only passes warning messages."""
61 return (logging.WARNING <= rec.levelno < logging.ERROR)
65 """A filter that only passes debug messages."""
67 return (logging.DEBUG <= rec.levelno < logging.INFO)
71 """A filter that only emits messages from the given sources."""
73 logging.Filter.__init__(self)
81 A logging handler that just notes if any messages are logged.
84 logging.Handler.__init__(self, level=level)
91 """Reset the handler, as if no messages have occurred."""
96 """Log a debug message to facility.
98 Arguments are treated as for the print statement.
100 logger = logging.getLogger(facility)
101 if logger.isEnabledFor(logging.DEBUG):
102 logger.debug(
' '.join(map(str, args)))
105 def LOG(facility, level, *args):
106 """Log a message to facility with the given level.
108 Arguments are treated as for the print statement.
110 logger = logging.getLogger(facility)
111 if logger.isEnabledFor(level):
112 logger.log(level,
' '.join(map(str, args)))
121 DFS =
Enum(
'White',
'Gray',
'Black')
125 A mixin class for objects that have a colour attribute, and so support
126 a depth-first search.
129 super(Colourable, self).
__init__(*args, **kwargs)
143 """A simple true/false store that can be used as a default parameter value in recursive calls.
145 This provides a slightly nicer looking alternative to code such as:
150 if xyz: done[0] = True
153 The list can be replaced with a Sentinel instance.
156 """Create a new, unset sentinel."""
160 """Test whether the sentinel has been set."""
164 """Set the sentinel."""
169 """An iterator over a single item."""
179 raise StopIteration()
191 def amara_parse(source, uri=None, rules=None, binderobj=None,
193 """Convenience function for parsing XML.
195 Works just as amara.parse, except that if source is '-' then
196 it reads from standard input.
199 return amara.parse(sys.stdin, uri=uri, rules=rules,
200 binderobj=binderobj, prefixes=prefixes)
202 return amara.parse(source, uri=uri, rules=rules,
203 binderobj=binderobj, prefixes=prefixes)
207 """Find the path from the root element to this element."""
208 if hasattr(elt,
'xml_parent'):
210 for child
in elt.xml_parent.xml_children:
211 if getattr(child,
'nodeType',
None) == Node.ELEMENT_NODE:
221 """Compare 2 elements by comparing their paths from the root element."""
226 """Return an xpath expression that will select this element."""
228 xpath =
u'/*[' +
u']/*['.join(map(str, indices)) +
u']'
233 """Print a more concise version of elt.xml() that omits all attributes."""
235 if getattr(elt,
'nodeType',
None) == Node.ELEMENT_NODE:
236 children = getattr(elt,
'xml_children', [])
238 s +=
'<' + elt.localName +
'>'
239 for child
in children:
241 s +=
'</' + elt.localName +
'>'
243 s +=
'<' + elt.localName +
'/>'
256 """Call the given callable with the given arguments iff tf is True."""
258 return callable(*args, **kwargs)
262 """Find the maximum entry of an iterable, and return it with its index.
264 Returns (i, m) where i is the index of m, the maximum entry of `it`.
267 for i, val
in enumerate(it):
268 if m
is None or val > m:
274 """Get the id of an object as a hex string, optionally with its class/type."""
285 """Add multiple dictionaries together.
287 Updates the first input dictionary by adding values from
288 subsequent inputs. Produces a dictionary with keys taken from the
289 input dictionaries, and values being the sum of the corresponding
290 values in all inputs.
291 Assumes values are numeric.
294 for k, v
in d.iteritems():
295 r[k] = r.get(k, 0) + v
299 """Open fname for output.
301 fname should be a local filename, or '-' for standard output.
302 Additionally, the names 'stdout' and 'stderr' have the usual
305 if fname ==
'-' or fname ==
'stdout':
307 elif fname ==
'stderr':
310 stream = open(fname,
'w')
316 Close the given output stream, unless it's one of the standard streams
317 (i.e. sys.stdout or sys.stderr).
318 Note that closing a stream multiple times is safe.
320 if not stream
is sys.stdout
and not stream
is sys.stderr:
def call_if
# Miscellaneous functions # # ...