From: Christian Van Wambeke Date: Tue, 24 Apr 2018 11:31:06 +0000 (+0200) Subject: add doc/build for EZ direct html or pdf X-Git-Tag: 5.1.0~35 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a99a6f7bf7be23bb64bdd090ab709d14498449f4;p=tools%2Fsat.git add doc/build for EZ direct html or pdf --- diff --git a/.gitignore b/.gitignore index 86431c4..2337686 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,8 @@ sat-py3 .pydevproject .project .settings -doc/build +# doc/build +doc/build/latex/salomeTools.log .coverage test/htmlcov test/test_res.html diff --git a/doc/build/doctrees/commands/apidoc/modules.doctree b/doc/build/doctrees/commands/apidoc/modules.doctree new file mode 100644 index 0000000..253388e Binary files /dev/null and b/doc/build/doctrees/commands/apidoc/modules.doctree differ diff --git a/doc/build/doctrees/commands/apidoc/src.colorama.doctree b/doc/build/doctrees/commands/apidoc/src.colorama.doctree new file mode 100644 index 0000000..a675d20 Binary files /dev/null and b/doc/build/doctrees/commands/apidoc/src.colorama.doctree differ diff --git a/doc/build/doctrees/commands/apidoc/src.doctree b/doc/build/doctrees/commands/apidoc/src.doctree new file mode 100644 index 0000000..635ba6e Binary files /dev/null and b/doc/build/doctrees/commands/apidoc/src.doctree differ diff --git a/doc/build/doctrees/commands/application.doctree b/doc/build/doctrees/commands/application.doctree new file mode 100644 index 0000000..90f3f1b Binary files /dev/null and b/doc/build/doctrees/commands/application.doctree differ diff --git a/doc/build/doctrees/commands/clean.doctree b/doc/build/doctrees/commands/clean.doctree new file mode 100644 index 0000000..3fb9817 Binary files /dev/null and b/doc/build/doctrees/commands/clean.doctree differ diff --git a/doc/build/doctrees/commands/compile.doctree b/doc/build/doctrees/commands/compile.doctree new file mode 100644 index 0000000..a595a1e Binary files /dev/null and b/doc/build/doctrees/commands/compile.doctree differ diff --git a/doc/build/doctrees/commands/config.doctree b/doc/build/doctrees/commands/config.doctree new file mode 100644 index 0000000..52f56f6 Binary files /dev/null and b/doc/build/doctrees/commands/config.doctree differ diff --git a/doc/build/doctrees/commands/environ.doctree b/doc/build/doctrees/commands/environ.doctree new file mode 100644 index 0000000..6266339 Binary files /dev/null and b/doc/build/doctrees/commands/environ.doctree differ diff --git a/doc/build/doctrees/commands/generate.doctree b/doc/build/doctrees/commands/generate.doctree new file mode 100644 index 0000000..ec0b4ff Binary files /dev/null and b/doc/build/doctrees/commands/generate.doctree differ diff --git a/doc/build/doctrees/commands/launcher.doctree b/doc/build/doctrees/commands/launcher.doctree new file mode 100644 index 0000000..b0c39c2 Binary files /dev/null and b/doc/build/doctrees/commands/launcher.doctree differ diff --git a/doc/build/doctrees/commands/log.doctree b/doc/build/doctrees/commands/log.doctree new file mode 100644 index 0000000..9cc7f15 Binary files /dev/null and b/doc/build/doctrees/commands/log.doctree differ diff --git a/doc/build/doctrees/commands/package.doctree b/doc/build/doctrees/commands/package.doctree new file mode 100644 index 0000000..4ca44f4 Binary files /dev/null and b/doc/build/doctrees/commands/package.doctree differ diff --git a/doc/build/doctrees/commands/prepare.doctree b/doc/build/doctrees/commands/prepare.doctree new file mode 100644 index 0000000..abc1a31 Binary files /dev/null and b/doc/build/doctrees/commands/prepare.doctree differ diff --git a/doc/build/doctrees/configuration.doctree b/doc/build/doctrees/configuration.doctree new file mode 100644 index 0000000..c6d9f05 Binary files /dev/null and b/doc/build/doctrees/configuration.doctree differ diff --git a/doc/build/doctrees/environment.pickle b/doc/build/doctrees/environment.pickle new file mode 100644 index 0000000..8b1f6c4 Binary files /dev/null and b/doc/build/doctrees/environment.pickle differ diff --git a/doc/build/doctrees/index.doctree b/doc/build/doctrees/index.doctree new file mode 100644 index 0000000..42a530f Binary files /dev/null and b/doc/build/doctrees/index.doctree differ diff --git a/doc/build/doctrees/installation_of_sat.doctree b/doc/build/doctrees/installation_of_sat.doctree new file mode 100644 index 0000000..62e5233 Binary files /dev/null and b/doc/build/doctrees/installation_of_sat.doctree differ diff --git a/doc/build/doctrees/release_notes/release_notes_5.0.0.doctree b/doc/build/doctrees/release_notes/release_notes_5.0.0.doctree new file mode 100644 index 0000000..109e83a Binary files /dev/null and b/doc/build/doctrees/release_notes/release_notes_5.0.0.doctree differ diff --git a/doc/build/doctrees/usage_of_sat.doctree b/doc/build/doctrees/usage_of_sat.doctree new file mode 100644 index 0000000..155a84a Binary files /dev/null and b/doc/build/doctrees/usage_of_sat.doctree differ diff --git a/doc/build/doctrees/write_command.doctree b/doc/build/doctrees/write_command.doctree new file mode 100644 index 0000000..3e7d2af Binary files /dev/null and b/doc/build/doctrees/write_command.doctree differ diff --git a/doc/build/html/.buildinfo b/doc/build/html/.buildinfo new file mode 100644 index 0000000..1d98c1d --- /dev/null +++ b/doc/build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 2c4d344051e59f2c4840e68130e38438 +tags: fbb0d17656682115ca4d033fb2f83ba1 diff --git a/doc/build/html/_images/sat_about.png b/doc/build/html/_images/sat_about.png new file mode 100644 index 0000000..600d3d8 Binary files /dev/null and b/doc/build/html/_images/sat_about.png differ diff --git a/doc/build/html/_modules/index.html b/doc/build/html/_modules/index.html new file mode 100644 index 0000000..29da883 --- /dev/null +++ b/doc/build/html/_modules/index.html @@ -0,0 +1,114 @@ + + + + + + + + + Overview: module code — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/ElementTree.html b/doc/build/html/_modules/src/ElementTree.html new file mode 100644 index 0000000..a9af586 --- /dev/null +++ b/doc/build/html/_modules/src/ElementTree.html @@ -0,0 +1,1393 @@ + + + + + + + + + src.ElementTree — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.ElementTree

+#
+# ElementTree
+# $Id: ElementTree.py 2326 2005-03-17 07:45:21Z fredrik $
+#
+# light-weight XML support for Python 1.5.2 and later.
+#
+# history:
+# 2001-10-20 fl   created (from various sources)
+# 2001-11-01 fl   return root from parse method
+# 2002-02-16 fl   sort attributes in lexical order
+# 2002-04-06 fl   TreeBuilder refactoring, added PythonDoc markup
+# 2002-05-01 fl   finished TreeBuilder refactoring
+# 2002-07-14 fl   added basic namespace support to ElementTree.write
+# 2002-07-25 fl   added QName attribute support
+# 2002-10-20 fl   fixed encoding in write
+# 2002-11-24 fl   changed default encoding to ascii; fixed attribute encoding
+# 2002-11-27 fl   accept file objects or file names for parse/write
+# 2002-12-04 fl   moved XMLTreeBuilder back to this module
+# 2003-01-11 fl   fixed entity encoding glitch for us-ascii
+# 2003-02-13 fl   added XML literal factory
+# 2003-02-21 fl   added ProcessingInstruction/PI factory
+# 2003-05-11 fl   added tostring/fromstring helpers
+# 2003-05-26 fl   added ElementPath support
+# 2003-07-05 fl   added makeelement factory method
+# 2003-07-28 fl   added more well-known namespace prefixes
+# 2003-08-15 fl   fixed typo in ElementTree.findtext (Thomas Dartsch)
+# 2003-09-04 fl   fall back on emulator if ElementPath is not installed
+# 2003-10-31 fl   markup updates
+# 2003-11-15 fl   fixed nested namespace bug
+# 2004-03-28 fl   added XMLID helper
+# 2004-06-02 fl   added default support to findtext
+# 2004-06-08 fl   fixed encoding of non-ascii element/attribute names
+# 2004-08-23 fl   take advantage of post-2.1 expat features
+# 2005-02-01 fl   added iterparse implementation
+# 2005-03-02 fl   fixed iterparse support for pre-2.2 versions
+#
+# Copyright (c) 1999-2005 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2005 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+__all__ = [
+    # public symbols
+    "Comment",
+    "dump",
+    "Element", "ElementTree",
+    "fromstring",
+    "iselement", "iterparse",
+    "parse",
+    "PI", "ProcessingInstruction",
+    "QName",
+    "SubElement",
+    "tostring",
+    "TreeBuilder",
+    "VERSION", "XML",
+    "XMLTreeBuilder",
+    ]
+
+##
+# The <b>Element</b> type is a flexible container object, designed to
+# store hierarchical data structures in memory. The type can be
+# described as a cross between a list and a dictionary.
+# <p>
+# Each element has a number of properties associated with it:
+# <ul>
+# <li>a <i>tag</i>. This is a string identifying what kind of data
+# this element represents (the element type, in other words).</li>
+# <li>a number of <i>attributes</i>, stored in a Python dictionary.</li>
+# <li>a <i>text</i> string.</li>
+# <li>an optional <i>tail</i> string.</li>
+# <li>a number of <i>child elements</i>, stored in a Python sequence</li>
+# </ul>
+#
+# To create an element instance, use the {@link #Element} or {@link
+# #SubElement} factory functions.
+# <p>
+# The {@link #ElementTree} class can be used to wrap an element
+# structure, and convert it from and to XML.
+##
+
+import string, sys, re, platform
+
+class _SimpleElementPath:
+    # emulate pre-1.2 find/findtext/findall behaviour
+    def find(self, element, tag):
+        for elem in element:
+            if elem.tag == tag:
+                return elem
+        return None
+    def findtext(self, element, tag, default=None):
+        for elem in element:
+            if elem.tag == tag:
+                return elem.text or ""
+        return default
+    def findall(self, element, tag):
+        if tag[:3] == ".//":
+            return element.getiterator(tag[3:])
+        result = []
+        for elem in element:
+            if elem.tag == tag:
+                result.append(elem)
+        return result
+
+try:
+    import ElementPath
+except ImportError:
+    # FIXME: issue warning in this case?
+    ElementPath = _SimpleElementPath()
+
+# TODO: add support for custom namespace resolvers/default namespaces
+# TODO: add improved support for incremental parsing
+
+VERSION = "1.2.6"
+
+##
+# Internal element class.  This class defines the Element interface,
+# and provides a reference implementation of this interface.
+# <p>
+# You should not create instances of this class directly.  Use the
+# appropriate factory functions instead, such as {@link #Element}
+# and {@link #SubElement}.
+#
+# @see Element
+# @see SubElement
+# @see Comment
+# @see ProcessingInstruction
+
+class _ElementInterface:
+    # <tag attrib>text<child/>...</tag>tail
+
+    ##
+    # (Attribute) Element tag.
+
+    tag = None
+
+    ##
+    # (Attribute) Element attribute dictionary.  Where possible, use
+    # {@link #_ElementInterface.get},
+    # {@link #_ElementInterface.set},
+    # {@link #_ElementInterface.keys}, and
+    # {@link #_ElementInterface.items} to access
+    # element attributes.
+
+    attrib = None
+
+    ##
+    # (Attribute) Text before first subelement.  This is either a
+    # string or the value None, if there was no text.
+
+    text = None
+
+    ##
+    # (Attribute) Text after this element's end tag, but before the
+    # next sibling element's start tag.  This is either a string or
+    # the value None, if there was no text.
+
+    tail = None # text after end tag, if any
+
+    def __init__(self, tag, attrib):
+        self.tag = tag
+        self.attrib = attrib
+        self._children = []
+
+    def __repr__(self):
+        return "<Element %s at %x>" % (self.tag, id(self))
+
+    ##
+    # Creates a new element object of the same type as this element.
+    #
+    # @param tag Element tag.
+    # @param attrib Element attributes, given as a dictionary.
+    # @return A new element instance.
+
+    def makeelement(self, tag, attrib):
+        return Element(tag, attrib)
+
+    ##
+    # Returns the number of subelements.
+    #
+    # @return The number of subelements.
+
+    def __len__(self):
+        return len(self._children)
+
+    ##
+    # Returns the given subelement.
+    #
+    # @param index What subelement to return.
+    # @return The given subelement.
+    # @exception IndexError If the given element does not exist.
+
+    def __getitem__(self, index):
+        return self._children[index]
+
+    ##
+    # Replaces the given subelement.
+    #
+    # @param index What subelement to replace.
+    # @param element The new element value.
+    # @exception IndexError If the given element does not exist.
+    # @exception AssertionError If element is not a valid object.
+
+    def __setitem__(self, index, element):
+        assert iselement(element)
+        self._children[index] = element
+
+    ##
+    # Deletes the given subelement.
+    #
+    # @param index What subelement to delete.
+    # @exception IndexError If the given element does not exist.
+
+    def __delitem__(self, index):
+        del self._children[index]
+
+    ##
+    # Returns a list containing subelements in the given range.
+    #
+    # @param start The first subelement to return.
+    # @param stop The first subelement that shouldn't be returned.
+    # @return A sequence object containing subelements.
+
+    def __getslice__(self, start, stop):
+        return self._children[start:stop]
+
+    ##
+    # Replaces a number of subelements with elements from a sequence.
+    #
+    # @param start The first subelement to replace.
+    # @param stop The first subelement that shouldn't be replaced.
+    # @param elements A sequence object with zero or more elements.
+    # @exception AssertionError If a sequence member is not a valid object.
+
+    def __setslice__(self, start, stop, elements):
+        for element in elements:
+            assert iselement(element)
+        self._children[start:stop] = list(elements)
+
+    ##
+    # Deletes a number of subelements.
+    #
+    # @param start The first subelement to delete.
+    # @param stop The first subelement to leave in there.
+
+    def __delslice__(self, start, stop):
+        del self._children[start:stop]
+
+    ##
+    # Adds a subelement to the end of this element.
+    #
+    # @param element The element to add.
+    # @exception AssertionError If a sequence member is not a valid object.
+
+    def append(self, element):
+        assert iselement(element)
+        self._children.append(element)
+
+    ##
+    # Inserts a subelement at the given position in this element.
+    #
+    # @param index Where to insert the new subelement.
+    # @exception AssertionError If the element is not a valid object.
+
+    def insert(self, index, element):
+        assert iselement(element)
+        self._children.insert(index, element)
+
+    ##
+    # Removes a matching subelement.  Unlike the <b>find</b> methods,
+    # this method compares elements based on identity, not on tag
+    # value or contents.
+    #
+    # @param element What element to remove.
+    # @exception ValueError If a matching element could not be found.
+    # @exception AssertionError If the element is not a valid object.
+
+    def remove(self, element):
+        assert iselement(element)
+        self._children.remove(element)
+
+    ##
+    # Returns all subelements.  The elements are returned in document
+    # order.
+    #
+    # @return A list of subelements.
+    # @defreturn list of Element instances
+
+    def getchildren(self):
+        return self._children
+
+    ##
+    # Finds the first matching subelement, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @return The first matching element, or None if no element was found.
+    # @defreturn Element or None
+
+    def find(self, path):
+        if ElementPath.find(self, path) == None:
+            return ElementPath.find(self, path.encode())
+        return ElementPath.find(self, path)
+
+    ##
+    # Finds text for the first matching subelement, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @param default What to return if the element was not found.
+    # @return The text content of the first matching element, or the
+    #     default value no element was found.  Note that if the element
+    #     has is found, but has no text content, this method returns an
+    #     empty string.
+    # @defreturn string
+
+    def findtext(self, path, default=None):
+        return ElementPath.findtext(self, path, default)
+
+    ##
+    # Finds all matching subelements, by tag name or path.
+    #
+    # @param path What element to look for.
+    # @return A list or iterator containing all matching elements,
+    #    in document order.
+    # @defreturn list of Element instances
+
+    def findall(self, path):
+        return ElementPath.findall(self, path)
+
+    ##
+    # Resets an element.  This function removes all subelements, clears
+    # all attributes, and sets the text and tail attributes to None.
+
+    def clear(self):
+        self.attrib.clear()
+        self._children = []
+        self.text = self.tail = None
+
+    ##
+    # Gets an element attribute.
+    #
+    # @param key What attribute to look for.
+    # @param default What to return if the attribute was not found.
+    # @return The attribute value, or the default value, if the
+    #     attribute was not found.
+    # @defreturn string or None
+
+    def get(self, key, default=None):
+        res = self.attrib.get(key, default)
+        if not res:
+            res = self.attrib.get(key.encode(), default)
+        if isinstance(res, bytes):
+            return res.decode()
+        else:
+            return res
+
+    ##
+    # Sets an element attribute.
+    #
+    # @param key What attribute to set.
+    # @param value The attribute value.
+
+    def set(self, key, value):
+        self.attrib[key] = value
+
+    ##
+    # Gets a list of attribute names.  The names are returned in an
+    # arbitrary order (just like for an ordinary Python dictionary).
+    #
+    # @return A list of element attribute names.
+    # @defreturn list of strings
+
+    def keys(self):
+        res = []
+        for key in self.attrib.keys():
+            if isinstance(key, bytes):
+                res.append(key.decode())
+            else:
+                res.append(key)
+        return res
+                
+    ##
+    # Gets element attributes, as a sequence.  The attributes are
+    # returned in an arbitrary order.
+    #
+    # @return A list of (name, value) tuples for all attributes.
+    # @defreturn list of (string, string) tuples
+
+    def items(self):
+        return self.attrib.items()
+
+    ##
+    # Creates a tree iterator.  The iterator loops over this element
+    # and all subelements, in document order, and returns all elements
+    # with a matching tag.
+    # <p>
+    # If the tree structure is modified during iteration, the result
+    # is undefined.
+    #
+    # @param tag What tags to look for (default is to return all elements).
+    # @return A list or iterator containing all the matching elements.
+    # @defreturn list or iterator
+
+    def getiterator(self, tag=None):
+        nodes = []
+        if tag == "*":
+            tag = None
+        if tag is None or self.tag == tag:
+            nodes.append(self)
+        for node in self._children:
+            nodes.extend(node.getiterator(tag))
+        return nodes
+
+# compatibility
+_Element = _ElementInterface
+
+##
+# Element factory.  This function returns an object implementing the
+# standard Element interface.  The exact class or type of that object
+# is implementation dependent, but it will always be compatible with
+# the {@link #_ElementInterface} class in this module.
+# <p>
+# The element name, attribute names, and attribute values can be
+# either 8-bit ASCII strings or Unicode strings.
+#
+# @param tag The element name.
+# @param attrib An optional dictionary, containing element attributes.
+# @param **extra Additional attributes, given as keyword arguments.
+# @return An element instance.
+# @defreturn Element
+
+
[docs]def Element(tag, attrib={}, **extra): + attrib = attrib.copy() + attrib.update(extra) + return _ElementInterface(tag, attrib) + +## +# Subelement factory. This function creates an element instance, and +# appends it to an existing element. +# <p> +# The element name, attribute names, and attribute values can be +# either 8-bit ASCII strings or Unicode strings. +# +# @param parent The parent element. +# @param tag The subelement name. +# @param attrib An optional dictionary, containing element attributes. +# @param **extra Additional attributes, given as keyword arguments. +# @return An element instance. +# @defreturn Element +
+
[docs]def SubElement(parent, tag, attrib={}, **extra): + attrib = attrib.copy() + attrib.update(extra) + element = parent.makeelement(tag, attrib) + parent.append(element) + return element + +## +# Comment element factory. This factory function creates a special +# element that will be serialized as an XML comment. +# <p> +# The comment string can be either an 8-bit ASCII string or a Unicode +# string. +# +# @param text A string containing the comment string. +# @return An element instance, representing a comment. +# @defreturn Element +
+
[docs]def Comment(text=None): + element = Element(Comment) + element.text = text + return element + +## +# PI element factory. This factory function creates a special element +# that will be serialized as an XML processing instruction. +# +# @param target A string containing the PI target. +# @param text A string containing the PI contents, if any. +# @return An element instance, representing a PI. +# @defreturn Element +
+
[docs]def ProcessingInstruction(target, text=None): + element = Element(ProcessingInstruction) + element.text = target + if text: + element.text = element.text + " " + text + return element +
+PI = ProcessingInstruction + +## +# QName wrapper. This can be used to wrap a QName attribute value, in +# order to get proper namespace handling on output. +# +# @param text A string containing the QName value, in the form {uri}local, +# or, if the tag argument is given, the URI part of a QName. +# @param tag Optional tag. If given, the first argument is interpreted as +# an URI, and this argument is interpreted as a local name. +# @return An opaque object, representing the QName. + +
[docs]class QName: + def __init__(self, text_or_uri, tag=None): + if tag: + text_or_uri = "{%s}%s" % (text_or_uri, tag) + self.text = text_or_uri + def __str__(self): + return self.text + def __hash__(self): + return hash(self.text) + def __cmp__(self, other): + if isinstance(other, QName): + return cmp(self.text, other.text) + return cmp(self.text, other) + +## +# ElementTree wrapper class. This class represents an entire element +# hierarchy, and adds some extra support for serialization to and from +# standard XML. +# +# @param element Optional root element. +# @keyparam file Optional file handle or name. If given, the +# tree is initialized with the contents of this XML file. +
+
[docs]class ElementTree: + + def __init__(self, element=None, file=None): + assert element is None or iselement(element) + self._root = element # first node + if file: + self.parse(file) + + ## + # Gets the root element for this tree. + # + # @return An element instance. + # @defreturn Element + +
[docs] def getroot(self): + return self._root + + ## + # Replaces the root element for this tree. This discards the + # current contents of the tree, and replaces it with the given + # element. Use with care. + # + # @param element An element instance. +
+ def _setroot(self, element): + assert iselement(element) + self._root = element + + ## + # Loads an external XML document into this element tree. + # + # @param source A file name or file object. + # @param parser An optional parser instance. If not given, the + # standard {@link XMLTreeBuilder} parser is used. + # @return The document root element. + # @defreturn Element + +
[docs] def parse(self, source, parser=None): + if not hasattr(source, "read"): + # OP 14/11/2017 Ajout de traces pour essayer de decouvrir le pb + # de remontee de log des tests + #print "TRACES OP - ElementTree.py/ElementTree.parse() source = '#%s#'" %source + source = open(source, "rb") + if not parser: + parser = XMLTreeBuilder() + while 1: + data = source.read(32768) + if not data: + break + parser.feed(data) + self._root = parser.close() + return self._root + + ## + # Creates a tree iterator for the root element. The iterator loops + # over all elements in this tree, in document order. + # + # @param tag What tags to look for (default is to return all elements) + # @return An iterator. + # @defreturn iterator +
+
[docs] def getiterator(self, tag=None): + assert self._root is not None + return self._root.getiterator(tag) + + ## + # Finds the first toplevel element with given tag. + # Same as getroot().find(path). + # + # @param path What element to look for. + # @return The first matching element, or None if no element was found. + # @defreturn Element or None +
+
[docs] def find(self, path): + assert self._root is not None + if path[:1] == "/": + path = "." + path + return self._root.find(path) + + ## + # Finds the element text for the first toplevel element with given + # tag. Same as getroot().findtext(path). + # + # @param path What toplevel element to look for. + # @param default What to return if the element was not found. + # @return The text content of the first matching element, or the + # default value no element was found. Note that if the element + # has is found, but has no text content, this method returns an + # empty string. + # @defreturn string +
+
[docs] def findtext(self, path, default=None): + assert self._root is not None + if path[:1] == "/": + path = "." + path + return self._root.findtext(path, default) + + ## + # Finds all toplevel elements with the given tag. + # Same as getroot().findall(path). + # + # @param path What element to look for. + # @return A list or iterator containing all matching elements, + # in document order. + # @defreturn list of Element instances +
+
[docs] def findall(self, path): + assert self._root is not None + if path[:1] == "/": + path = "." + path + return self._root.findall(path) + + ## + # Writes the element tree to a file, as XML. + # + # @param file A file name, or a file object opened for writing. + # @param encoding Optional output encoding (default is US-ASCII). +
+
[docs] def write(self, file, encoding="us-ascii"): + assert self._root is not None + if not hasattr(file, "write"): + file = open(file, "wb") + if not encoding: + encoding = "us-ascii" + elif encoding != "utf-8" and encoding != "us-ascii": + file.write("<?xml version='1.0' encoding='%s'?>\n" % encoding) + self._write(file, self._root, encoding, {}) +
+ def _write(self, file, node, encoding, namespaces, margin=0): + # write XML to file + tag = node.tag + if tag is Comment: + file.write("<!-- %s -->\n" % _escape_cdata(node.text, encoding)) + elif tag is ProcessingInstruction: + file.write("<?%s?>\n" % _escape_cdata(node.text, encoding)) + else: + items = node.items() + xmlns_items = [] # new namespaces in this scope + try: + if isinstance(tag, QName) or tag[:1] == "{": + tag, xmlns = fixtag(tag, namespaces) + if xmlns: xmlns_items.append(xmlns) + except TypeError: + _raise_serialization_error(tag) + file.write(' ' * margin) + file.write(_encode("<", encoding) + _encode(tag, encoding)) + if items or xmlns_items: + items = sorted(items) # lexical order + for k, v in items: + try: + if isinstance(k, QName) or k[:1] == "{": + k, xmlns = fixtag(k, namespaces) + if xmlns: xmlns_items.append(xmlns) + except TypeError: + _raise_serialization_error(k) + try: + if isinstance(v, QName): + v, xmlns = fixtag(v, namespaces) + if xmlns: xmlns_items.append(xmlns) + except TypeError: + _raise_serialization_error(v) + file.write(" %s=\"%s\"" % (k,v)) + for k, v in xmlns_items: + file.write(" %s=\"%s\"" % (k,v)) + if node.text or len(node): + file.write(">") + if node.text: + file.write(_escape_cdata(node.text, encoding)) + if len(node) > 0: file.write("\n") + for n in node: + self._write(file, n, encoding, namespaces, margin + 2) + if len(node) > 0: file.write(' ' * margin) + file.write(_encode("</", encoding) + _encode(tag, encoding) + _encode(">\n", encoding)) + else: + file.write("/>\n") + for k, v in xmlns_items: + del namespaces[v] + if node.tail: + file.write(_escape_cdata(node.tail, encoding)) + +# -------------------------------------------------------------------- +# helpers + +## +# Checks if an object appears to be a valid element object. +# +# @param An element instance. +# @return A true value if this is an element object. +# @defreturn flag +
+
[docs]def iselement(element): + # FIXME: not sure about this; might be a better idea to look + # for tag/attrib/text attributes + return isinstance(element, _ElementInterface) or hasattr(element, "tag") + +## +# Writes an element tree or element structure to sys.stdout. This +# function should be used for debugging only. +# <p> +# The exact output format is implementation dependent. In this +# version, it's written as an ordinary XML file. +# +# @param elem An element tree or an individual element. +
+
[docs]def dump(elem): + # debugging + if not isinstance(elem, ElementTree): + elem = ElementTree(elem) + elem.write(sys.stdout) + tail = elem.getroot().tail + if not tail or tail[-1] != "\n": + sys.stdout.write("\n") +
+def _encode(s, encoding): + try: + return s.encode(encoding) + except AttributeError: + return s # 1.5.2: assume the string uses the right encoding + +if sys.version[:3] == "1.5": + _escape = re.compile(r"[&<>\"\x80-\xff]+") # 1.5.2 +else: + _escape = re.compile(eval(r'u"[&<>\"\u0080-\uffff]+"')) + +_escape_map = { + "&": "&amp;", + "<": "&lt;", + ">": "&gt;", + '"': "&quot;", +} + +_namespace_map = { + # "well-known" namespace prefixes + "http://www.w3.org/XML/1998/namespace": "xml", + "http://www.w3.org/1999/xhtml": "html", + "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf", + "http://schemas.xmlsoap.org/wsdl/": "wsdl", +} + +def _raise_serialization_error(text): + raise TypeError( + "cannot serialize %r (type %s)" % (text, type(text).__name__) + ) + +def _encode_entity(text, pattern=_escape): + # map reserved and non-ascii characters to numerical entities + def escape_entities(m, map=_escape_map): + out = [] + append = out.append + for char in m.group(): + text = map.get(char) + if text is None: + text = "&#%d;" % ord(char) + append(text) + return string.join(out, "") + try: + return _encode(pattern.sub(escape_entities, text), "ascii") + except TypeError: + _raise_serialization_error(text) + +# +# the following functions assume an ascii-compatible encoding +# (or "utf-16") + +def _escape_cdata(text, encoding=None, replace=str.replace): + # escape character data + try: + if platform.python_version()[0] == '2': # python 2.x.y + if encoding: + try: + text = _encode(text, encoding) + except UnicodeError: + return _encode_entity(text) + + text = replace(text, "&", "&amp;") + text = replace(text, "<", "&lt;") + text = replace(text, ">", "&gt;") + text = replace(text, "####newLine####", "<br \>") + if encoding: + try: + text = _encode(text, encoding) + except UnicodeError: + return _encode_entity(text) + return text + except (TypeError, AttributeError): + _raise_serialization_error(text) + +def _escape_attrib(text, encoding=None, replace=str.replace): + # escape attribute value + try: + text = replace(text, "&", "&amp;") + text = replace(text, "'", "&apos;") # FIXME: overkill + text = replace(text, "\"", "&quot;") + text = replace(text, "<", "&lt;") + text = replace(text, ">", "&gt;") + if encoding: + try: + text = _encode(text, encoding) + except UnicodeError: + return _encode_entity(text) + return text + except (TypeError, AttributeError): + _raise_serialization_error(text) + +def fixtag(tag, namespaces): + # given a decorated tag (of the form {uri}tag), return prefixed + # tag and namespace declaration, if any + if isinstance(tag, QName): + tag = tag.text + namespace_uri, tag = string.split(tag[1:], "}", 1) + prefix = namespaces.get(namespace_uri) + if prefix is None: + prefix = _namespace_map.get(namespace_uri) + if prefix is None: + prefix = "ns%d" % len(namespaces) + namespaces[namespace_uri] = prefix + if prefix == "xml": + xmlns = None + else: + xmlns = ("xmlns:%s" % prefix, namespace_uri) + else: + xmlns = None + return "%s:%s" % (prefix, tag), xmlns + +## +# Parses an XML document into an element tree. +# +# @param source A filename or file object containing XML data. +# @param parser An optional parser instance. If not given, the +# standard {@link XMLTreeBuilder} parser is used. +# @return An ElementTree instance + +
[docs]def parse(source, parser=None): + # OP 14/11/2017 Ajout de traces pour essayer de decouvrir le pb + # de remontee de log des tests + #print "TRACES OP - ElementTree.py/parse() source = '#%s#'" %source + tree = ElementTree() + tree.parse(source, parser) + return tree + +## +# Parses an XML document into an element tree incrementally, and reports +# what's going on to the user. +# +# @param source A filename or file object containing XML data. +# @param events A list of events to report back. If omitted, only "end" +# events are reported. +# @return A (event, elem) iterator. +
+
[docs]class iterparse: + + def __init__(self, source, events=None): + if not hasattr(source, "read"): + # OP TEST + print "iterparse.__init__ source = %s" %source + source = open(source, "rb") + self._file = source + self._events = [] + self._index = 0 + self.root = self._root = None + self._parser = XMLTreeBuilder() + # wire up the parser for event reporting + parser = self._parser._parser + append = self._events.append + if events is None: + events = ["end"] + for event in events: + if event == "start": + try: + parser.ordered_attributes = 1 + parser.specified_attributes = 1 + def handler(tag, attrib_in, event=event, append=append, + start=self._parser._start_list): + append((event, start(tag, attrib_in))) + parser.StartElementHandler = handler + except AttributeError: + def handler(tag, attrib_in, event=event, append=append, + start=self._parser._start): + append((event, start(tag, attrib_in))) + parser.StartElementHandler = handler + elif event == "end": + def handler(tag, event=event, append=append, + end=self._parser._end): + append((event, end(tag))) + parser.EndElementHandler = handler + elif event == "start-ns": + def handler(prefix, uri, event=event, append=append): + try: + uri = _encode(uri, "ascii") + except UnicodeError: + pass + append((event, (prefix or "", uri))) + parser.StartNamespaceDeclHandler = handler + elif event == "end-ns": + def handler(prefix, event=event, append=append): + append((event, None)) + parser.EndNamespaceDeclHandler = handler + +
[docs] def next(self): + while 1: + try: + item = self._events[self._index] + except IndexError: + if self._parser is None: + self.root = self._root + try: + raise StopIteration + except NameError: + raise IndexError + # load event buffer + del self._events[:] + self._index = 0 + data = self._file.read(16384) + if data: + self._parser.feed(data) + else: + self._root = self._parser.close() + self._parser = None + else: + self._index = self._index + 1 + return item +
+ try: + iter + def __iter__(self): + return self + except NameError: + def __getitem__(self, index): + return self.next() + +## +# Parses an XML document from a string constant. This function can +# be used to embed "XML literals" in Python code. +# +# @param source A string containing XML data. +# @return An Element instance. +# @defreturn Element +
+
[docs]def XML(text): + parser = XMLTreeBuilder() + parser.feed(text) + return parser.close() + +## +# Parses an XML document from a string constant, and also returns +# a dictionary which maps from element id:s to elements. +# +# @param source A string containing XML data. +# @return A tuple containing an Element instance and a dictionary. +# @defreturn (Element, dictionary) +
+def XMLID(text): + parser = XMLTreeBuilder() + parser.feed(text) + tree = parser.close() + ids = {} + for elem in tree.getiterator(): + id = elem.get("id") + if id: + ids[id] = elem + return tree, ids + +## +# Parses an XML document from a string constant. Same as {@link #XML}. +# +# @def fromstring(text) +# @param source A string containing XML data. +# @return An Element instance. +# @defreturn Element + +fromstring = XML + +## +# Generates a string representation of an XML element, including all +# subelements. +# +# @param element An Element instance. +# @return An encoded string containing the XML data. +# @defreturn string + +
[docs]def tostring(element, encoding=None): + class dummy: + pass + data = [] + file = dummy() + file.write = data.append + ElementTree(element).write(file, encoding) + data2 = [] + for item in data: + if isinstance(item, bytes): + item = item.decode() + data2.append(item) + return "".join(data2) + +## +# Generic element structure builder. This builder converts a sequence +# of {@link #TreeBuilder.start}, {@link #TreeBuilder.data}, and {@link +# #TreeBuilder.end} method calls to a well-formed element structure. +# <p> +# You can use this class to build an element structure using a custom XML +# parser, or a parser for some other XML-like format. +# +# @param element_factory Optional element factory. This factory +# is called to create new Element instances, as necessary. +
+
[docs]class TreeBuilder: + + def __init__(self, element_factory=None): + self._data = [] # data collector + self._elem = [] # element stack + self._last = None # last element + self._tail = None # true if we're after an end tag + if element_factory is None: + element_factory = _ElementInterface + self._factory = element_factory + + ## + # Flushes the parser buffers, and returns the toplevel documen + # element. + # + # @return An Element instance. + # @defreturn Element + +
[docs] def close(self): + assert len(self._elem) == 0, "missing end tags" + assert self._last != None, "missing toplevel element" + return self._last +
+ def _flush(self): + if self._data: + if self._last is not None: + text = "" + for item in self._data: + try: + text += item + except: + text += item.decode() + if self._tail: + assert self._last.tail is None, "internal error (tail)" + self._last.tail = text + else: + assert self._last.text is None, "internal error (text)" + self._last.text = text + self._data = [] + + ## + # Adds text to the current element. + # + # @param data A string. This should be either an 8-bit string + # containing ASCII text, or a Unicode string. + +
[docs] def data(self, data): + self._data.append(data) + + ## + # Opens a new element. + # + # @param tag The element name. + # @param attrib A dictionary containing element attributes. + # @return The opened element. + # @defreturn Element +
+
[docs] def start(self, tag, attrs): + self._flush() + self._last = elem = self._factory(tag, attrs) + if self._elem: + self._elem[-1].append(elem) + self._elem.append(elem) + self._tail = 0 + return elem + + ## + # Closes the current element. + # + # @param tag The element name. + # @return The closed element. + # @defreturn Element +
+
[docs] def end(self, tag): + self._flush() + self._last = self._elem.pop() + assert self._last.tag == tag,\ + "end tag mismatch (expected %s, got %s)" % ( + self._last.tag, tag) + self._tail = 1 + return self._last + +## +# Element structure builder for XML source data, based on the +# <b>expat</b> parser. +# +# @keyparam target Target object. If omitted, the builder uses an +# instance of the standard {@link #TreeBuilder} class. +# @keyparam html Predefine HTML entities. This flag is not supported +# by the current implementation. +# @see #ElementTree +# @see #TreeBuilder +
+
[docs]class XMLTreeBuilder: + + def __init__(self, html=0, target=None): + try: + from xml.parsers import expat + except ImportError: + raise ImportError( + "No module named expat; use SimpleXMLTreeBuilder instead" + ) + self._parser = parser = expat.ParserCreate(None, "}") + if target is None: + target = TreeBuilder() + self._target = target + self._names = {} # name memo cache + # callbacks + parser.DefaultHandlerExpand = self._default + parser.StartElementHandler = self._start + parser.EndElementHandler = self._end + parser.CharacterDataHandler = self._data + # let expat do the buffering, if supported + try: + self._parser.buffer_text = 1 + except AttributeError: + pass + # use new-style attribute handling, if supported + try: + self._parser.ordered_attributes = 1 + self._parser.specified_attributes = 1 + parser.StartElementHandler = self._start_list + except AttributeError: + pass + #encoding = None + #if not parser.returns_unicode: + # encoding = "utf-8" + # target.xml(encoding, None) + self._doctype = None + self.entity = {} + + def _fixtext(self, text): + # convert text string to ascii, if possible + try: + return _encode(text, "ascii") + except UnicodeError: + return text + + def _fixname(self, key): + # expand qname, and convert name string to ascii, if possible + try: + name = self._names[key] + except KeyError: + name = key + if "}" in name: + name = "{" + name + self._names[key] = name = self._fixtext(name) + return name + + def _start(self, tag, attrib_in): + fixname = self._fixname + tag = fixname(tag) + attrib = {} + for key, value in attrib_in.items(): + attrib[fixname(key)] = self._fixtext(value) + return self._target.start(tag, attrib) + + def _start_list(self, tag, attrib_in): + fixname = self._fixname + tag = fixname(tag) + attrib = {} + if attrib_in: + for i in range(0, len(attrib_in), 2): + attrib[fixname(attrib_in[i])] = self._fixtext(attrib_in[i+1]) + return self._target.start(tag, attrib) + + def _data(self, text): + return self._target.data(self._fixtext(text)) + + def _end(self, tag): + return self._target.end(self._fixname(tag)) + + def _default(self, text): + prefix = text[:1] + if prefix == "&": + # deal with undefined entities + try: + self._target.data(self.entity[text[1:-1]]) + except KeyError: + from xml.parsers import expat + raise expat.error( + "undefined entity %s: line %d, column %d" % + (text, self._parser.ErrorLineNumber, + self._parser.ErrorColumnNumber) + ) + elif prefix == "<" and text[:9] == "<!DOCTYPE": + self._doctype = [] # inside a doctype declaration + elif self._doctype is not None: + # parse doctype contents + if prefix == ">": + self._doctype = None + return + text = string.strip(text) + if not text: + return + self._doctype.append(text) + n = len(self._doctype) + if n > 2: + type = self._doctype[1] + if type == "PUBLIC" and n == 4: + name, type, pubid, system = self._doctype + elif type == "SYSTEM" and n == 3: + name, type, system = self._doctype + pubid = None + else: + return + if pubid: + pubid = pubid[1:-1] + self.doctype(name, pubid, system[1:-1]) + self._doctype = None + + ## + # Handles a doctype declaration. + # + # @param name Doctype name. + # @param pubid Public identifier. + # @param system System identifier. + +
[docs] def doctype(self, name, pubid, system): + pass + + ## + # Feeds data to the parser. + # + # @param data Encoded data. +
+
[docs] def feed(self, data): + # OP 14/11/2017 Ajout de traces pour essayer de decouvrir le pb + # de remontee de log des tests + #print "TRACES OP - ElementTree.py/XMLTreeBuilder.feed() data = '#%s#'" %data + self._parser.Parse(data, 0) + + ## + # Finishes feeding data to the parser. + # + # @return An element structure. + # @defreturn Element +
+
[docs] def close(self): + self._parser.Parse("", 1) # end of data + tree = self._target.close() + del self._target, self._parser # get rid of circular references + return tree
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/__init__.html b/doc/build/html/_modules/src/__init__.html new file mode 100644 index 0000000..0415399 --- /dev/null +++ b/doc/build/html/_modules/src/__init__.html @@ -0,0 +1,544 @@ + + + + + + + + + src.__init__ — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.__init__

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+
+"""\
+initial imports and utilities methods for salomeTools
+"""
+
+import os
+import shutil
+import errno
+import stat
+
+from . import pyconf
+from . import architecture
+from . import printcolors
+from . import options
+from . import system
+from . import ElementTree
+from . import logger
+from . import product
+from . import environment
+from . import fileEnviron
+from . import compilation
+from . import test_module
+from . import template
+
+import platform
+if platform.system() == "Windows" :
+    import colorama
+    colorama.init()
+
+OK_STATUS = "OK"
+KO_STATUS = "KO"
+NA_STATUS = "NA"
+KNOWNFAILURE_STATUS = "KF"
+TIMEOUT_STATUS = "TIMEOUT"
+
+CONFIG_FILENAME = "sat-config.pyconf"
+
+
[docs]class SatException(Exception): + """rename Exception Class""" + pass +
+
[docs]def ensure_path_exists(p): + """Create a path if not existing + + :param p str: The path. + """ + if not os.path.exists(p): + os.makedirs(p) +
+
[docs]def check_config_has_application( config, details = None ): + """check that the config has the key APPLICATION. Else raise an exception. + + :param config class 'common.pyconf.Config': The config. + """ + if 'APPLICATION' not in config: + message = _("An APPLICATION is required. Use 'config --list' to get" + " the list of available applications.\n") + if details : + details.append(message) + raise SatException( message ) +
+
[docs]def check_config_has_profile( config, details = None ): + """\ + check that the config has the key APPLICATION.profile. + else, raise an exception. + + :param config class 'common.pyconf.Config': The config. + """ + check_config_has_application(config) + if 'profile' not in config.APPLICATION: + message = _("A profile section is required in your application.\n") + if details : + details.append(message) + raise SatException( message ) +
+
[docs]def config_has_application( config ): + return 'APPLICATION' in config +
+
[docs]def get_cfg_param(config, param_name, default): + """\ + eearch for param_name value in config. + if param_name is not in config + then return default, + else return the found value + + :param config class 'common.pyconf.Config': The config. + :param param_name str: the name of the parameter to get the value + :param default str: The value to return if param_name is not in config + :return: see initial description of the function + :rtype: str + """ + if param_name in config: + return config[param_name] + return default +
+ +
[docs]def get_base_path(config): + """\ + Returns the path of the products base. + + :param config Config: The global Config instance. + :return: The path of the products base. + :rtype: str + """ + if "base" not in config.LOCAL: + local_file_path = os.path.join(config.VARS.salometoolsway, + "data", + "local.pyconf") + msg = _("Please define a base path in the file %s" % local_file_path) + raise SatException(msg) + + base_path = os.path.abspath(config.LOCAL.base) + + return base_path +
+
[docs]def get_launcher_name(config): + """\ + Returns the name of salome launcher. + + :param config Config: The global Config instance. + :return: The name of salome launcher. + :rtype: str + """ + check_config_has_application(config) + if 'profile' in config.APPLICATION and 'launcher_name' in config.APPLICATION.profile: + launcher_name = config.APPLICATION.profile.launcher_name + else: + launcher_name = 'salome' + + return launcher_name +
+
[docs]def get_log_path(config): + """\ + Returns the path of the logs. + + :param config Config: The global Config instance. + :return: The path of the logs. + :rtype: str + """ + if "log_dir" not in config.LOCAL: + local_file_path = os.path.join(config.VARS.salometoolsway, + "data", + "local.pyconf") + msg = _("Please define a log_dir in the file %s" % local_file_path) + raise SatException(msg) + + log_dir_path = os.path.abspath(config.LOCAL.log_dir) + + return log_dir_path +
+
[docs]def get_salome_version(config): + if hasattr(config.APPLICATION, 'version_salome'): + Version = config.APPLICATION.version_salome + else: + KERNEL_info = product.get_product_config(config, "KERNEL") + VERSION = os.path.join( + KERNEL_info.install_dir, + "bin", + "salome", + "VERSION") + if not os.path.isfile(VERSION): + return None + + fVERSION = open(VERSION) + Version = fVERSION.readline() + fVERSION.close() + + VersionSalome = int(only_numbers(Version)) + return VersionSalome +
+
[docs]def only_numbers(str_num): + return ''.join([nb for nb in str_num if nb in '0123456789'] or '0') +
+
[docs]def read_config_from_a_file(filePath): + try: + cfg_file = pyconf.Config(filePath) + except pyconf.ConfigError as e: + raise SatException(_("Error in configuration file: %(file)s\n %(error)s") % \ + { 'file': filePath, 'error': str(e) }) + return cfg_file +
+
[docs]def get_tmp_filename(cfg, name): + if not os.path.exists(cfg.VARS.tmp_root): + os.makedirs(cfg.VARS.tmp_root) + + return os.path.join(cfg.VARS.tmp_root, name) + +## +# Utils class to simplify path manipulations.
+
[docs]class Path: + def __init__(self, path): + self.path = str(path) + + def __add__(self, other): + return Path(os.path.join(self.path, str(other))) + + def __abs__(self): + return Path(os.path.abspath(self.path)) + + def __str__(self): + return self.path + + def __eq__(self, other): + return self.path == other.path + +
[docs] def exists(self): + return self.islink() or os.path.exists(self.path) +
+ +
[docs] def isdir(self): + return os.path.isdir(self.path) +
+
[docs] def isfile(self): + return os.path.isfile(self.path) +
+
[docs] def list(self): + return [Path(p) for p in os.listdir(self.path)] +
+
[docs] def dir(self): + return Path(os.path.dirname(self.path)) +
+
[docs] def base(self): + return Path(os.path.basename(self.path)) +
+
[docs] def make(self, mode=None): + os.makedirs(self.path) + if mode: + os.chmod(self.path, mode) +
+
[docs] def chmod(self, mode): + os.chmod(self.path, mode) +
+
[docs] def rm(self): + if self.islink(): + os.remove(self.path) + else: + shutil.rmtree( self.path, onerror = handleRemoveReadonly ) +
+
[docs] def copy(self, path, smart=False): + if not isinstance(path, Path): + path = Path(path) + + if os.path.islink(self.path): + return self.copylink(path) + elif os.path.isdir(self.path): + return self.copydir(path, smart) + else: + return self.copyfile(path) +
+
[docs] def smartcopy(self, path): + return self.copy(path, True) +
+ + + +
[docs] def copydir(self, dst, smart=False): + try: + names = self.list() + + if not dst.exists(): + dst.make() + + for name in names: + if name == dst: + continue + if smart and (str(name) in [".git", "CVS", ".svn"]): + continue + srcname = self + name + dstname = dst + name + srcname.copy(dstname, smart) + return True + except: + return False +
+
[docs] def copyfile(self, path): + try: + shutil.copy2(self.path, str(path)) + return True + except: + return False +
+
[docs]def find_file_in_lpath(file_name, lpath, additional_dir = ""): + """\ + Find in all the directories in lpath list the file that has the same name + as file_name. + If it is found + then return the full path of the file + else return False. + + The additional_dir (optional) is the name of the directory to add to all + paths in lpath. + + :param file_name str: The file name to search + :param lpath List: The list of directories where to search + :param additional_dir str: The name of the additional directory + :return: the full path of the file or False if not found + :rtype: str + """ + for directory in lpath: + dir_complete = os.path.join(directory, additional_dir) + if not os.path.isdir(directory) or not os.path.isdir(dir_complete): + continue + l_files = os.listdir(dir_complete) + for file_n in l_files: + if file_n == file_name: + return os.path.join(dir_complete, file_name) + return False +
+
[docs]def handleRemoveReadonly(func, path, exc): + excvalue = exc[1] + if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES: + os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777 + func(path) + else: + raise +
+
[docs]def deepcopy_list(input_list): + """\ + Do a deep copy of a list + + :param input_list List: The list to copy + :return: The copy of the list + :rtype: List + """ + res = [] + for elem in input_list: + res.append(elem) + return res +
+
[docs]def remove_item_from_list(input_list, item): + """\ + Remove all occurences of item from input_list + + :param input_list List: The list to modify + :return: The without any item + :rtype: List + """ + res = [] + for elem in input_list: + if elem == item: + continue + res.append(elem) + return res +
+
[docs]def parse_date(date): + """\ + Transform YYYYMMDD_hhmmss into YYYY-MM-DD hh:mm:ss. + + :param date str: The date to transform + :return: The date in the new format + :rtype: str + """ + if len(date) != 15: + return date + res = "%s-%s-%s %s:%s:%s" % (date[0:4], + date[4:6], + date[6:8], + date[9:11], + date[11:13], + date[13:]) + return res +
+
[docs]def merge_dicts(*dict_args): + """\ + Given any number of dicts, shallow copy and merge into a new dict, + precedence goes to key value pairs in latter dicts. + """ + result = {} + for dictionary in dict_args: + result.update(dictionary) + return result +
+
[docs]def replace_in_file(filein, strin, strout): + """Replace <strin> by <strout> in file <filein>""" + shutil.move(filein, filein + "_old") + fileout= filein + filein = filein + "_old" + fin = open(filein, "r") + fout = open(fileout, "w") + for line in fin: + fout.write(line.replace(strin, strout)) +
+
[docs]def get_property_in_product_cfg(product_cfg, pprty): + if not "properties" in product_cfg: + return None + if not pprty in product_cfg.properties: + return None + return product_cfg.properties[pprty] +
+
[docs]def activate_mesa_property(config): + """Add mesa property into application properties + + :param config Config: The global configuration. It must have an application! + """ + # Verify the existence of the file + if not 'properties' in config.APPLICATION: + config.APPLICATION.addMapping( 'properties', src.pyconf.Mapping(), None ) + config.APPLICATION.properties.use_mesa="yes" +
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/architecture.html b/doc/build/html/_modules/src/architecture.html new file mode 100644 index 0000000..e47e0d0 --- /dev/null +++ b/doc/build/html/_modules/src/architecture.html @@ -0,0 +1,239 @@ + + + + + + + + + src.architecture — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.architecture

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+'''
+In this file : all the stuff that can change with the architecture 
+on which SAT is running
+'''
+
+import os, sys, platform
+
+
[docs]def is_windows(): + '''method that checks windows OS + + :rtype: boolean + ''' + return platform.system() == 'Windows' +
+
[docs]def get_user(): + '''method that gets the username that launched sat + + :rtype: str + ''' + # In windows case, the USERNAME environment variable has to be set + if is_windows(): + if not os.environ.has_key('USERNAME'): + raise Exception('USERNAME environment variable not set') + return os.environ['USERNAME'] + else: # linux + import pwd + return pwd.getpwuid(os.getuid())[0] +
+def _lsb_release(args): + '''Get system information with lsb_release. + + :param args str: The arguments to give to lsb_release. + :return: The distribution. + :rtype: str + ''' + try: + path = '/usr/local/bin:/usr/bin:/bin' + lsb_path = os.getenv("LSB_PATH") + if lsb_path is not None: + path = lsb_path + ":" + path + + from subprocess import Popen, PIPE + res = Popen(['lsb_release', args], env={'PATH': path}, + stdout=PIPE).communicate()[0][:-1] + # in case of python3, convert byte to str + if isinstance(res, bytes): + res = res.decode() + return res + except OSError: + sys.stderr.write(_(u"lsb_release not installed\n")) + sys.stderr.write(_(u"You can define $LSB_PATH to give" + " the path to lsb_release\n")) + sys.exit(-1) + +
[docs]def get_distribution(codes): + '''Gets the code for the distribution + + :param codes L{Mapping}: The map containing distribution correlation table. + :return: The distribution on which salomeTools is running, regarding the + distribution correlation table contained in codes variable. + :rtype: str + ''' + if is_windows(): + return "Win" + + # Call to lsb_release + distrib = _lsb_release('-si') + if codes is not None and distrib in codes: + distrib = codes[distrib] + else: + sys.stderr.write(_(u"Unknown distribution: '%s'\n") % distrib) + sys.stderr.write(_(u"Please add your distribution to" + " src/internal_config/distrib.pyconf\n")) + sys.exit(-1) + + return distrib + +
+
[docs]def get_distrib_version(distrib, codes): + '''Gets the version of the distribution + + :param distrib str: The distribution on which the version will be found. + :param codes L{Mapping}: The map containing distribution correlation table. + :return: The version of the distribution on which salomeTools is running, + regarding the distribution correlation table contained in codes + variable. + :rtype: str + ''' + + if is_windows(): + return platform.release() + + # Call to lsb_release + version = _lsb_release('-sr') + if distrib in codes: + if version in codes[distrib]: + version = codes[distrib][version] + + if distrib == "CO": + version=version[0] #for centos, we only care for major version + return version +
+
[docs]def get_python_version(): + '''Gets the version of the running python. + + :return: the version of the running python. + :rtype: str + ''' + + # The platform python module gives the answer + return platform.python_version() +
+
[docs]def get_nb_proc(): + '''Gets the number of processors of the machine + on which salomeTools is running. + + :return: the number of processors. + :rtype: str + ''' + + try : + import multiprocessing + nb_proc=multiprocessing.cpu_count() + except : + nb_proc=int(os.sysconf('SC_NPROCESSORS_ONLN')) + return nb_proc
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/colorama/ansi.html b/doc/build/html/_modules/src/colorama/ansi.html new file mode 100644 index 0000000..3f13ba4 --- /dev/null +++ b/doc/build/html/_modules/src/colorama/ansi.html @@ -0,0 +1,197 @@ + + + + + + + + + src.colorama.ansi — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.colorama.ansi

+# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
+'''
+This module generates ANSI character codes to printing colors to terminals.
+See: http://en.wikipedia.org/wiki/ANSI_escape_code
+'''
+
+CSI = '\033['
+OSC = '\033]'
+BEL = '\007'
+
+
+
[docs]def code_to_chars(code): + return CSI + str(code) + 'm' +
+
[docs]def set_title(title): + return OSC + '2;' + title + BEL +
+
[docs]def clear_screen(mode=2): + return CSI + str(mode) + 'J' +
+
[docs]def clear_line(mode=2): + return CSI + str(mode) + 'K' + +
+
[docs]class AnsiCodes(object): + def __init__(self): + # the subclasses declare class attributes which are numbers. + # Upon instantiation we define instance attributes, which are the same + # as the class attributes but wrapped with the ANSI escape sequence + for name in dir(self): + if not name.startswith('_'): + value = getattr(self, name) + setattr(self, name, code_to_chars(value)) + +
+
[docs]class AnsiCursor(object): +
[docs] def UP(self, n=1): + return CSI + str(n) + 'A'
+
[docs] def DOWN(self, n=1): + return CSI + str(n) + 'B'
+
[docs] def FORWARD(self, n=1): + return CSI + str(n) + 'C'
+
[docs] def BACK(self, n=1): + return CSI + str(n) + 'D'
+
[docs] def POS(self, x=1, y=1): + return CSI + str(y) + ';' + str(x) + 'H' + +
+
[docs]class AnsiFore(AnsiCodes): + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 90 + LIGHTRED_EX = 91 + LIGHTGREEN_EX = 92 + LIGHTYELLOW_EX = 93 + LIGHTBLUE_EX = 94 + LIGHTMAGENTA_EX = 95 + LIGHTCYAN_EX = 96 + LIGHTWHITE_EX = 97 + +
+
[docs]class AnsiBack(AnsiCodes): + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 100 + LIGHTRED_EX = 101 + LIGHTGREEN_EX = 102 + LIGHTYELLOW_EX = 103 + LIGHTBLUE_EX = 104 + LIGHTMAGENTA_EX = 105 + LIGHTCYAN_EX = 106 + LIGHTWHITE_EX = 107 + +
+
[docs]class AnsiStyle(AnsiCodes): + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 +
+Fore = AnsiFore() +Back = AnsiBack() +Style = AnsiStyle() +Cursor = AnsiCursor() +
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/colorama/ansitowin32.html b/doc/build/html/_modules/src/colorama/ansitowin32.html new file mode 100644 index 0000000..e750280 --- /dev/null +++ b/doc/build/html/_modules/src/colorama/ansitowin32.html @@ -0,0 +1,331 @@ + + + + + + + + + src.colorama.ansitowin32 — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.colorama.ansitowin32

+# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
+import re
+import sys
+import os
+
+from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style
+from .winterm import WinTerm, WinColor, WinStyle
+from .win32 import windll, winapi_test
+
+
+winterm = None
+if windll is not None:
+    winterm = WinTerm()
+
+
+
[docs]def is_stream_closed(stream): + return not hasattr(stream, 'closed') or stream.closed + +
+
[docs]def is_a_tty(stream): + return hasattr(stream, 'isatty') and stream.isatty() + +
+
[docs]class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + +
[docs] def write(self, text): + self.__convertor.write(text) + +
+
[docs]class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\001?\033\[((?:\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer + ANSI_OSC_RE = re.compile('\001?\033\]((?:.|;)*?)(\x07)\002?') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = os.name == 'nt' + # We test if the WinAPI works, because even if we are on Windows + # we may be using a terminal that doesn't support the WinAPI + # (e.g. Cygwin Terminal). In this case it's up to the terminal + # to support the ANSI codes. + conversion_supported = on_windows and winapi_test() + + # should we strip ANSI sequences from our output? + if strip is None: + strip = conversion_supported or (not is_stream_closed(wrapped) and not is_a_tty(wrapped)) + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = conversion_supported and not is_stream_closed(wrapped) and is_a_tty(wrapped) + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + +
[docs] def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset +
+
[docs] def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), + AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), + AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), + AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), + AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), + AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), + AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), + AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), + AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), + AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), + AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), + AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), + AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), + AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), + AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), + } + return dict() +
+
[docs] def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + +
+
[docs] def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif not self.strip and not is_stream_closed(self.wrapped): + self.wrapped.write(Style.RESET_ALL) + +
+
[docs] def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + text = self.convert_osc(text) + for match in self.ANSI_CSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + +
+
[docs] def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + +
+
[docs] def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(command, paramstring) + self.call_win32(command, params) + +
+
[docs] def extract_params(self, command, paramstring): + if command in 'Hf': + params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) + while len(params) < 2: + # defaults: + params = params + (1,) + else: + params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) + if len(params) == 0: + # defaults: + if command in 'JKm': + params = (0,) + elif command in 'ABCD': + params = (1,) + + return params + +
+
[docs] def call_win32(self, command, params): + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in 'J': + winterm.erase_screen(params[0], on_stderr=self.on_stderr) + elif command in 'K': + winterm.erase_line(params[0], on_stderr=self.on_stderr) + elif command in 'Hf': # cursor position - absolute + winterm.set_cursor_position(params, on_stderr=self.on_stderr) + elif command in 'ABCD': # cursor position - relative + n = params[0] + # A - up, B - down, C - forward, D - back + x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] + winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) + +
+
[docs] def convert_osc(self, text): + for match in self.ANSI_OSC_RE.finditer(text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() + if command in '\x07': # \x07 = BEL + params = paramstring.split(";") + # 0 - change title and icon (we will only change title) + # 1 - change icon (we don't support this) + # 2 - change title + if params[0] in '02': + winterm.set_title(params[1]) + return text
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/colorama/initialise.html b/doc/build/html/_modules/src/colorama/initialise.html new file mode 100644 index 0000000..10d509f --- /dev/null +++ b/doc/build/html/_modules/src/colorama/initialise.html @@ -0,0 +1,175 @@ + + + + + + + + + src.colorama.initialise — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.colorama.initialise

+# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
+import atexit
+import contextlib
+import sys
+
+from .ansitowin32 import AnsiToWin32
+
+
+orig_stdout = None
+orig_stderr = None
+
+wrapped_stdout = None
+wrapped_stderr = None
+
+atexit_done = False
+
+
+
[docs]def reset_all(): + if AnsiToWin32 is not None: # Issue #74: objects might become None at exit + AnsiToWin32(orig_stdout).reset_all() + +
+
[docs]def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + global orig_stdout, orig_stderr + + orig_stdout = sys.stdout + orig_stderr = sys.stderr + + if sys.stdout is None: + wrapped_stdout = None + else: + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + if sys.stderr is None: + wrapped_stderr = None + else: + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + +
+
[docs]def deinit(): + if orig_stdout is not None: + sys.stdout = orig_stdout + if orig_stderr is not None: + sys.stderr = orig_stderr + +
+@contextlib.contextmanager +
[docs]def colorama_text(*args, **kwargs): + init(*args, **kwargs) + try: + yield + finally: + deinit() + +
+
[docs]def reinit(): + if wrapped_stdout is not None: + sys.stdout = wrapped_stdout + if wrapped_stderr is not None: + sys.stderr = wrapped_stderr + +
+
[docs]def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream +
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/colorama/win32.html b/doc/build/html/_modules/src/colorama/win32.html new file mode 100644 index 0000000..49bd541 --- /dev/null +++ b/doc/build/html/_modules/src/colorama/win32.html @@ -0,0 +1,249 @@ + + + + + + + + + src.colorama.win32 — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.colorama.win32

+# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
+
+# from winbase.h
+STDOUT = -11
+STDERR = -12
+
+try:
+    import ctypes
+    from ctypes import LibraryLoader
+    windll = LibraryLoader(ctypes.WinDLL)
+    from ctypes import wintypes
+except (AttributeError, ImportError):
+    windll = None
+    SetConsoleTextAttribute = lambda *_: None
+    winapi_test = lambda *_: None
+else:
+    from ctypes import byref, Structure, c_char, POINTER
+
+    COORD = wintypes._COORD
+
+    class CONSOLE_SCREEN_BUFFER_INFO(Structure):
+        """struct in wincon.h."""
+        _fields_ = [
+            ("dwSize", COORD),
+            ("dwCursorPosition", COORD),
+            ("wAttributes", wintypes.WORD),
+            ("srWindow", wintypes.SMALL_RECT),
+            ("dwMaximumWindowSize", COORD),
+        ]
+        def __str__(self):
+            return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
+                self.dwSize.Y, self.dwSize.X
+                , self.dwCursorPosition.Y, self.dwCursorPosition.X
+                , self.wAttributes
+                , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
+                , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
+            )
+
+    _GetStdHandle = windll.kernel32.GetStdHandle
+    _GetStdHandle.argtypes = [
+        wintypes.DWORD,
+    ]
+    _GetStdHandle.restype = wintypes.HANDLE
+
+    _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
+    _GetConsoleScreenBufferInfo.argtypes = [
+        wintypes.HANDLE,
+        POINTER(CONSOLE_SCREEN_BUFFER_INFO),
+    ]
+    _GetConsoleScreenBufferInfo.restype = wintypes.BOOL
+
+    _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
+    _SetConsoleTextAttribute.argtypes = [
+        wintypes.HANDLE,
+        wintypes.WORD,
+    ]
+    _SetConsoleTextAttribute.restype = wintypes.BOOL
+
+    _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
+    _SetConsoleCursorPosition.argtypes = [
+        wintypes.HANDLE,
+        COORD,
+    ]
+    _SetConsoleCursorPosition.restype = wintypes.BOOL
+
+    _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA
+    _FillConsoleOutputCharacterA.argtypes = [
+        wintypes.HANDLE,
+        c_char,
+        wintypes.DWORD,
+        COORD,
+        POINTER(wintypes.DWORD),
+    ]
+    _FillConsoleOutputCharacterA.restype = wintypes.BOOL
+
+    _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
+    _FillConsoleOutputAttribute.argtypes = [
+        wintypes.HANDLE,
+        wintypes.WORD,
+        wintypes.DWORD,
+        COORD,
+        POINTER(wintypes.DWORD),
+    ]
+    _FillConsoleOutputAttribute.restype = wintypes.BOOL
+
+    _SetConsoleTitleW = windll.kernel32.SetConsoleTitleA
+    _SetConsoleTitleW.argtypes = [
+        wintypes.LPCSTR
+    ]
+    _SetConsoleTitleW.restype = wintypes.BOOL
+
+    handles = {
+        STDOUT: _GetStdHandle(STDOUT),
+        STDERR: _GetStdHandle(STDERR),
+    }
+
+
[docs] def winapi_test(): + handle = handles[STDOUT] + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return bool(success) +
+ def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = handles[stream_id] + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + +
[docs] def SetConsoleTextAttribute(stream_id, attrs): + handle = handles[stream_id] + return _SetConsoleTextAttribute(handle, attrs) +
+ def SetConsoleCursorPosition(stream_id, position, adjust=True): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + if adjust: + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = handles[stream_id] + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = handles[stream_id] + char = c_char(char.encode()) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = handles[stream_id] + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + + def SetConsoleTitle(title): + return _SetConsoleTitleW(title) +
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/colorama/winterm.html b/doc/build/html/_modules/src/colorama/winterm.html new file mode 100644 index 0000000..8f2045e --- /dev/null +++ b/doc/build/html/_modules/src/colorama/winterm.html @@ -0,0 +1,257 @@ + + + + + + + + + src.colorama.winterm — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.colorama.winterm

+# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
+from . import win32
+
+
+# from wincon.h
+
[docs]class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h
+
[docs]class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + BRIGHT_BACKGROUND = 0x80 # dim text, bright background +
+
[docs]class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. + # So that LIGHT_EX colors and BRIGHT style do not clobber each other, + # we track them separately, since LIGHT_EX is overwritten by Fore/Back + # and BRIGHT is overwritten by Style codes. + self._light = 0 + +
[docs] def get_attrs(self): + return self._fore + self._back * 16 + (self._style | self._light) +
+
[docs] def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) +
+
[docs] def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) +
+
[docs] def fore(self, fore=None, light=False, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + # Emulate LIGHT_EX with BRIGHT Style + if light: + self._light |= WinStyle.BRIGHT + else: + self._light &= ~WinStyle.BRIGHT + self.set_console(on_stderr=on_stderr) +
+
[docs] def back(self, back=None, light=False, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style + if light: + self._light |= WinStyle.BRIGHT_BACKGROUND + else: + self._light &= ~WinStyle.BRIGHT_BACKGROUND + self.set_console(on_stderr=on_stderr) +
+
[docs] def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) +
+
[docs] def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) +
+
[docs] def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position +
+
[docs] def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + # I'm not currently tracking the position, so there is no default. + # position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) +
+
[docs] def cursor_adjust(self, x, y, on_stderr=False): + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y + y, position.X + x) + win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) +
+
[docs] def erase_screen(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen, and move cursor to (1,1) + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y + # get number of character cells before current cursor position + cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = cells_in_screen - cells_before_cursor + if mode == 1: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_before_cursor + elif mode == 2: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_in_screen + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + if mode == 2: + # put the cursor where needed + win32.SetConsoleCursorPosition(handle, (1, 1)) +
+
[docs] def erase_line(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the line. + # 1 should clear from the cursor to the beginning of the line. + # 2 should clear the entire line. + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X + if mode == 1: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwCursorPosition.X + elif mode == 2: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwSize.X + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) +
+
[docs] def set_title(self, title): + win32.SetConsoleTitle(title)
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/compilation.html b/doc/build/html/_modules/src/compilation.html new file mode 100644 index 0000000..2de70b5 --- /dev/null +++ b/doc/build/html/_modules/src/compilation.html @@ -0,0 +1,588 @@ + + + + + + + + + src.compilation — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.compilation

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+import os
+import subprocess
+import sys
+import shutil
+
+import src
+
+C_COMPILE_ENV_LIST = ["CC",
+                      "CXX",
+                      "F77",
+                      "CFLAGS",
+                      "CXXFLAGS",
+                      "LIBS",
+                      "LDFLAGS"]
+
+
[docs]class Builder: + """Class to handle all construction steps, like cmake, configure, make, ... + """ + def __init__(self, + config, + logger, + product_info, + options = src.options.OptResult(), + check_src=True): + self.config = config + self.logger = logger + self.options = options + self.product_info = product_info + self.build_dir = src.Path(self.product_info.build_dir) + self.source_dir = src.Path(self.product_info.source_dir) + self.install_dir = src.Path(self.product_info.install_dir) + self.header = "" + self.debug_mode = False + if "debug" in self.product_info and self.product_info.debug == "yes": + self.debug_mode = True + + ## + # Shortcut method to log in log file. +
[docs] def log(self, text, level, showInfo=True): + self.logger.write(text, level, showInfo) + self.logger.logTxtFile.write(src.printcolors.cleancolor(text)) + self.logger.flush() + + ## + # Shortcut method to log a command.
+
[docs] def log_command(self, command): + self.log("> %s\n" % command, 5) + + ## + # Prepares the environment. + # Build two environment: one for building and one for testing (launch).
+
[docs] def prepare(self): + + if not self.build_dir.exists(): + # create build dir + self.build_dir.make() + + self.log(' build_dir = %s\n' % str(self.build_dir), 4) + self.log(' install_dir = %s\n' % str(self.install_dir), 4) + self.log('\n', 4) + + # add products in depend and opt_depend list recursively + environ_info = src.product.get_product_dependencies(self.config, + self.product_info) + #environ_info.append(self.product_info.name) + + # create build environment + self.build_environ = src.environment.SalomeEnviron(self.config, + src.environment.Environ(dict(os.environ)), + True) + self.build_environ.silent = (self.config.USER.output_verbose_level < 5) + self.build_environ.set_full_environ(self.logger, environ_info) + + # create runtime environment + self.launch_environ = src.environment.SalomeEnviron(self.config, + src.environment.Environ(dict(os.environ)), + False) + self.launch_environ.silent = True # no need to show here + self.launch_environ.set_full_environ(self.logger, environ_info) + + for ee in C_COMPILE_ENV_LIST: + vv = self.build_environ.get(ee) + if len(vv) > 0: + self.log(" %s = %s\n" % (ee, vv), 4, False) + + return 0 + + ## + # Runs cmake with the given options.
+
[docs] def cmake(self, options=""): + + cmake_option = options + # cmake_option +=' -DCMAKE_VERBOSE_MAKEFILE=ON -DSALOME_CMAKE_DEBUG=ON' + if 'cmake_options' in self.product_info: + cmake_option += " %s " % " ".join( + self.product_info.cmake_options.split()) + + # add debug option + if self.debug_mode: + cmake_option += " -DCMAKE_BUILD_TYPE=Debug" + else : + cmake_option += " -DCMAKE_BUILD_TYPE=Release" + + # In case CMAKE_GENERATOR is defined in environment, + # use it in spite of automatically detect it + if 'cmake_generator' in self.config.APPLICATION: + cmake_option += " -DCMAKE_GENERATOR=%s" \ + % self.config.APPLICATION.cmake_generator + + command = ("cmake %s -DCMAKE_INSTALL_PREFIX=%s %s" % + (cmake_option, self.install_dir, self.source_dir)) + + self.log_command(command) + # for key in sorted(self.build_environ.environ.environ.keys()): + # print key, " ", self.build_environ.environ.environ[key] + res = subprocess.call(command, + shell=True, + cwd=str(self.build_dir), + env=self.build_environ.environ.environ, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT) + + self.put_txt_log_in_appli_log_dir("cmake") + if res == 0: + return res + else: + return 1 + + ## + # Runs build_configure with the given options.
+
[docs] def build_configure(self, options=""): + + if 'buildconfigure_options' in self.product_info: + options += " %s " % self.product_info.buildconfigure_options + + command = str('%s/build_configure') % (self.source_dir) + command = command + " " + options + self.log_command(command) + + res = subprocess.call(command, + shell=True, + cwd=str(self.build_dir), + env=self.build_environ.environ.environ, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT) + self.put_txt_log_in_appli_log_dir("build_configure") + if res == 0: + return res + else: + return 1 + + ## + # Runs configure with the given options.
+
[docs] def configure(self, options=""): + + if 'configure_options' in self.product_info: + options += " %s " % self.product_info.configure_options + + command = "%s/configure --prefix=%s" % (self.source_dir, + str(self.install_dir)) + + command = command + " " + options + self.log_command(command) + + res = subprocess.call(command, + shell=True, + cwd=str(self.build_dir), + env=self.build_environ.environ.environ, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT) + + self.put_txt_log_in_appli_log_dir("configure") + if res == 0: + return res + else: + return 1 +
+
[docs] def hack_libtool(self): + if not os.path.exists(str(self.build_dir + 'libtool')): + return + + lf = open(os.path.join(str(self.build_dir), "libtool"), 'r') + for line in lf.readlines(): + if 'hack_libtool' in line: + return + + # fix libtool by replacing CC="<compil>" with hack_libtool function + hack_command='''sed -i "s%^CC=\\"\(.*\)\\"%hack_libtool() { \\n\\ +if test \\"\$(echo \$@ | grep -E '\\\\\\-L/usr/lib(/../lib)?(64)? ')\\" == \\\"\\\" \\n\\ + then\\n\\ + cmd=\\"\\1 \$@\\"\\n\\ + else\\n\\ + cmd=\\"\\1 \\"\`echo \$@ | sed -r -e 's|(.*)-L/usr/lib(/../lib)?(64)? (.*)|\\\\\\1\\\\\\4 -L/usr/lib\\\\\\3|g'\`\\n\\ + fi\\n\\ + \$cmd\\n\\ +}\\n\\ +CC=\\"hack_libtool\\"%g" libtool''' + + self.log_command(hack_command) + subprocess.call(hack_command, + shell=True, + cwd=str(self.build_dir), + env=self.build_environ.environ.environ, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT) + + + ## + # Runs make to build the module.
+
[docs] def make(self, nb_proc, make_opt=""): + + # make + command = 'make' + command = command + " -j" + str(nb_proc) + command = command + " " + make_opt + self.log_command(command) + res = subprocess.call(command, + shell=True, + cwd=str(self.build_dir), + env=self.build_environ.environ.environ, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT) + self.put_txt_log_in_appli_log_dir("make") + if res == 0: + return res + else: + return 1 + + ## + # Runs msbuild to build the module.
+
[docs] def wmake(self,nb_proc, opt_nb_proc = None): + + hh = 'MSBUILD /m:%s' % str(nb_proc) + if self.debug_mode: + hh += " " + src.printcolors.printcWarning("DEBUG") + # make + command = 'msbuild' + command = command + " /maxcpucount:" + str(nb_proc) + if self.debug_mode: + command = command + " /p:Configuration=Debug" + else: + command = command + " /p:Configuration=Release" + command = command + " ALL_BUILD.vcxproj" + + self.log_command(command) + res = subprocess.call(command, + shell=True, + cwd=str(self.build_dir), + env=self.build_environ.environ.environ, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT) + + self.put_txt_log_in_appli_log_dir("make") + if res == 0: + return res + else: + return 1 + + ## + # Runs 'make install'.
+
[docs] def install(self): + if self.config.VARS.dist_name=="Win": + command = 'msbuild INSTALL.vcxproj' + if self.debug_mode: + command = command + " /p:Configuration=Debug" + else: + command = command + " /p:Configuration=Release" + else : + command = 'make install' + + self.log_command(command) + + res = subprocess.call(command, + shell=True, + cwd=str(self.build_dir), + env=self.build_environ.environ.environ, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT) + + self.put_txt_log_in_appli_log_dir("makeinstall") + if res == 0: + return res + else: + return 1 + + ## + # Runs 'make_check'.
+
[docs] def check(self, command=""): + if src.architecture.is_windows(): + cmd = 'msbuild RUN_TESTS.vcxproj' + else : + if self.product_info.build_source=="autotools" : + cmd = 'make check' + else: + cmd = 'make test' + + if command: + cmd = command + + self.log_command(cmd) + + res = subprocess.call(cmd, + shell=True, + cwd=str(self.build_dir), + env=self.launch_environ.environ.environ, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT) + + if res == 0: + return res + else: + return 1 + + ## + # Performs a default build for this module.
+
[docs] def do_default_build(self, + build_conf_options="", + configure_options="", + show_warning=True): + use_autotools = False + if 'use_autotools' in self.product_info: + uc = self.product_info.use_autotools + if uc in ['always', 'yes']: + use_autotools = True + elif uc == 'option': + use_autotools = self.options.autotools + + + self.use_autotools = use_autotools + + use_ctest = False + if 'use_ctest' in self.product_info: + uc = self.product_info.use_ctest + if uc in ['always', 'yes']: + use_ctest = True + elif uc == 'option': + use_ctest = self.options.ctest + + self.use_ctest = use_ctest + + if show_warning: + cmd = "" + if use_autotools: cmd = "(autotools)" + if use_ctest: cmd = "(ctest)" + + self.log("\n", 4, False) + self.log("%(module)s: Run default compilation method %(cmd)s\n" % \ + { "module": self.module, "cmd": cmd }, 4) + + if use_autotools: + if not self.prepare(): return self.get_result() + if not self.build_configure( + build_conf_options): return self.get_result() + if not self.configure(configure_options): return self.get_result() + if not self.make(): return self.get_result() + if not self.install(): return self.get_result() + if not self.clean(): return self.get_result() + + else: # CMake + if self.config.VARS.dist_name=='Win': + if not self.wprepare(): return self.get_result() + if not self.cmake(): return self.get_result() + if not self.wmake(): return self.get_result() + if not self.install(): return self.get_result() + if not self.clean(): return self.get_result() + else : + if not self.prepare(): return self.get_result() + if not self.cmake(): return self.get_result() + if not self.make(): return self.get_result() + if not self.install(): return self.get_result() + if not self.clean(): return self.get_result() + + return self.get_result() + + ## + # Performs a build with a script.
+
[docs] def do_python_script_build(self, script, nb_proc): + # script found + self.logger.write(_("Compile %(product)s using script %(script)s\n") % \ + { 'product': self.product_info.name, + 'script': src.printcolors.printcLabel(script) }, 4) + try: + import imp + product = self.product_info.name + pymodule = imp.load_source(product + "_compile_script", script) + self.nb_proc = nb_proc + retcode = pymodule.compil(self.config, self, self.logger) + except: + __, exceptionValue, exceptionTraceback = sys.exc_info() + self.logger.write(str(exceptionValue), 1) + import traceback + traceback.print_tb(exceptionTraceback) + traceback.print_exc() + retcode = 1 + finally: + self.put_txt_log_in_appli_log_dir("script") + + return retcode +
+
[docs] def complete_environment(self, make_options): + assert self.build_environ is not None + # pass additional variables to environment + # (may be used by the build script) + self.build_environ.set("SOURCE_DIR", str(self.source_dir)) + self.build_environ.set("INSTALL_DIR", str(self.install_dir)) + self.build_environ.set("PRODUCT_INSTALL", str(self.install_dir)) + self.build_environ.set("BUILD_DIR", str(self.build_dir)) + self.build_environ.set("PRODUCT_BUILD", str(self.build_dir)) + self.build_environ.set("MAKE_OPTIONS", make_options) + self.build_environ.set("DIST_NAME", self.config.VARS.dist_name) + self.build_environ.set("DIST_VERSION", self.config.VARS.dist_version) + self.build_environ.set("DIST", self.config.VARS.dist) + self.build_environ.set("VERSION", self.product_info.version) +
+
[docs] def do_batch_script_build(self, script, nb_proc): + + if src.architecture.is_windows(): + make_options = "/maxcpucount:%s" % nb_proc + else : + make_options = "-j%s" % nb_proc + + self.log_command(" " + _("Run build script %s\n") % script) + self.complete_environment(make_options) + + res = subprocess.call(script, + shell=True, + stdout=self.logger.logTxtFile, + stderr=subprocess.STDOUT, + cwd=str(self.build_dir), + env=self.build_environ.environ.environ) + + self.put_txt_log_in_appli_log_dir("script") + if res == 0: + return res + else: + return 1 +
+
[docs] def do_script_build(self, script, number_of_proc=0): + # define make options (may not be used by the script) + if number_of_proc==0: + nb_proc = src.get_cfg_param(self.product_info,"nb_proc", 0) + if nb_proc == 0: + nb_proc = self.config.VARS.nb_proc + else: + nb_proc = min(number_of_proc, self.config.VARS.nb_proc) + + extension = script.split('.')[-1] + if extension in ["bat","sh"]: + return self.do_batch_script_build(script, nb_proc) + if extension == "py": + return self.do_python_script_build(script, nb_proc) + + msg = _("The script %s must have .sh, .bat or .py extension." % script) + raise src.SatException(msg) +
+
[docs] def put_txt_log_in_appli_log_dir(self, file_name): + '''Put the txt log (that contain the system logs, like make command + output) in the directory <APPLICATION DIR>/LOGS/<product_name>/ + + :param file_name Str: the name of the file to write + ''' + if self.logger.logTxtFile == sys.__stdout__: + return + dir_where_to_put = os.path.join(self.config.APPLICATION.workdir, + "LOGS", + self.product_info.name) + file_path = os.path.join(dir_where_to_put, file_name) + src.ensure_path_exists(dir_where_to_put) + # write the logTxtFile copy it to the destination, and then recreate + # it as it was + self.logger.logTxtFile.close() + shutil.move(self.logger.txtFilePath, file_path) + self.logger.logTxtFile = open(str(self.logger.txtFilePath), 'w') + self.logger.logTxtFile.write(open(file_path, "r").read()) +
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/debug.html b/doc/build/html/_modules/src/debug.html new file mode 100644 index 0000000..8be6b29 --- /dev/null +++ b/doc/build/html/_modules/src/debug.html @@ -0,0 +1,297 @@ + + + + + + + + + src.debug — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.debug

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+#  Copyright (C) 2010-2018  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+"""\
+This file assume DEBUG functionalities use
+
+- print debug messages in sys.stderr for salomeTools
+- show pretty print debug representation from instances of SAT classes
+  (pretty print src.pyconf.Config), and python dict/list etc. (as 'aVariable')
+
+WARNING: obviously supposedly show messages in SAT development phase, not production
+
+usage:
+>> import debug as DBG
+>> DBG.write("aTitle", aVariable)        # not shown in production 
+>> DBG.write("aTitle", aVariable, True)  # unconditionaly shown (as show=True)
+
+to set show message as development phase:
+>> DBG.push_debug(True)
+
+to set no show message as production phase:
+>> DBG.push_debug(False)
+
+to set show message temporary as development phase, only in a method:
+>> def aMethodToDebug(...):
+>>   DBG.push_debug(True)              #force show as appended status
+>>   etc. method code with some DBG.write()
+>>   DBG.pop_debug()                   #restore previous status (show or not show)
+>>   return
+
+to set a message for future fix, as temporary problem to not forget:
+DBG.tofix("aTitle", aVariable, True/False) #True/False in production shown, or not
+
+in command line interface you could redirect stderr to file 'myDebug.log':
+>> sat compile ... 2> myDebug.log   # only stderr
+>> sat compile ... &> myDebug.log   # stdout and stderr
+"""
+
+import os
+import sys
+import StringIO as SIO
+import pprint as PP
+
+_debug = [False] #support push/pop for temporary activate debug outputs
+
+
[docs]def indent(text, amount=2, ch=' '): + """indent multi lines message""" + padding = amount * ch + return ''.join(padding + line for line in text.splitlines(True)) +
+
[docs]def write(title, var="", force=None, fmt="\n#### DEBUG: %s:\n%s\n"): + """write sys.stderr a message if _debug[-1]==True or optionaly force=True""" + if _debug[-1] or force: + if 'src.pyconf.' in str(type(var)): + sys.stderr.write(fmt % (title, indent(getStrConfigDbg(var)))) + elif type(var) is not str: + sys.stderr.write(fmt % (title, indent(PP.pformat(var)))) + else: + sys.stderr.write(fmt % (title, indent(var))) + return +
+
[docs]def tofix(title, var="", force=None): + """\ + write sys.stderr a message if _debug[-1]==True or optionaly force=True + use this only if no logger accessible for classic + logger.warning(message) or logger.debug(message) + """ + fmt = "\n#### TOFIX: %s:\n%s\n" + write(title, var, force, fmt) +
+
[docs]def push_debug(aBool): + """set debug outputs activated, or not""" + _debug.append(aBool) +
+
[docs]def pop_debug(): + """restore previous debug outputs status""" + if len(_debug) > 1: + return _debug.pop() + else: + sys.stderr.write("\nERROR: pop_debug: too much pop.") + return None + +############################################### +# utilitaires divers pour debug +############################################### +
+
[docs]class OutStream(SIO.StringIO): + """utility class for pyconf.Config output iostream""" +
[docs] def close(self): + """because Config.__save__ calls close() stream as file + keep value before lost as self.value + """ + self.value = self.getvalue() + SIO.StringIO.close(self) +
+
[docs]class InStream(SIO.StringIO): + """utility class for pyconf.Config input iostream""" + pass +
+
[docs]def getLocalEnv(): + """get string for environment variables representation""" + res = "" + for i in sorted(os.environ): + res += "%s : %s\n" % (i, os.environ[i]) + return res + +# save as initial Config.save() moved as Config.__save__()
+
[docs]def saveConfigStd(config, aStream): + """returns as file .pyconf""" + indent = 0 + config.__save__(aStream, indent) +
+
[docs]def getStrConfigStd(config): + """set string as saveConfigStd, as file .pyconf""" + outStream = OutStream() + saveConfigStd(config, outStream) + return outStream.value +
+
[docs]def getStrConfigDbg(config): + """\ + set string as saveConfigDbg, + as (path expression evaluation) for debug + """ + outStream = OutStream() + saveConfigDbg(config, outStream) + return outStream.value +
+
[docs]def saveConfigDbg(config, aStream, indent=0, path=""): + """pyconf returns multilines (path expression evaluation) for debug""" + _saveConfigRecursiveDbg(config, aStream, indent, path) + aStream.close() # as config.__save__() +
+def _saveConfigRecursiveDbg(config, aStream, indent, path): + """pyconf inspired from Mapping.__save__""" + debug = False + if indent <= 0: + indentp = 0 + else: + indentp = indentp + 2 + indstr = indent * ' ' # '':no indent, ' ':indent + strType = str(type(config)) + if "Sequence" in strType: + for i in range(len(config)): + _saveConfigRecursiveDbg(config[i], aStream, indentp, path+"[%i]" % i) + return + try: + order = object.__getattribute__(config, 'order') + data = object.__getattribute__(config, 'data') + except: + aStream.write("%s%s : '%s'\n" % (indstr, path, str(config))) + return + for key in sorted(order): + value = data[key] + strType = str(type(value)) + if debug: print indstr + 'strType = %s' % strType, key + if "Config" in strType: + _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key) + continue + if "Mapping" in strType: + _saveConfigRecursiveDbg(value, aStream, indentp, path+"."+key) + continue + if "Sequence" in strType: + for i in range(len(value)): + _saveConfigRecursiveDbg(value[i], aStream, indentp, path+"."+key+"[%i]" % i) + continue + if "Expression" in strType: + try: + evaluate = value.evaluate(config) + aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate)) + except Exception as e: + aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message)) + continue + if "Reference" in strType: + try: + evaluate = value.resolve(config) + aStream.write("%s%s.%s : %s --> '%s'\n" % (indstr, path, key, str(value), evaluate)) + except Exception as e: + aStream.write("%s%s.%s : !!! ERROR: %s !!!\n" % (indstr, path, key, e.message)) + continue + if type(value) in [str, bool, int, type(None), unicode]: + aStream.write("%s%s.%s : '%s'\n" % (indstr, path, key, str(value))) + continue + try: + aStream.write("!!! TODO fix that %s %s%s.%s : %s\n" % (type(value), indstr, path, key, str(value))) + except Exception as e: + aStream.write("%s%s.%s : !!! %s\n" % (indstr, path, key, e.message)) +
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/environment.html b/doc/build/html/_modules/src/environment.html new file mode 100644 index 0000000..94ebac1 --- /dev/null +++ b/doc/build/html/_modules/src/environment.html @@ -0,0 +1,982 @@ + + + + + + + + + src.environment — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.environment

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+import os
+import subprocess
+import string
+import sys
+
+import src
+import src.debug as DBG
+import pprint as PP
+
+
[docs]class Environ: + """\ + Class to manage the environment context + """ + def __init__(self, environ=None): + """Initialization. If the environ argument is passed, the environment + will be add to it, else it is the external environment. + + :param environ dict: + """ + if environ is not None: + self.environ = environ + else: + self.environ = os.environ + + def __repr__(self): + """easy non exhaustive quick resume for debug print""" + return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(self.environ)) + + def _expandvars(self, value): + """\ + replace some $VARIABLE into its actual value in the environment + + :param value str: the string to be replaced + :return: the replaced variable + :rtype: str + """ + if "$" in value: + # The string.Template class is a string class + # for supporting $-substitutions + zt = string.Template(value) + try: + value = zt.substitute(self.environ) + except KeyError as exc: + raise src.SatException(_("Missing definition " + "in environment: %s") % str(exc)) + return value + +
[docs] def append_value(self, key, value, sep=os.pathsep): + """\ + append value to key using sep + + :param key str: the environment variable to append + :param value str: the value to append to key + :param sep str: the separator string + """ + # check if the key is already in the environment + if key in self.environ: + value_list = self.environ[key].split(sep) + # Check if the value is already in the key value or not + if not value in value_list: + value_list.append(value) + else: + value_list.append(value_list.pop(value_list.index(value))) + self.set(key, sep.join(value_list)) + else: + self.set(key, value) +
+
[docs] def append(self, key, value, sep=os.pathsep): + """\ + Same as append_value but the value argument can be a list + + :param key str: the environment variable to append + :param value str or list: the value(s) to append to key + :param sep str: the separator string + """ + if isinstance(value, list): + for v in value: + self.append_value(key, v, sep) + else: + self.append_value(key, value, sep) +
+
[docs] def prepend_value(self, key, value, sep=os.pathsep): + """\ + prepend value to key using sep + + :param key str: the environment variable to prepend + :param value str: the value to prepend to key + :param sep str: the separator string + """ + if key in self.environ: + value_list = self.environ[key].split(sep) + if not value in value_list: + value_list.insert(0, value) + else: + value_list.insert(0, value_list.pop(value_list.index(value))) + self.set(key, sep.join(value_list)) + else: + self.set(key, value) +
+
[docs] def prepend(self, key, value, sep=os.pathsep): + """\ + Same as prepend_value but the value argument can be a list + + :param key str: the environment variable to prepend + :param value str or list: the value(s) to prepend to key + :param sep str: the separator string + """ + if isinstance(value, list): + for v in value: + self.prepend_value(key, v, sep) + else: + self.prepend_value(key, value, sep) +
+
[docs] def is_defined(self, key): + """\ + Check if the key exists in the environment + + :param key str: the environment variable to check + """ + return key in self.environ.keys() +
+
[docs] def set(self, key, value): + """\ + Set the environment variable "key" to value "value" + + :param key str: the environment variable to set + :param value str: the value + """ + self.environ[key] = self._expandvars(value) +
+
[docs] def get(self, key): + """\ + Get the value of the environment variable "key" + + :param key str: the environment variable + """ + if key in self.environ: + return self.environ[key] + else: + return "" +
+
[docs] def command_value(self, key, command): + """\ + Get the value given by the system command "command" + and put it in the environment variable key + + :param key str: the environment variable + :param command str: the command to execute + """ + value = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE, + env=self.environ).communicate()[0] + self.environ[key] = value + +
+
[docs]class SalomeEnviron: + """\ + Class to manage the environment of SALOME. + """ + def __init__(self, + cfg, + environ, + forBuild=False, + for_package=None, + enable_simple_env_script = True): + """\ + Initialization. + + :param cfg Config: the global config + :param environ Environ: the Environ instance where + to store the environment variables + :param forBuild bool: If true, it is a launch environment, + else a build one + :param for_package str: If not None, produce a relative environment + designed for a package. + """ + self.environ = environ + self.cfg = cfg + self.forBuild = forBuild + self.for_package = for_package + self.enable_simple_env_script = enable_simple_env_script + self.silent = False + + def __repr__(self): + """easy almost exhaustive quick resume for debug print""" + res = { + "environ" : self.environ, + "forBuild" : self.forBuild, + "for_package" : self.for_package, + } + return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(res)) + +
[docs] def append(self, key, value, sep=os.pathsep): + """\ + append value to key using sep + + :param key str: the environment variable to append + :param value str: the value to append to key + :param sep str: the separator string + """ + return self.environ.append(key, value, sep) +
+
[docs] def prepend(self, key, value, sep=os.pathsep): + """\ + prepend value to key using sep + + :param key str: the environment variable to prepend + :param value str: the value to prepend to key + :param sep str: the separator string + """ + return self.environ.prepend(key, value, sep) +
+
[docs] def is_defined(self, key): + """\ + Check if the key exists in the environment + + :param key str: the environment variable to check + """ + return self.environ.is_defined(key) +
+
[docs] def get(self, key): + """\ + Get the value of the environment variable "key" + + :param key str: the environment variable + """ + return self.environ.get(key) +
+
[docs] def set(self, key, value): + """\ + Set the environment variable "key" to value "value" + + :param key str: the environment variable to set + :param value str: the value + """ + # check if value needs to be evaluated + if value is not None and value.startswith("`") and value.endswith("`"): + res = subprocess.Popen("echo %s" % value, + shell=True, + stdout=subprocess.PIPE).communicate() + value = res[0].strip() + + return self.environ.set(key, value) +
+
[docs] def dump(self, out): + """\ + Write the environment to out + + :param out file: the stream where to write the environment + """ + for k in self.environ.environ.keys(): + try: + value = self.get(k) + except: + value = "?" + out.write("%s=%s\n" % (k, value)) +
+
[docs] def add_line(self, nb_line): + """\ + Add empty lines to the out stream (in case of file generation) + + :param nb_line int: the number of empty lines to add + """ + if 'add_line' in dir(self.environ): + self.environ.add_line(nb_line) +
+
[docs] def add_comment(self, comment): + """\ + Add a commentary to the out stream (in case of file generation) + + :param comment str: the commentary to add + """ + if 'add_comment' in dir(self.environ): + self.environ.add_comment(comment) +
+
[docs] def add_warning(self, warning): + """\ + Add a warning to the out stream (in case of file generation) + + :param warning str: the warning to add + """ + if 'add_warning' in dir(self.environ): + self.environ.add_warning(warning) +
+
[docs] def finish(self, required): + """\ + Add a final instruction in the out file (in case of file generation) + + :param required bool: Do nothing if required is False + """ + if 'finish' in dir(self.environ): + self.environ.add_line(1) + self.environ.add_comment("clean all the path") + self.environ.finish(required) +
+
[docs] def set_python_libdirs(self): + """Set some generic variables for python library paths""" + ver = self.get('PYTHON_VERSION') + self.set('PYTHON_LIBDIR0', os.path.join('lib', + 'python' + ver, + 'site-packages')) + self.set('PYTHON_LIBDIR1', os.path.join('lib64', + 'python' + ver, + 'site-packages')) + + self.python_lib0 = self.get('PYTHON_LIBDIR0') + self.python_lib1 = self.get('PYTHON_LIBDIR1') +
+
[docs] def get_names(self, lProducts): + """\ + Get the products name to add in SALOME_MODULES environment variable + It is the name of the product, except in the case where the is a + component name. And it has to be in SALOME_MODULES variable only + if the product has the property has_salome_hui = "yes" + + :param lProducts list: List of products to potentially add + """ + lProdHasGui = [p for p in lProducts if 'properties' in + src.product.get_product_config(self.cfg, p) and + 'has_salome_gui' in + src.product.get_product_config(self.cfg, p).properties and + src.product.get_product_config(self.cfg, + p).properties.has_salome_gui=='yes'] + lProdName = [] + for ProdName in lProdHasGui: + pi = src.product.get_product_config(self.cfg, ProdName) + if 'component_name' in pi: + lProdName.append(pi.component_name) + else: + lProdName.append(ProdName) + return lProdName +
+
[docs] def set_application_env(self, logger): + """\ + Sets the environment defined in the APPLICATION file. + + :param logger Logger: The logger instance to display messages + """ + + # add variable PRODUCT_ROOT_DIR as $workdir in APPLICATION.environ section if not present + try: + tmp = self.cfg.APPLICATION.environ.PRODUCT_ROOT_DIR + except: + self.cfg.APPLICATION.environ.PRODUCT_ROOT_DIR = src.pyconf.Reference(self.cfg, src.pyconf.DOLLAR, "workdir") + DBG.write("set_application_env add default Config.APPLICATION.environ.PRODUCT_ROOT_DIR", self.cfg.APPLICATION.environ) + + # Set the variables defined in the "environ" section + if 'environ' in self.cfg.APPLICATION: + # we write PRODUCT environment it in order to conform to + # parseConfigFile.py + self.add_comment("PRODUCT environment") + self.load_cfg_environment(self.cfg.APPLICATION.environ) + if self.forBuild and "build" in self.cfg.APPLICATION.environ: + self.load_cfg_environment(self.cfg.APPLICATION.environ.build) + if not self.forBuild and "launch" in self.cfg.APPLICATION.environ: + self.load_cfg_environment(self.cfg.APPLICATION.environ.launch) + self.add_line(1) + + # If there is an "environ_script" section, load the scripts + if 'environ_script' in self.cfg.APPLICATION: + for pscript in self.cfg.APPLICATION.environ_script: + self.add_comment("script %s" % pscript) + sname = pscript.replace(" ", "_") + self.run_env_script("APPLICATION_%s" % sname, + self.cfg.APPLICATION.environ_script[pscript], + logger) + self.add_line(1) +
+
[docs] def set_salome_minimal_product_env(self, product_info, logger): + """\ + Sets the minimal environment for a SALOME product. + xxx_ROOT_DIR and xxx_SRC_DIR + + :param product_info Config: The product description + :param logger Logger: The logger instance to display messages + """ + # set root dir + DBG.write("set_salome_minimal_product_env", product_info) + root_dir = product_info.name + "_ROOT_DIR" + if not self.is_defined(root_dir): + if 'install_dir' in product_info and product_info.install_dir: + self.set(root_dir, product_info.install_dir) + elif not self.silent: + logger.write(" " + _("No install_dir for product %s\n") % + product_info.name, 5) + + source_in_package = src.get_property_in_product_cfg(product_info, + "sources_in_package") + if not self.for_package or source_in_package == "yes": + # set source dir, unless no source dir + if not src.product.product_is_fixed(product_info): + src_dir = product_info.name + "_SRC_DIR" + if not self.is_defined(src_dir): + if not self.for_package: + self.set(src_dir, product_info.source_dir) + else: + self.set(src_dir, os.path.join("out_dir_Path", + "SOURCES", + product_info.name)) +
+
[docs] def set_salome_generic_product_env(self, pi): + """\ + Sets the generic environment for a SALOME product. + + :param pi Config: The product description + """ + # Construct XXX_ROOT_DIR + env_root_dir = self.get(pi.name + "_ROOT_DIR") + l_binpath_libpath = [] + + # create additional ROOT_DIR for CPP components + if 'component_name' in pi: + compo_name = pi.component_name + if compo_name + "CPP" == pi.name: + compo_root_dir = compo_name + "_ROOT_DIR" + envcompo_root_dir = os.path.join( + self.cfg.TOOLS.common.install_root, compo_name ) + self.set(compo_root_dir , envcompo_root_dir) + bin_path = os.path.join(envcompo_root_dir, 'bin', 'salome') + lib_path = os.path.join(envcompo_root_dir, 'lib', 'salome') + l_binpath_libpath.append( (bin_path, lib_path) ) + + if src.get_property_in_product_cfg(pi, "fhs"): + lib_path = os.path.join(env_root_dir, 'lib') + pylib1_path = os.path.join(env_root_dir, self.python_lib0) + pylib2_path = os.path.join(env_root_dir, self.python_lib1) + bin_path = os.path.join(env_root_dir, 'bin') + else: + lib_path = os.path.join(env_root_dir, 'lib', 'salome') + pylib1_path = os.path.join(env_root_dir, self.python_lib0, 'salome') + pylib2_path = os.path.join(env_root_dir, self.python_lib1, 'salome') + bin_path = os.path.join(env_root_dir, 'bin', 'salome') + + # Construct the paths to prepend to PATH and LD_LIBRARY_PATH and + # PYTHONPATH + l_binpath_libpath.append( (bin_path, lib_path) ) + + for bin_path, lib_path in l_binpath_libpath: + if not self.forBuild: + self.prepend('PATH', bin_path) + if src.architecture.is_windows(): + self.prepend('PATH', lib_path) + else : + self.prepend('LD_LIBRARY_PATH', lib_path) + + l = [ bin_path, lib_path, pylib1_path, pylib2_path ] + self.prepend('PYTHONPATH', l) +
+
[docs] def set_cpp_env(self, product_info): + """\ + Sets the generic environment for a SALOME cpp product. + + :param product_info Config: The product description + """ + # Construct XXX_ROOT_DIR + env_root_dir = self.get(product_info.name + "_ROOT_DIR") + l_binpath_libpath = [] + + # Construct the paths to prepend to PATH and LD_LIBRARY_PATH and + # PYTHONPATH + bin_path = os.path.join(env_root_dir, 'bin') + lib_path = os.path.join(env_root_dir, 'lib') + l_binpath_libpath.append( (bin_path, lib_path) ) + + for bin_path, lib_path in l_binpath_libpath: + if not self.forBuild: + self.prepend('PATH', bin_path) + if src.architecture.is_windows(): + self.prepend('PATH', lib_path) + else : + self.prepend('LD_LIBRARY_PATH', lib_path) + + l = [ bin_path, lib_path, + os.path.join(env_root_dir, self.python_lib0), + os.path.join(env_root_dir, self.python_lib1) + ] + self.prepend('PYTHONPATH', l) +
+
[docs] def load_cfg_environment(self, cfg_env): + """\ + Loads environment defined in cfg_env + + :param cfg_env Config: A config containing an environment + """ + # Loop on cfg_env values + for env_def in cfg_env: + val = cfg_env[env_def] + + # if it is env_script, do not do anything (reserved keyword) + if env_def == "env_script": + continue + + # if it is a dict, do not do anything + if isinstance(val, src.pyconf.Mapping): + continue + + # if it is a list, loop on its values + if isinstance(val, src.pyconf.Sequence): + # transform into list of strings + l_val = [] + for item in val: + l_val.append(item) + val = l_val + + # "_" means that the value must be prepended + if env_def.startswith("_"): + # separator exception for PV_PLUGIN_PATH + if env_def[1:] == 'PV_PLUGIN_PATH': + self.prepend(env_def[1:], val, ';') + else: + self.prepend(env_def[1:], val) + elif env_def.endswith("_"): + # separator exception for PV_PLUGIN_PATH + if env_def[:-1] == 'PV_PLUGIN_PATH': + self.append(env_def[:-1], val, ';') + else: + self.append(env_def[:-1], val) + else: + self.set(env_def, val) +
+
[docs] def set_a_product(self, product, logger): + """\ + Sets the environment of a product. + + :param product str: The product name + :param logger Logger: The logger instance to display messages + """ + + # Get the informations corresponding to the product + pi = src.product.get_product_config(self.cfg, product) + + # skip mesa products (if any) at run time, + # unless use_mesa property was activated + if not self.forBuild: + if not ("APPLICATION" in self.cfg and + "properties" in self.cfg.APPLICATION and + "use_mesa" in self.cfg.APPLICATION.properties and + self.cfg.APPLICATION.properties.use_mesa == "yes") : + if ("properties" in pi and + "is_mesa" in pi.properties and + pi.properties.is_mesa == "yes") : + logger.write(_("Skip mesa product %s\n") % pi.name, 4) + return + + + if self.for_package: + pi.install_dir = os.path.join("out_dir_Path", + self.for_package, + pi.name) + + if not self.silent: + logger.write(_("Setting environment for %s\n") % product, 4) + + self.add_line(1) + self.add_comment('setting environ for ' + product) + + # Do not define environment if the product is native + if src.product.product_is_native(pi): + if src.product.product_has_env_script(pi): + self.run_env_script(pi, native=True) + return + + # Set an additional environment for SALOME products + if src.product.product_is_salome(pi): + # set environment using definition of the product + self.set_salome_minimal_product_env(pi, logger) + self.set_salome_generic_product_env(pi) + + if src.product.product_is_cpp(pi): + # set a specific environment for cpp modules + self.set_salome_minimal_product_env(pi, logger) + self.set_cpp_env(pi) + + if src.product.product_is_generated(pi): + if "component_name" in pi: + # hack the source and install directories in order to point + # on the generated product source install directories + install_dir_save = pi.install_dir + source_dir_save = pi.source_dir + name_save = pi.name + pi.install_dir = os.path.join(self.cfg.APPLICATION.workdir, + "INSTALL", + pi.component_name) + if self.for_package: + pi.install_dir = os.path.join("out_dir_Path", + self.for_package, + pi.component_name) + pi.source_dir = os.path.join(self.cfg.APPLICATION.workdir, + "GENERATED", + pi.component_name) + pi.name = pi.component_name + self.set_salome_minimal_product_env(pi, logger) + self.set_salome_generic_product_env(pi) + + # Put original values + pi.install_dir = install_dir_save + pi.source_dir = source_dir_save + pi.name = name_save + + # Put the environment define in the configuration of the product + if "environ" in pi: + self.load_cfg_environment(pi.environ) + if self.forBuild and "build" in pi.environ: + self.load_cfg_environment(pi.environ.build) + if not self.forBuild and "launch" in pi.environ: + self.load_cfg_environment(pi.environ.launch) + # if product_info defines a env_scripts, load it + if 'env_script' in pi.environ: + self.run_env_script(pi, logger) + + + +
+
[docs] def run_env_script(self, product_info, logger=None, native=False): + """\ + Runs an environment script. + + :param product_info Config: The product description + :param logger Logger: The logger instance to display messages + :param native Boolean: if True load set_native_env instead of set_env + """ + env_script = product_info.environ.env_script + # Check that the script exists + if not os.path.exists(env_script): + raise src.SatException(_("Environment script not found: %s") % + env_script) + + if not self.silent and logger is not None: + logger.write(" ** load %s\n" % env_script, 4) + + # import the script and run the set_env function + try: + import imp + pyproduct = imp.load_source(product_info.name + "_env_script", + env_script) + if not native: + pyproduct.set_env(self, + product_info.install_dir, + product_info.version) + else: + if "set_nativ_env" in dir(pyproduct): + pyproduct.set_nativ_env(self) + except: + __, exceptionValue, exceptionTraceback = sys.exc_info() + print(exceptionValue) + import traceback + traceback.print_tb(exceptionTraceback) + traceback.print_exc() +
+
[docs] def run_simple_env_script(self, script_path, logger=None): + """\ + Runs an environment script. Same as run_env_script, but with a + script path as parameter. + + :param script_path str: a path to an environment script + :param logger Logger: The logger instance to display messages + """ + if not self.enable_simple_env_script: + return + # Check that the script exists + if not os.path.exists(script_path): + raise src.SatException(_("Environment script not found: %s") % + script_path) + + if not self.silent and logger is not None: + logger.write(" ** load %s\n" % script_path, 4) + + script_basename = os.path.basename(script_path) + if script_basename.endswith(".py"): + script_basename = script_basename[:-len(".py")] + + # import the script and run the set_env function + try: + import imp + pyproduct = imp.load_source(script_basename + "_env_script", + script_path) + pyproduct.load_env(self) + except: + __, exceptionValue, exceptionTraceback = sys.exc_info() + print(exceptionValue) + import traceback + traceback.print_tb(exceptionTraceback) + traceback.print_exc() +
+
[docs] def set_products(self, logger, src_root=None): + """\ + Sets the environment for all the products. + + :param logger Logger: The logger instance to display messages + :param src_root src: the application working directory + """ + self.add_line(1) + self.add_comment('setting environ for all products') + + # Make sure that the python lib dirs are set after python + if "Python" in self.cfg.APPLICATION.products: + self.set_a_product("Python", logger) + self.set_python_libdirs() + + # The loop on the products + for product in self.cfg.APPLICATION.products.keys(): + if product == "Python": + continue + self.set_a_product(product, logger) + self.finish(False) +
+
[docs] def set_full_environ(self, logger, env_info): + """\ + Sets the full environment for products + specified in env_info dictionary. + + :param logger Logger: The logger instance to display messages + :param env_info list: the list of products + """ + DBG.write("set_full_environ for", env_info) + # DBG.write("set_full_environ config", self.cfg.APPLICATION.environ, True) + # set product environ + self.set_application_env(logger) + + self.set_python_libdirs() + + # set products + for product in env_info: + self.set_a_product(product, logger) +
+
[docs]class FileEnvWriter: + """\ + Class to dump the environment to a file. + """ + def __init__(self, config, logger, out_dir, src_root, env_info=None): + """\ + Initialization. + + :param cfg Config: the global config + :param logger Logger: The logger instance to display messages + :param out_dir str: The directory path where t put the output files + :param src_root str: The application working directory + :param env_info str: The list of products to add in the files. + """ + self.config = config + self.logger = logger + self.out_dir = out_dir + self.src_root= src_root + self.silent = True + self.env_info = env_info + +
[docs] def write_env_file(self, filename, forBuild, shell, for_package = None): + """\ + Create an environment file. + + :param filename str: the file path + :param forBuild bool: if true, the build environment + :param shell str: the type of file wanted (.sh, .bat) + :return: The path to the generated file + :rtype: str + """ + if not self.silent: + self.logger.write(_("Create environment file %s\n") % + src.printcolors.printcLabel(filename), 3) + + # create then env object + env_file = open(os.path.join(self.out_dir, filename), "w") + tmp = src.fileEnviron.get_file_environ(env_file, + shell, + {}) + env = SalomeEnviron(self.config, tmp, forBuild, for_package=for_package) + env.silent = self.silent + + # Set the environment + if self.env_info is not None: + env.set_full_environ(self.logger, self.env_info) + else: + # set env from the APPLICATION + env.set_application_env(self.logger) + + # The list of products to launch + lProductsName = env.get_names(self.config.APPLICATION.products.keys()) + env.set( "SALOME_MODULES", ','.join(lProductsName)) + + # set the products + env.set_products(self.logger, + src_root=self.src_root) + + # add cleanup and close + env.finish(True) + env_file.close() + + return env_file.name +
+
[docs] def write_cfgForPy_file(self, + filename, + additional_env = {}, + for_package = None, + with_commercial = True): + """\ + Append to current opened aFile a cfgForPy + environment (SALOME python launcher). + + :param filename str: the file path + :param additional_env dict: a dictionary of additional variables + to add to the environment + :param for_package str: If not None, produce a relative environment + designed for a package. + """ + if not self.silent: + self.logger.write(_("Create configuration file %s\n") % + src.printcolors.printcLabel(filename.name), 3) + + # create then env object + tmp = src.fileEnviron.get_file_environ(filename, + "cfgForPy", + {}) + # environment for launch + env = SalomeEnviron(self.config, + tmp, + forBuild=False, + for_package=for_package, + enable_simple_env_script = with_commercial) + env.silent = self.silent + + if self.env_info is not None: + env.set_full_environ(self.logger, self.env_info) + else: + # set env from PRODUCT + env.set_application_env(self.logger) + + # The list of products to launch + lProductsName = env.get_names(self.config.APPLICATION.products.keys()) + env.set( "SALOME_MODULES", ','.join(lProductsName)) + + # set the products + env.set_products(self.logger, + src_root=self.src_root) + + # Add the additional environment if it is not empty + if len(additional_env) != 0: + for variable in additional_env: + env.set(variable, additional_env[variable]) + + # add cleanup and close + env.finish(True) +
+
[docs]class Shell: + """\ + Definition of a Shell. + """ + def __init__(self, name, extension): + """\ + Initialization. + + :param name str: the shell name + :param extension str: the shell extension + """ + self.name = name + self.extension = extension +
+
[docs]def load_environment(config, build, logger): + """\ + Loads the environment (used to run the tests, for example). + + :param config Config: the global config + :param build bool: build environement if True + :param logger Logger: The logger instance to display messages + """ + environ = SalomeEnviron(config, Environ(os.environ), build) + environ.set_application_env(logger) + environ.set_products(logger) + environ.finish(True)
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/fileEnviron.html b/doc/build/html/_modules/src/fileEnviron.html new file mode 100644 index 0000000..9a087bb --- /dev/null +++ b/doc/build/html/_modules/src/fileEnviron.html @@ -0,0 +1,964 @@ + + + + + + + + + src.fileEnviron — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.fileEnviron

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+import os
+import pprint as PP
+import src.debug as DBG
+
+bat_header="""\
+@echo off
+
+rem The following variables are used only in case of a sat package
+set out_dir_Path=%~dp0
+set PRODUCT_OUT_DIR=%out_dir_Path%
+set prereq_install_Path=%out_dir_Path%\PREREQUISITES\INSTALL
+set prereq_build_Path=%out_dir_Path%\PREREQUISITES\BUILD
+"""
+
+
+bash_header="""\
+#!/bin/bash
+##########################################################################
+#
+#### cleandup ###
+# cleanup a path (first parameter) from duplicated entries;
+# second parameter is the separator
+cleandup() {
+out_var=`echo $1 | awk -v sep=$2 '{                      \\
+     na = split($1,a,sep);                               \\
+     k=0;                                                \\
+     for(i=0;i<=na;i++) {                                \\
+       found=0;                                          \\
+       for(j=0;j<k;j++) {                                \\
+         if(a[i]==aa[j])                                 \\
+         {                                               \\
+           found=1;                                      \\
+           break;                                        \\
+         };                                              \\
+       };                                                \\
+       if(found==0) {                                    \\
+         aa[k++]=a[i];                                   \\
+       };                                                \\
+     };                                                  \\
+     ORS=sep;                                            \\
+     for(i=0;i<k;i++) {                                  \\
+       print aa[i];                                      \\
+     }                                                   \\
+   }' | sed -e 's|\\(.*\\)$1|\\1|g' -e 's|^[:;]||' -e 's|[:;]$||'`
+echo $out_var
+}
+### clean ###
+clean ()
+{
+xenv=`printenv $1`
+out_var=`cleandup $xenv $2`
+export $1=$out_var
+}
+
+# The 3 following variables are used only in case of a sat package
+export out_dir_Path=$(cd $(dirname ${BASH_SOURCE[0]});pwd)
+export PRODUCT_OUT_DIR=${out_dir_Path}
+export PRODUCT_ROOT_DIR=${PRODUCT_OUT_DIR}
+
+###########################################################################
+"""
+
+cfg_header="""\
+[SALOME Configuration]
+"""
+
+Launcher_header="""\
+# a generated SALOME Configuration file using python syntax
+"""
+
+
[docs]def get_file_environ(output, shell, environ=None): + """Instantiate correct FileEnvironment sub-class. + + :param output file: the output file stream. + :param shell str: the type of shell syntax to use. + :param environ dict: a potential additional environment. + """ + if shell == "bash": + return BashFileEnviron(output, environ) + if shell == "bat": + return BatFileEnviron(output, environ) + if shell == "cfgForPy": + return LauncherFileEnviron(output, environ) + if shell == "cfg": + return ContextFileEnviron(output, environ) + raise Exception("FileEnviron: Unknown shell = %s" % shell) +
+
[docs]class FileEnviron(object): + """\ + Base class for shell environment + """ + def __init__(self, output, environ=None): + """\ + Initialization + + :param output file: the output file stream. + :param environ dict: a potential additional environment. + """ + self._do_init(output, environ) + + def __repr__(self): + """\ + easy non exhaustive quick resume for debug print""" + res = { + "output" : self.output, + "environ" : self.environ, + } + return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(res)) + + + def _do_init(self, output, environ=None): + """\ + Initialization + + :param output file: the output file stream. + :param environ dict: a potential additional environment. + """ + self.output = output + self.toclean = [] + if environ is not None: + #if str(type(environ)) == "<type 'instance'>": + if id(environ) == id(os.environ): + DBG.tofix("set %s environ as python os.environ, are you sure it is safe ?" % self.__class__.__name__, True) + self.environ = environ + else: + DBG.tofix("set %s environ as COPY of python os.environ, are you sure it is safe ?" % self.__class__.__name__, True) + self.environ = dict(os.environ) #make a copy cvw 180320 + +
[docs] def add_line(self, number): + """\ + Add some empty lines in the shell file + + :param number int: the number of lines to add + """ + self.output.write("\n" * number) +
+
[docs] def add_comment(self, comment): + """\ + Add a comment in the shell file + + :param comment str: the comment to add + """ + self.output.write("# %s\n" % comment) +
+
[docs] def add_echo(self, text): + """\ + Add a "echo" in the shell file + + :param text str: the text to echo + """ + self.output.write('echo %s"\n' % text) +
+
[docs] def add_warning(self, warning): + """\ + Add a warning "echo" in the shell file + + :param warning str: the text to echo + """ + self.output.write('echo "WARNING %s"\n' % warning) +
+
[docs] def append_value(self, key, value, sep=os.pathsep): + """\ + append value to key using sep + + :param key str: the environment variable to append + :param value str: the value to append to key + :param sep str: the separator string + """ + self.set(key, self.get(key) + sep + value) + if (key, sep) not in self.toclean: + self.toclean.append((key, sep)) +
+
[docs] def append(self, key, value, sep=os.pathsep): + """\ + Same as append_value but the value argument can be a list + + :param key str: the environment variable to append + :param value str or list: the value(s) to append to key + :param sep str: the separator string + """ + if isinstance(value, list): + self.append_value(key, sep.join(value), sep) + else: + self.append_value(key, value, sep) +
+
[docs] def prepend_value(self, key, value, sep=os.pathsep): + """\ + prepend value to key using sep + + :param key str: the environment variable to prepend + :param value str: the value to prepend to key + :param sep str: the separator string + """ + self.set(key, value + sep + self.get(key)) + if (key, sep) not in self.toclean: + self.toclean.append((key, sep)) +
+
[docs] def prepend(self, key, value, sep=os.pathsep): + """\ + Same as prepend_value but the value argument can be a list + + :param key str: the environment variable to prepend + :param value str or list: the value(s) to prepend to key + :param sep str: the separator string + """ + if isinstance(value, list): + self.prepend_value(key, sep.join(value), sep) + else: + self.prepend_value(key, value, sep) +
+
[docs] def is_defined(self, key): + """\ + Check if the key exists in the environment + + :param key str: the environment variable to check + """ + return (key in self.environ) +
+
[docs] def set(self, key, value): + """\ + Set the environment variable 'key' to value 'value' + + :param key str: the environment variable to set + :param value str: the value + """ + raise NotImplementedError("set is not implement for this shell!") +
+
[docs] def get(self, key): + """\ + Get the value of the environment variable "key" + + :param key str: the environment variable + """ + return '${%s}' % key +
+
[docs] def command_value(self, key, command): + """\ + Get the value given by the system command "command" + and put it in the environment variable key. + Has to be overwritten in the derived classes + This can be seen as a virtual method + + :param key str: the environment variable + :param command str: the command to execute + """ + raise NotImplementedError("command_value is not implement " + "for this shell!") +
+
[docs] def finish(self, required=True): + """Add a final instruction in the out file (in case of file generation) + + :param required bool: Do nothing if required is False + """ + for (key, sep) in self.toclean: + if sep != ' ': + self.output.write('clean %s "%s"\n' % (key, sep)) +
+
[docs]class BashFileEnviron(FileEnviron): + """\ + Class for bash shell. + """ + def __init__(self, output, environ=None): + """Initialization + + :param output file: the output file stream. + :param environ dict: a potential additional environment. + """ + self._do_init(output, environ) + self.output.write(bash_header) + +
[docs] def set(self, key, value): + """Set the environment variable "key" to value "value" + + :param key str: the environment variable to set + :param value str: the value + """ + self.output.write('export %s="%s"\n' % (key, value)) + self.environ[key] = value +
+
[docs] def command_value(self, key, command): + """\ + Get the value given by the system command "command" + and put it in the environment variable key. + Has to be overwritten in the derived classes + This can be seen as a virtual method + + :param key str: the environment variable + :param command str: the command to execute + """ + self.output.write('export %s=$(%s)\n' % (key, command)) +
+
[docs] def finish(self, required=True): + """Add a final instruction in the out file (in case of file generation) + + :param required bool: Do nothing if required is False + """ + if not required: + return + FileEnviron.finish(self, required) +
+
[docs]class BatFileEnviron(FileEnviron): + """\ + for Windows batch shell. + """ + def __init__(self, output, environ=None): + """Initialization + + :param output file: the output file stream. + :param environ dict: a potential additional environment. + """ + self._do_init(output, environ) + self.output.write(bat_header) + +
[docs] def add_comment(self, comment): + """Add a comment in the shell file + + :param comment str: the comment to add + """ + self.output.write("rem %s\n" % comment) +
+
[docs] def get(self, key): + """Get the value of the environment variable "key" + + :param key str: the environment variable + """ + return '%%%s%%' % key +
+
[docs] def set(self, key, value): + """Set the environment variable "key" to value "value" + + :param key str: the environment variable to set + :param value str: the value + """ + self.output.write('set %s=%s\n' % (key, value)) + self.environ[key] = value +
+
[docs] def command_value(self, key, command): + """\ + Get the value given by the system command "command" + and put it in the environment variable key. + Has to be overwritten in the derived classes + This can be seen as a virtual method + + :param key str: the environment variable + :param command str: the command to execute + """ + self.output.write('%s > tmp.txt\n' % (command)) + self.output.write('set /p %s =< tmp.txt\n' % (key)) +
+
[docs] def finish(self, required=True): + """\ + Add a final instruction in the out file (in case of file generation) + In the particular windows case, do nothing + + :param required bool: Do nothing if required is False + """ + return +
+
[docs]class ContextFileEnviron(FileEnviron): + """Class for a salome context configuration file. + """ + def __init__(self, output, environ=None): + """Initialization + + :param output file: the output file stream. + :param environ dict: a potential additional environment. + """ + self._do_init(output, environ) + self.output.write(cfg_header) + +
[docs] def set(self, key, value): + """Set the environment variable "key" to value "value" + + :param key str: the environment variable to set + :param value str: the value + """ + self.output.write('%s="%s"\n' % (key, value)) + self.environ[key] = value +
+
[docs] def get(self, key): + """Get the value of the environment variable "key" + + :param key str: the environment variable + """ + return '%({0})s'.format(key) +
+
[docs] def command_value(self, key, command): + """\ + Get the value given by the system command "command" + and put it in the environment variable key. + Has to be overwritten in the derived classes + This can be seen as a virtual method + + :param key str: the environment variable + :param command str: the command to execute + """ + raise NotImplementedError("command_value is not implement " + "for salome context files!") +
+
[docs] def add_echo(self, text): + """Add a comment + + :param text str: the comment to add + """ + self.add_comment(text) +
+
[docs] def add_warning(self, warning): + """Add a warning + + :param text str: the warning to add + """ + self.add_comment("WARNING %s" % warning) +
+
[docs] def prepend_value(self, key, value, sep=os.pathsep): + """prepend value to key using sep + + :param key str: the environment variable to prepend + :param value str: the value to prepend to key + :param sep str: the separator string + """ + self.output.write('ADD_TO_%s: %s\n' % (key, value)) +
+
[docs] def append_value(self, key, value, sep=os.pathsep): + """append value to key using sep + + :param key str: the environment variable to append + :param value str: the value to append to key + :param sep str: the separator string + """ + self.prepend_value(key, value) +
+
[docs] def finish(self, required=True): + """Add a final instruction in the out file (in case of file generation) + + :param required bool: Do nothing if required is False + """ + return +
+
[docs]def special_path_separator(name): + """\ + TCLLIBPATH, TKLIBPATH, PV_PLUGIN_PATH environments variables need + some exotic path separator. + This function gives the separator regarding the name of the variable + to append or prepend. + + :param name str: The name of the variable to find the separator + """ + special_blanks_keys=["TCLLIBPATH", "TKLIBPATH"] + special_semicolon_keys=["PV_PLUGIN_PATH"] + res=os.pathsep + if name in special_blanks_keys: res=" " + if name in special_semicolon_keys: res=";" + return res +
+
[docs]class LauncherFileEnviron: + """\ + Class to generate a launcher file script + (in python syntax) SalomeContext API + """ + def __init__(self, output, environ=None): + """Initialization + + :param output file: the output file stream. + :param environ dict: a potential additional environment. + """ + self.output = output + self.toclean = [] + if environ is not None: + self.environ = environ + else: + self.environ = os.environ + # Initialize some variables + if not "PATH" in self.environ.keys(): + self.environ["PATH"]="" + if not "LD_LIBRARY_PATH" in self.environ.keys(): + self.environ["LD_LIBRARY_PATH"]="" + if not "PYTHONPATH" in self.environ.keys(): + self.environ["PYTHONPATH"]="" + if not "TCLLIBPATH" in self.environ.keys(): + self.environ["TCLLIBPATH"]="" + if not "TKLIBPATH" in self.environ.keys(): + self.environ["TKLIBPATH"]="" + + # four whitespaces for first indentation in a python script + self.indent=" " + self.prefix="context." + self.setVarEnv="setVariable" + + self.begin=self.indent+self.prefix + self.output.write(Launcher_header) + self.specialKeys={"PATH": "Path", + "LD_LIBRARY_PATH": "LdLibraryPath", + "PYTHONPATH": "PythonPath"} + +
[docs] def change_to_launcher(self, value): + res=value + return res +
+
[docs] def add_line(self, number): + """Add some empty lines in the launcher file + + :param number int: the number of lines to add + """ + self.output.write("\n" * number) +
+
[docs] def add_echo(self, text): + """Add a comment + + :param text str: the comment to add + """ + self.output.write('# %s"\n' % text) +
+
[docs] def add_warning(self, warning): + """Add a warning + + :param text str: the warning to add + """ + self.output.write('# "WARNING %s"\n' % warning) +
+
[docs] def append_value(self, key, value, sep=":"): + """append value to key using sep + + :param key str: the environment variable to append + :param value str: the value to append to key + :param sep str: the separator string + """ + if self.is_defined(key) : + self.add(key, value) + else : + self.set(key, value) +
+
[docs] def append(self, key, value, sep=":"): + """Same as append_value but the value argument can be a list + + :param key str: the environment variable to append + :param value str or list: the value(s) to append to key + :param sep str: the separator string + """ + if isinstance(value, list): + self.append_value(key, sep.join(value), sep) + else: + self.append_value(key, value, sep) +
+
[docs] def prepend_value(self, key, value, sep=":"): + """prepend value to key using sep + + :param key str: the environment variable to prepend + :param value str: the value to prepend to key + :param sep str: the separator string + """ + if self.is_defined(key) : + self.add(key, value) + else : + self.set(key, value) +
+
[docs] def prepend(self, key, value, sep=":"): + """Same as prepend_value but the value argument can be a list + + :param key str: the environment variable to prepend + :param value str or list: the value(s) to prepend to key + :param sep str: the separator string + """ + if isinstance(value, list): + self.prepend_value(key, sep.join(value), sep) + else: + self.prepend_value(key, value, sep) +
+
[docs] def is_defined(self, key): + """Check if the key exists in the environment + + :param key str: the environment variable to check + """ + return key in self.environ.keys() +
+
[docs] def get(self, key): + """Get the value of the environment variable "key" + + :param key str: the environment variable + """ + return '${%s}' % key +
+
[docs] def set(self, key, value): + """Set the environment variable "key" to value "value" + + :param key str: the environment variable to set + :param value str: the value + """ + self.output.write(self.begin+self.setVarEnv+ + '(r"%s", r"%s", overwrite=True)\n' % + (key, self.change_to_launcher(value))) + self.environ[key] = value +
+
[docs] def add(self, key, value): + """prepend value to key using sep + + :param key str: the environment variable to prepend + :param value str: the value to prepend to key + """ + if key in self.specialKeys.keys(): + self.output.write(self.begin+'addTo%s(r"%s")\n' % + (self.specialKeys[key], + self.change_to_launcher(value))) + self.environ[key]+=":"+value + return + sep=special_path_separator(key) + self.output.write(self.indent+ + '#temporary solution!!! have to be defined in API a ' + '?dangerous? addToSpecial(r"%s", r"%s")\n' % + (key, value)) + #pathsep not precised because do not know future os launch? + self.output.write(self.begin+'addToSpecial(r"%s", r"%s")\n' + % (key, self.change_to_launcher(value))) + self.environ[key]+=sep+value #here yes we know os for current execution +
+
[docs] def command_value(self, key, command): + """\ + Get the value given by the system command "command" + and put it in the environment variable key. + + :param key str: the environment variable + :param command str: the command to execute + """ + self.output.write(self.indent+'#`%s`\n' % command) + + import shlex, subprocess + args = shlex.split(command) + res=subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, __ = res.communicate() + self.output.write(self.begin+ + self.setVarEnv+ + '(r"%s", r"%s", overwrite=True)\n' % (key, out)) +
+
[docs] def add_comment(self, comment): + # Special comment in case of the distène licence + if comment=="DISTENE license": + self.output.write(self.indent+ + "#"+ + self.prefix+ + self.setVarEnv+ + '(r"%s", r"%s", overwrite=True)\n' % + ('DISTENE_LICENSE_FILE', + self.change_to_launcher( + 'Use global envvar: DLIM8VAR'))) + self.output.write(self.indent+ + "#"+ + self.prefix+ + self.setVarEnv+ + '(r"%s", r"%s", overwrite=True)\n' % + ('DLIM8VAR', + self.change_to_launcher( + '<your licence>'))) + return + if "setting environ for" in comment: + self.output.write(self.indent+"#[%s]\n" % + comment.split("setting environ for ")[1]) + return + + self.output.write(self.indent+"# %s\n" % comment) +
+
[docs] def finish(self, required=True): + """\ + Add a final instruction in the out file (in case of file generation) + In the particular launcher case, do nothing + + :param required bool: Do nothing if required is False + """ + return +
+
[docs]class ScreenEnviron(FileEnviron): + def __init__(self, output, environ=None): + self._do_init(output, environ) + self.defined = {} + +
[docs] def add_line(self, number): + pass +
+
[docs] def add_comment(self, comment): + pass +
+
[docs] def add_echo(self, text): + pass +
+
[docs] def add_warning(self, warning): + pass +
+
[docs] def write(self, command, name, value, sign="="): + import src + self.output.write(" %s%s %s %s %s\n" % \ + (src.printcolors.printcLabel(command), + " " * (12 - len(command)), + src.printcolors.printcInfo(name), sign, value)) +
+
[docs] def is_defined(self, name): + return self.defined.has_key(name) +
+
[docs] def get(self, name): + return "${%s}" % name +
+
[docs] def set(self, name, value): + self.write("set", name, value) + self.defined[name] = value +
+
[docs] def prepend(self, name, value, sep=":"): + if isinstance(value, list): + value = sep.join(value) + value = value + sep + self.get(name) + self.write("prepend", name, value) +
+
[docs] def append(self, name, value, sep=":"): + if isinstance(value, list): + value = sep.join(value) + value = self.get(name) + sep + value + self.write("append", name, value) +
+
[docs] def command_value(self, key, command): + pass +
+
[docs] def run_env_script(self, module, script): + self.write("load", script, "", sign="") + +# The SALOME launcher template
+withProfile = """\ + #! /usr/bin/env python + +################################################################ +# WARNING: this file is automatically generated by SalomeTools # +# WARNING: and so could be overwritten at any time. # +################################################################ + +import os +import sys +import subprocess + + +# Add the pwdPath to able to run the launcher after unpacking a package +# Used only in case of a salomeTools package +out_dir_Path=os.path.abspath(os.path.dirname(__file__)) + +# Preliminary work to initialize path to SALOME Python modules +def __initialize(): + + sys.path[:0] = [ 'BIN_KERNEL_INSTALL_DIR' ] + os.environ['ABSOLUTE_APPLI_PATH'] = 'KERNEL_INSTALL_DIR' + + # define folder to store omniorb config (initially in virtual application folder) + try: + from salomeContextUtils import setOmniOrbUserPath + setOmniOrbUserPath() + except Exception, e: + print e + sys.exit(1) +# End of preliminary work + +# salome doc only works for virtual applications. Therefore we overwrite it with this function +def _showDoc(modules): + for module in modules: + modulePath = os.getenv(module+"_ROOT_DIR") + if modulePath != None: + baseDir = os.path.join(modulePath, "share", "doc", "salome") + docfile = os.path.join(baseDir, "gui", module.upper(), "index.html") + if not os.path.isfile(docfile): + docfile = os.path.join(baseDir, "tui", module.upper(), "index.html") + if not os.path.isfile(docfile): + docfile = os.path.join(baseDir, "dev", module.upper(), "index.html") + if os.path.isfile(docfile): + out, err = subprocess.Popen(["xdg-open", docfile]).communicate() + else: + print "Online documentation is not accessible for module:", module + else: + print module+"_ROOT_DIR not found!" + +def main(args): + # Identify application path then locate configuration files + __initialize() + + if args == ['--help']: + from salomeContext import usage + usage() + sys.exit(0) + + #from salomeContextUtils import getConfigFileNames + #configFileNames, args, unexisting = getConfigFileNames( args, checkExistence=True ) + #if len(unexisting) > 0: + # print "ERROR: unexisting configuration file(s): " + ', '.join(unexisting) + # sys.exit(1) + + # Create a SalomeContext which parses configFileNames to initialize environment + try: + from salomeContext import SalomeContext, SalomeContextException + SalomeContext.addToSpecial=addToSpecial + context = SalomeContext(None) + + # Here set specific variables, if needed + # context.addToPath('mypath') + # context.addToLdLibraryPath('myldlibrarypath') + # context.addToPythonPath('mypythonpath') + # context.setVariable('myvarname', 'value') + + # Logger level error + context.getLogger().setLevel(40) + + context.setVariable(r"PRODUCT_ROOT_DIR", out_dir_Path, overwrite=True) + # here your local standalone environment + + if len(args) >1 and args[0]=='doc': + _showDoc(args[1:]) + return + + # Start SALOME, parsing command line arguments + context.runSalome(args) + #print 'Thank you for using SALOME!' + + # Logger level info + context.getLogger().setLevel(20) + + except SalomeContextException, e: + import logging + logging.getLogger("salome").error(e) + sys.exit(1) +# +def addToSpecial(self, name, value, pathSep=None): + # add special dangerous cases: TCLLIBPATH PV_PLUGIN_PATH etc... + # http://computer-programming-forum.com/57-tcl/1dfddc136afccb94.htm + # TCLLIBPATH: Tcl treats the contents of that variable as a list. Be happy, for you can now use drive letters on windows. + if value == '': + return + + specialBlanksKeys=["TCLLIBPATH", "TKLIBPATH"] + specialSemicolonKeys=["PV_PLUGIN_PATH"] + res=os.pathsep + if name in specialBlanksKeys: res=" " + if name in specialSemicolonKeys: res=";" + + if pathSep==None: + sep=res + else: + sep=pathSep + value = os.path.expandvars(value) # expand environment variables + self.getLogger().debug("Add to %s: %s", name, value) + env = os.getenv(name, None) + if env is None: + os.environ[name] = value + else: + os.environ[name] = value + sep + env #explicitely or not special path separator ?whitespace, semicolon? + +if __name__ == "__main__": + args = sys.argv[1:] + main(args) +# +""" + +
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/fork.html b/doc/build/html/_modules/src/fork.html new file mode 100644 index 0000000..890c570 --- /dev/null +++ b/doc/build/html/_modules/src/fork.html @@ -0,0 +1,256 @@ + + + + + + + + + src.fork — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.fork

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+import os
+import sys
+import time
+import pickle
+import subprocess
+
+
[docs]def show_progress(logger, top, delai, ss=""): + """shortcut function to display the progression + + :param logger Logger: The logging instance + :param top int: the number to display + :param delai int: the number max + :param ss str: the string to display + """ + logger.write("\r%s\r%s %s / %s " % ((" " * 30), ss, top, (delai - top)), 4, + False) + logger.flush() +
+
[docs]def write_back(logger, message, level): + """shortcut function to write at the begin of the line + + :param logger Logger: The logging instance + :param message str: the text to display + :param level int: the level of verbosity + """ + logger.write("\r%s\r%s" % ((" " * 40), message), level) + +# Launch command +# --------------
+
[docs]def launch_command(cmd, logger, cwd, args=[], log=None): + if log: + log = file(log, "a") + logger.write("launch: %s\n" % cmd, 5, screenOnly=True) + for arg in args: + cmd += " " + arg + prs = subprocess.Popen(cmd, + shell=True, + stdout=log, + stderr=subprocess.STDOUT, + cwd=cwd, + executable='/bin/bash') + return prs + +# Launch a batch +# --------------
+
[docs]def batch(cmd, logger, cwd, args=[], log=None, delai=20, sommeil=1): + proc = launch_command(cmd, logger, cwd, args, log) + top = 0 + sys.stdout.softspace = True + begin = time.time() + while proc.poll() is None: + if time.time() - begin >= 1: + show_progress(logger, top, delai, "batch:") + if top == delai: + logger.write("batch: time out KILL\n", 3) + import signal + os.kill(proc.pid, signal.SIGTERM) + break + else: + begin = time.time() + time.sleep(sommeil) + top += 1 + sys.stdout.flush() + else: + write_back(logger, "batch: exit (%s)\n" % str(proc.returncode), 5) + return (proc.returncode == 0), top + +# Launch a salome process +# -----------------------
+
[docs]def batch_salome(cmd, logger, cwd, args, getTmpDir, + pendant="SALOME_Session_Server", fin="killSalome.py", + log=None, delai=20, sommeil=1, delaiapp=0): + + beginTime = time.time() + launch_command(cmd, logger, cwd, args, log) + + if delaiapp == 0: + delaiapp = delai + + # first launch salome (looking for .pidict file) + top = 0 + found = False + tmp_dir = getTmpDir() + while (not found and top < delaiapp): + if os.path.exists(tmp_dir): + listFile = os.listdir(tmp_dir) + else: + listFile = [] + + for file_name in listFile: + if file_name.endswith("pidict"): + # sometime we get a old file that will be removed by runSalome. + # So we test that we can read it. + currentTime = None + try: + statinfo = os.stat(os.path.join(tmp_dir, file_name)) + currentTime = statinfo.st_mtime + except: pass + + if currentTime and currentTime > beginTime: + try: + file_ = open(os.path.join(tmp_dir, file_name), "r") + process_ids = pickle.load(file_) + file_.close() + for process_id in process_ids: + for __, cmd in process_id.items(): + if cmd == [pendant]: + found = True + pidictFile = file_name + except: + file_.close() + + time.sleep(sommeil) + top += 1 + show_progress(logger, top, delaiapp, "launching salome or appli:") + + # continue or not + if found: + write_back(logger, "batch_salome: started\n", 5) + else: + logger.write("batch_salome: FAILED to launch salome or appli\n", 3) + return False, -1 + + # salome launched run the script + top = 0 + code = None + while code is None: + show_progress(logger, top, delai, "running salome or appli:") + + if not os.access(os.path.join(tmp_dir, pidictFile), os.F_OK): + write_back(logger, "batch_salome: exit\n", 5) + code = True + elif top >= delai: + # timeout kill the test + os.system(fin) + logger.write("batch_salome: time out KILL\n", 3) + code = False + else: + # still waiting + time.sleep(sommeil) + top = top + 1 + + return code, top
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/logger.html b/doc/build/html/_modules/src/logger.html new file mode 100644 index 0000000..3521621 --- /dev/null +++ b/doc/build/html/_modules/src/logger.html @@ -0,0 +1,506 @@ + + + + + + + + + src.logger — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.logger

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2012  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+"""\
+Implements the classes and method relative to the logging
+"""
+
+import sys
+import os
+import datetime
+import re
+import tempfile
+
+import src
+from . import printcolors
+from . import xmlManager
+
+log_macro_command_file_expression = "^[0-9]{8}_+[0-9]{6}_+.*\.xml$"
+log_all_command_file_expression = "^.*[0-9]{8}_+[0-9]{6}_+.*\.xml$"
+
+
[docs]class Logger(object): + """\ + Class to handle log mechanism. + """ + def __init__(self, + config, + silent_sysstd=False, + all_in_terminal=False, + micro_command = False): + """Initialization + + :param config pyconf.Config: The global configuration. + :param silent_sysstd boolean: if True, do not write anything + in terminal. + """ + self.config = config + self.default_level = 3 + self.silentSysStd = silent_sysstd + + # Construct xml log file location for sat prints. + prefix = "" + if micro_command: + prefix = "micro_" + hour_command_host = (config.VARS.datehour + "_" + + config.VARS.command + "_" + + config.VARS.hostname) + logFileName = prefix + hour_command_host + ".xml" + log_dir = src.get_log_path(config) + logFilePath = os.path.join(log_dir, logFileName) + # Construct txt file location in order to log + # the external commands calls (cmake, make, git clone, etc...) + txtFileName = prefix + hour_command_host + ".txt" + txtFilePath = os.path.join(log_dir, "OUT", txtFileName) + + src.ensure_path_exists(os.path.dirname(logFilePath)) + src.ensure_path_exists(os.path.dirname(txtFilePath)) + + # The path of the log files (one for sat traces, and the other for + # the system commands traces) + self.logFileName = logFileName + self.logFilePath = logFilePath + self.txtFileName = txtFileName + self.txtFilePath = txtFilePath + + # The list of all log files corresponding to the current command and + # the commands called by the current command + self.l_logFiles = [logFilePath, txtFilePath] + + # Initialize xml instance and put first fields + # like beginTime, user, command, etc... + self.xmlFile = xmlManager.XmlLogFile(logFilePath, "SATcommand", + attrib = {"application" : config.VARS.application}) + self.put_initial_xml_fields() + # Initialize the txt file for reading + try: + self.logTxtFile = open(str(self.txtFilePath), 'w') + except IOError: + #msg1 = _("WARNING! Trying to write to a file that" + # " is not accessible:") + #msg2 = _("The logs won't be written.") + #print("%s\n%s\n%s\n" % (src.printcolors.printcWarning(msg1), + # src.printcolors.printcLabel(str(self.txtFilePath)), + # src.printcolors.printcWarning(msg2) )) + self.logTxtFile = tempfile.TemporaryFile() + + # If the option all_in_terminal was called, all the system commands + # are redirected to the terminal + if all_in_terminal: + self.logTxtFile = sys.__stdout__ + +
[docs] def put_initial_xml_fields(self): + """\ + Called at class initialization: Put all fields + corresponding to the command context (user, time, ...) + """ + # command name + self.xmlFile.add_simple_node("Site", attrib={"command" : + self.config.VARS.command}) + # version of salomeTools + self.xmlFile.append_node_attrib("Site", attrib={"satversion" : + self.config.INTERNAL.sat_version}) + # machine name on which the command has been launched + self.xmlFile.append_node_attrib("Site", attrib={"hostname" : + self.config.VARS.hostname}) + # Distribution of the machine + self.xmlFile.append_node_attrib("Site", attrib={"OS" : + self.config.VARS.dist}) + # The user that have launched the command + self.xmlFile.append_node_attrib("Site", attrib={"user" : + self.config.VARS.user}) + # The time when command was launched + Y, m, dd, H, M, S = date_to_datetime(self.config.VARS.datehour) + date_hour = "%2s/%2s/%4s %2sh%2sm%2ss" % (dd, m, Y, H, M, S) + self.xmlFile.append_node_attrib("Site", attrib={"beginTime" : + date_hour}) + # The application if any + if "APPLICATION" in self.config: + self.xmlFile.append_node_attrib("Site", + attrib={"application" : self.config.VARS.application}) + # The initialization of the trace node + self.xmlFile.add_simple_node("Log",text="") + # The system commands logs + self.xmlFile.add_simple_node("OutLog", + text=os.path.join("OUT", self.txtFileName)) + # The initialization of the node where + # to put the links to the other sat commands that can be called by any + # command + self.xmlFile.add_simple_node("Links") +
+ +
[docs] def write(self, message, level=None, screenOnly=False): + """\ + function used in the commands + to print in the terminal and the log file. + + :param message str: The message to print. + :param level int: The output level corresponding + to the message 0 < level < 6. + :param screenOnly boolean: if True, do not write in log file. + """ + # do not write message starting with \r to log file + if not message.startswith("\r") and not screenOnly: + self.xmlFile.append_node_text("Log", + printcolors.cleancolor(message)) + + # get user or option output level + current_output_verbose_level = self.config.USER.output_verbose_level + if not ('isatty' in dir(sys.stdout) and sys.stdout.isatty()): + # clean the message color if the terminal is redirected by user + # ex: sat compile appli > log.txt + message = printcolors.cleancolor(message) + + # Print message regarding the output level value + if level: + if level <= current_output_verbose_level and not self.silentSysStd: + sys.stdout.write(message) + else: + if self.default_level <= current_output_verbose_level and not self.silentSysStd: + sys.stdout.write(message) + self.flush() +
+
[docs] def error(self, message): + """Print an error. + + :param message str: The message to print. + """ + # Print in the log file + self.xmlFile.append_node_text("traces", _('ERROR:') + message) + + # Print in the terminal and clean colors if the terminal + # is redirected by user + if not ('isatty' in dir(sys.stderr) and sys.stderr.isatty()): + sys.stderr.write(printcolors.printcError(_('ERROR:') + message)) + else: + sys.stderr.write(_('ERROR:') + message) +
+
[docs] def flush(self): + """Flush terminal""" + sys.stdout.flush() + self.logTxtFile.flush() +
+
[docs] def end_write(self, attribute): + """\ + Called just after command end: Put all fields + corresponding to the command end context (time). + Write the log xml file on the hard drive. + And display the command to launch to get the log + + :param attribute dict: the attribute to add to the node "Site". + """ + # Get current time (end of command) and format it + dt = datetime.datetime.now() + Y, m, dd, H, M, S = date_to_datetime(self.config.VARS.datehour) + t0 = datetime.datetime(int(Y), int(m), int(dd), int(H), int(M), int(S)) + tf = dt + delta = tf - t0 + total_time = timedelta_total_seconds(delta) + hours = int(total_time / 3600) + minutes = int((total_time - hours*3600) / 60) + seconds = total_time - hours*3600 - minutes*60 + # Add the fields corresponding to the end time + # and the total time of command + endtime = dt.strftime('%Y/%m/%d %Hh%Mm%Ss') + self.xmlFile.append_node_attrib("Site", attrib={"endTime" : endtime}) + self.xmlFile.append_node_attrib("Site", + attrib={"TotalTime" : "%ih%im%is" % (hours, minutes, seconds)}) + + # Add the attribute passed to the method + self.xmlFile.append_node_attrib("Site", attrib=attribute) + + # Call the method to write the xml file on the hard drive + self.xmlFile.write_tree(stylesheet = "command.xsl") + + # Dump the config in a pyconf file in the log directory + logDir = src.get_log_path(self.config) + dumpedPyconfFileName = (self.config.VARS.datehour + + "_" + + self.config.VARS.command + + ".pyconf") + dumpedPyconfFilePath = os.path.join(logDir, 'OUT', dumpedPyconfFileName) + try: + f = open(dumpedPyconfFilePath, 'w') + self.config.__save__(f) + f.close() + except IOError: + pass +
+
[docs]def date_to_datetime(date): + """\ + From a string date in format YYYYMMDD_HHMMSS + returns list year, mon, day, hour, minutes, seconds + + :param date str: The date in format YYYYMMDD_HHMMSS + :return: the same date and time in separate variables. + :rtype: (str,str,str,str,str,str) + """ + Y = date[:4] + m = date[4:6] + dd = date[6:8] + H = date[9:11] + M = date[11:13] + S = date[13:15] + return Y, m, dd, H, M, S +
+
[docs]def timedelta_total_seconds(timedelta): + """\ + Replace total_seconds from datetime module + in order to be compatible with old python versions + + :param timedelta datetime.timedelta: The delta between two dates + :return: The number of seconds corresponding to timedelta. + :rtype: float + """ + return ( + timedelta.microseconds + 0.0 + + (timedelta.seconds + timedelta.days * 24 * 3600) * 10 ** 6) / 10 ** 6 +
+
[docs]def show_command_log(logFilePath, cmd, application, notShownCommands): + """\ + Used in updateHatXml. + Determine if the log xml file logFilePath + has to be shown or not in the hat log. + + :param logFilePath str: the path to the command xml log file + :param cmd str: the command of the log file + :param application str: the application passed as parameter + to the salomeTools command + :param notShownCommands list: the list of commands + that are not shown by default + + :return: True if cmd is not in notShownCommands and the application + in the log file corresponds to application + :rtype: boolean + """ + # When the command is not in notShownCommands, no need to go further : + # Do not show + if cmd in notShownCommands: + return False, None, None + + # Get the application of the log file + try: + logFileXml = src.xmlManager.ReadXmlFile(logFilePath) + except Exception as e: + msg = _("WARNING: the log file %s cannot be read:" % logFilePath) + sys.stdout.write(printcolors.printcWarning("%s\n%s\n" % (msg, e))) + return False, None, None + + if 'application' in logFileXml.xmlroot.keys(): + appliLog = logFileXml.xmlroot.get('application') + launched_cmd = logFileXml.xmlroot.find('Site').attrib['launchedCommand'] + # if it corresponds, then the log has to be shown + if appliLog == application: + return True, appliLog, launched_cmd + elif application != 'None': + return False, appliLog, launched_cmd + + return True, appliLog, launched_cmd + + if application == 'None': + return True, None, None + + return False, None, None +
+
[docs]def list_log_file(dirPath, expression): + """Find all files corresponding to expression in dirPath + + :param dirPath str: the directory where to search the files + :param expression str: the regular expression of files to find + :return: the list of files path and informations about it + :rtype: list + """ + lRes = [] + for fileName in os.listdir(dirPath): + # YYYYMMDD_HHMMSS_namecmd.xml + sExpr = expression + oExpr = re.compile(sExpr) + if oExpr.search(fileName): + file_name = fileName + if fileName.startswith("micro_"): + file_name = fileName[len("micro_"):] + # get date and hour and format it + date_hour_cmd_host = file_name.split('_') + date_not_formated = date_hour_cmd_host[0] + date = "%s/%s/%s" % (date_not_formated[6:8], + date_not_formated[4:6], + date_not_formated[0:4]) + hour_not_formated = date_hour_cmd_host[1] + hour = "%s:%s:%s" % (hour_not_formated[0:2], + hour_not_formated[2:4], + hour_not_formated[4:6]) + if len(date_hour_cmd_host) < 4: + cmd = date_hour_cmd_host[2][:-len('.xml')] + host = "" + else: + cmd = date_hour_cmd_host[2] + host = date_hour_cmd_host[3][:-len('.xml')] + lRes.append((os.path.join(dirPath, fileName), + date_not_formated, + date, + hour_not_formated, + hour, + cmd, + host)) + return lRes +
+
[docs]def update_hat_xml(logDir, application=None, notShownCommands = []): + """\ + Create the xml file in logDir that contain all the xml file + and have a name like YYYYMMDD_HHMMSS_namecmd.xml + + :param logDir str: the directory to parse + :param application str: the name of the application if there is any + """ + # Create an instance of XmlLogFile class to create hat.xml file + xmlHatFilePath = os.path.join(logDir, 'hat.xml') + xmlHat = src.xmlManager.XmlLogFile(xmlHatFilePath, + "LOGlist", {"application" : application}) + # parse the log directory to find all the command logs, + # then add it to the xml file + lLogFile = list_log_file(logDir, log_macro_command_file_expression) + for filePath, __, date, __, hour, cmd, __ in lLogFile: + showLog, cmdAppli, full_cmd = show_command_log(filePath, cmd, + application, notShownCommands) + #if cmd not in notShownCommands: + if showLog: + # add a node to the hat.xml file + xmlHat.add_simple_node("LogCommand", + text=os.path.basename(filePath), + attrib = {"date" : date, + "hour" : hour, + "cmd" : cmd, + "application" : cmdAppli, + "full_command" : full_cmd}) + + # Write the file on the hard drive + xmlHat.write_tree('hat.xsl')
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/options.html b/doc/build/html/_modules/src/options.html new file mode 100644 index 0000000..3b43764 --- /dev/null +++ b/doc/build/html/_modules/src/options.html @@ -0,0 +1,290 @@ + + + + + + + + + src.options — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.options

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+'''The Options class that manages the access to all options passed as 
+   parameters in salomeTools command lines
+'''
+import getopt
+import sys
+from . import printcolors
+
+
[docs]class OptResult(object): + '''An instance of this class will be the object manipulated + in code of all salomeTools commands + The aim of this class is to have an elegant syntax + to manipulate the options. + ex: + print(options.level) + 5 + ''' + def __init__(self): + '''Initialization + ''' + self.__dict__ = dict() + + def __getattr__(self, name): + '''Overwrite of the __getattr__ function + to customize it for option usage + + :param name str: The attribute to get the value. + :return: the value corresponding to the attribute. + :rtype: str,int,list,boolean + ''' + if name in self.__dict__: + return self.__dict__[name] + else: + raise AttributeError(name + _(u" is not a valid option")) + + def __setattr__(self, name, value): + '''Overwrite of the __setattr__ function + to customize it for option usage + + :param name str: The attribute to set. + :param value str: The value corresponding to the attribute. + :return: Nothing. + :rtype: N\A + ''' + object.__setattr__(self,name,value) +
+
[docs]class Options: + '''Class to manage all salomeTools options + ''' + def __init__(self): + '''Initialization + ''' + # The options field stocks all options of a command + # in a list that contains dicts + self.options = [] + # The list of available option type + self.availableOptions = ["boolean", "string", "int", "float", + "long", "list", "list2"] + self.default = None + +
[docs] def add_option(self, shortName, longName, + optionType, destName, helpString="", default = None): + '''Method to add an option to a command. It gets all attributes + of an option and append it in the options field + + :param shortName str: The short name of the option + (ex "l" for level option). + :param longName str: The long name of the option + (ex "level" for level option). + :param optionType str: The type of the option (ex "int"). + :param destName str: The name that will be used in the code. + :param helpString str: The text to display + when user ask for help on a command. + :return: Nothing. + :rtype: N\A + ''' + option = dict() + option['shortName'] = shortName + option['longName'] = longName + + if optionType not in self.availableOptions: + print("error optionType", optionType, "not available.") + sys.exit(-1) + + option['optionType'] = optionType + option['destName'] = destName + option['helpString'] = helpString + option['result'] = default + self.options.append(option) +
+
[docs] def print_help(self): + '''Method that display all options stored in self.options and there help + + :return: Nothing. + :rtype: N\A + ''' + # Do nothing if there are no options + if len(self.options) == 0: + return + + # for all options, print its values. + # "shortname" is an optional field of the options + print(printcolors.printcHeader(_("Available options are:"))) + for option in self.options: + if 'shortName' in option and len(option['shortName']) > 0: + print(" -%(shortName)1s, --%(longName)s" + " (%(optionType)s)\n\t%(helpString)s\n" % option) + else: + print(" --%(longName)s (%(optionType)s)\n\t%(helpString)s\n" + % option) +
+
[docs] def parse_args(self, argList=None): + '''Method that instantiates the class OptResult + that gives access to all options in the code + + :param argList list: the raw list of arguments that were passed + :return: optResult, args : optResult is the option instance + to manipulate in the code. args + is the full raw list of passed options + :rtype: (class 'common.options.OptResult',list) + ''' + if argList is None: + argList = sys.argv[1:] + + # format shortNameOption and longNameOption + # to make right arguments to getopt.getopt function + shortNameOption = "" + longNameOption = [] + for option in self.options: + shortNameOption = shortNameOption + option['shortName'] + if option['shortName'] != "" and option['optionType'] != "boolean": + shortNameOption = shortNameOption + ":" + + if option['longName'] != "": + if option['optionType'] != "boolean": + longNameOption.append(option['longName'] + "=") + else: + longNameOption.append(option['longName']) + + # call to getopt.getopt function to get the option + # passed in the command regarding the available options + optlist, args = getopt.getopt(argList, shortNameOption, longNameOption) + + # instantiate and completing the optResult that will be returned + optResult = OptResult() + for option in self.options: + shortOption = "-" + option['shortName'] + longOption = "--" + option['longName'] + optionType = option['optionType'] + for opt in optlist: + if opt[0] in [shortOption, longOption]: + if optionType == "string": + option['result'] = opt[1] + elif optionType == "boolean": + option['result'] = True + elif optionType == "int": + option['result'] = int(opt[1]) + elif optionType == "float": + option['result'] = float(opt[1]) + elif optionType == "long": + option['result'] = long(opt[1]) + elif optionType == "list": + if option['result'] is None: + option['result'] = list() + option['result'].append(opt[1]) + elif optionType == "list2": + if option['result'] is None: + option['result'] = list() + if opt[1].find(",") == -1: + option['result'].append(opt[1]) + else: + elts = filter(lambda l: len(l) > 0, opt[1].split(",")) + option['result'].extend(elts) + + optResult.__setattr__(option['destName'], option['result']) + # free the option in order to be able to make + # a new free call of options (API case) + option['result'] = None + return optResult, args +
+ +
+
+ +
+
+
+

Related Topics

+ +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/printcolors.html b/doc/build/html/_modules/src/printcolors.html new file mode 100644 index 0000000..1e82e1d --- /dev/null +++ b/doc/build/html/_modules/src/printcolors.html @@ -0,0 +1,278 @@ + + + + + + + + + src.printcolors — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.printcolors

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+'''In this file is stored the mechanism that manage color prints in the terminal
+'''
+
+# define constant to use in scripts
+COLOR_ERROR = 'ERROR'
+COLOR_WARNING = 'WARNING'
+COLOR_SUCCESS = 'SUCCESS'
+COLOR_LABEL = 'LABEL'
+COLOR_HEADER = 'HEADER'
+COLOR_INFO = 'INFO'
+COLOR_HIGLIGHT = 'HIGHLIGHT'
+
+# the color map to use to print the colors
+__colormap__ = {
+    COLOR_ERROR: '\033[1m\033[31m',
+    COLOR_SUCCESS: '\033[1m\033[32m',
+    COLOR_WARNING: '\033[33m',
+    COLOR_HEADER: '\033[34m',
+    COLOR_INFO: '\033[35m',
+    COLOR_LABEL: '\033[36m',
+    COLOR_HIGLIGHT: '\033[97m\033[43m'
+}
+
+# list of available codes
+__code_range__ = ([1, 4] + list(range(30, 38)) + list(range(40, 48))
+                + list(range(90, 98)) + list(range(100, 108)))
+
+
[docs]def printc(txt, code=''): + '''print a text with colors + + :param txt str: The text to be printed. + :param code str: The color to use. + :return: The colored text. + :rtype: str + ''' + # no code means 'auto mode' (works only for OK, KO, NO and ERR*) + if code == '': + striptxt = txt.strip().upper() + if striptxt == "OK": + code = COLOR_SUCCESS + elif striptxt in ["KO", "NO"] or striptxt.startswith("ERR"): + code = COLOR_ERROR + else: + return txt + + # no code => output the originial text + if code not in __colormap__.keys() or __colormap__[code] == '': + return txt + + return __colormap__[code] + txt + '\033[0m' +
+
[docs]def printcInfo(txt): + '''print a text info color + + :param txt str: The text to be printed. + :return: The colored text. + :rtype: str + ''' + return printc(txt, COLOR_INFO) +
+
[docs]def printcError(txt): + '''print a text error color + + :param txt str: The text to be printed. + :return: The colored text. + :rtype: str + ''' + return printc(txt, COLOR_ERROR) +
+
[docs]def printcWarning(txt): + '''print a text warning color + + :param txt str: The text to be printed. + :return: The colored text. + :rtype: str + ''' + return printc(txt, COLOR_WARNING) +
+
[docs]def printcHeader(txt): + '''print a text header color + + :param txt str: The text to be printed. + :return: The colored text. + :rtype: str + ''' + return printc(txt, COLOR_HEADER) +
+
[docs]def printcLabel(txt): + '''print a text label color + + :param txt str: The text to be printed. + :return: The colored text. + :rtype: str + ''' + return printc(txt, COLOR_LABEL) +
+
[docs]def printcSuccess(txt): + '''print a text success color + + :param txt str: The text to be printed. + :return: The colored text. + :rtype: str + ''' + return printc(txt, COLOR_SUCCESS) +
+
[docs]def printcHighlight(txt): + '''print a text highlight color + + :param txt str: The text to be printed. + :return: The colored text. + :rtype: str + ''' + return printc(txt, COLOR_HIGLIGHT) +
+
[docs]def cleancolor(message): + '''remove color from a colored text. + + :param message str: The text to be cleaned. + :return: The cleaned text. + :rtype: str + ''' + if message == None: + return message + + message = message.replace('\033[0m', '') + for i in __code_range__: + message = message.replace('\033[%dm' % i, '') + return message +
+ + +
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/product.html b/doc/build/html/_modules/src/product.html new file mode 100644 index 0000000..91fe3a2 --- /dev/null +++ b/doc/build/html/_modules/src/product.html @@ -0,0 +1,917 @@ + + + + + + + + + src.product — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.product

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2012  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+"""\
+In this file are implemented the methods 
+relative to the product notion of salomeTools
+"""
+
+import os
+import re
+
+import src
+import src.debug as DBG
+
+AVAILABLE_VCS = ['git', 'svn', 'cvs']
+config_expression = "^config-\d+$"
+VERSION_DELIMITER = "_to_"
+
+
[docs]def get_product_config(config, product_name, with_install_dir=True): + """Get the specific configuration of a product from the global configuration + + :param config Config: The global configuration + :param product_name str: The name of the product + :param with_install_dir boolean: If false, do not provide an install + directory (at false only for internal use + of the function check_config_exists) + :return: the specific configuration of the product + :rtype: Config + """ + + # Get the version of the product from the application definition + version = config.APPLICATION.products[product_name] + # if no version, then take the default one defined in the application + if isinstance(version, bool): + version = config.APPLICATION.tag + + # Define debug and dev modes + # Get the tag if a dictionary is given in APPLICATION.products for the + # current product + debug = 'no' + dev = 'no' + base = 'maybe' + section = None + if isinstance(version, src.pyconf.Mapping): + dic_version = version + # Get the version/tag + if not 'tag' in dic_version: + version = config.APPLICATION.tag + else: + version = dic_version.tag + + # Get the debug if any + if 'debug' in dic_version: + debug = dic_version.debug + + # Get the dev if any + if 'dev' in dic_version: + dev = dic_version.dev + + # Get the base if any + if 'base' in dic_version: + base = dic_version.base + + # Get the section if any + if 'section' in dic_version: + section = dic_version.section + + vv = version + # substitute some character with _ in order to get the correct definition + # in config.PRODUCTS. This is done because the pyconf tool does not handle + # the . and - characters + for c in ".-": vv = vv.replace(c, "_") + + prod_info = None + if product_name in config.PRODUCTS: + # Search for the product description in the configuration + prod_info = get_product_section(config, product_name, vv, section) + + # merge opt_depend in depend + if prod_info is not None and 'opt_depend' in prod_info: + for depend in prod_info.opt_depend: + if depend in config.APPLICATION.products: + prod_info.depend.append(depend,'') + + # In case of a product get with a vcs, + # put the tag (equal to the version) + if prod_info is not None and prod_info.get_source in AVAILABLE_VCS: + + if prod_info.get_source == 'git': + prod_info.git_info.tag = version + + if prod_info.get_source == 'svn': + prod_info.svn_info.tag = version + + if prod_info.get_source == 'cvs': + prod_info.cvs_info.tag = version + + # In case of a fixed product, + # define the install_dir (equal to the version) + if prod_info is not None and os.path.isdir(version): + prod_info.install_dir = version + prod_info.get_source = "fixed" + + # Check if the product is defined as native in the application + if prod_info is not None: + if version == "native": + prod_info.get_source = "native" + elif prod_info.get_source == "native": + msg = _("The product %(prod)s has version %(ver)s but is " + "declared as native in its definition" % + { 'prod': prod_info.name, 'ver': version}) + raise src.SatException(msg) + + # If there is no definition but the product is declared as native, + # construct a new definition containing only the get_source key + if prod_info is None and version == "native": + prod_info = src.pyconf.Config() + prod_info.name = product_name + prod_info.get_source = "native" + + # If there is no definition but the product is fixed, + # construct a new definition containing only the product name + if prod_info is None and os.path.isdir(version): + prod_info = src.pyconf.Config() + prod_info.name = product_name + prod_info.get_source = "fixed" + prod_info.addMapping("environ", src.pyconf.Mapping(prod_info), "") + + + # If prod_info is still None, it means that there is no product definition + # in the config. The user has to provide it. + if prod_info is None: + prod_pyconf_path = src.find_file_in_lpath(product_name + ".pyconf", + config.PATHS.PRODUCTPATH) + if not prod_pyconf_path: + msg = _("""\ +No definition found for the product %(1)s. +Please create a %(2)s.pyconf file somewhere in: +%(3)s""") % { + "1": product_name, + "2": product_name, + "3": config.PATHS.PRODUCTPATH } + else: + msg = _("""\ +No definition corresponding to the version %(1)s was found in the file: + %(2)s. +Please add a section in it.""") % {"1" : vv, "2" : prod_pyconf_path} + raise src.SatException(msg) + + # Set the debug, dev and version keys + prod_info.debug = debug + prod_info.dev = dev + prod_info.version = version + + # Set the archive_info if the product is get in archive mode + if prod_info.get_source == "archive": + if not "archive_info" in prod_info: + prod_info.addMapping("archive_info", + src.pyconf.Mapping(prod_info), + "") + if "archive_name" not in prod_info.archive_info: + arch_name = product_name + "-" + version + ".tar.gz" + arch_path = src.find_file_in_lpath(arch_name, + config.PATHS.ARCHIVEPATH) + if not arch_path: + msg = _("Archive %(1)s for %(2)s not found in config.PATHS.ARCHIVEPATH") % \ + {"1" : arch_name, "2" : prod_info.name} + DBG.tofix(msg, config.PATHS.ARCHIVEPATH) + prod_info.archive_info.archive_name = arch_name #without path + # raise src.SatException(msg) #may be a warning, continue #8646 + else: + prod_info.archive_info.archive_name = arch_path + else: + if (os.path.basename(prod_info.archive_info.archive_name) == + prod_info.archive_info.archive_name): + arch_name = prod_info.archive_info.archive_name + arch_path = src.find_file_in_lpath( + arch_name, + config.PATHS.ARCHIVEPATH) + if not arch_path: + msg = _("Archive %(1)s for %(2)s not found in config.PATHS.ARCHIVEPATH") % \ + {"1" : arch_name, "2" : prod_info.name} + DBG.tofix(msg, config.PATHS.ARCHIVEPATH) #avoid 2 messages in compile + prod_info.archive_info.archive_name = arch_name #without path + # raise src.SatException(msg) #may be a warning, continue #8646 + prod_info.archive_info.archive_name = arch_path + + # If the product compiles with a script, check the script existence + # and if it is executable + if product_has_script(prod_info): + # Check the compil_script key existence + if "compil_script" not in prod_info: + msg = _("""\ +No compilation script found for the product %s. +Please provide a 'compil_script' key in its definition.""") % product_name + raise src.SatException(msg) + + # Get the path of the script + script = prod_info.compil_script + script_name = os.path.basename(script) + if script == script_name: + # Only a name is given. Search in the default directory + script_path = src.find_file_in_lpath(script_name, + config.PATHS.PRODUCTPATH, + "compil_scripts") + if not script_path: + raise src.SatException( + _("Compilation script not found: %s") % script_name) + prod_info.compil_script = script_path + if src.architecture.is_windows(): + prod_info.compil_script = prod_info.compil_script[:-len(".sh")] + ".bat" + + # Check that the script is executable + if not os.access(prod_info.compil_script, os.X_OK): + #raise src.SatException( + # _("Compilation script cannot be executed: %s") % + # prod_info.compil_script) + DBG.tofix("Compilation script cannot be executed:", prod_info.compil_script) + + # Get the full paths of all the patches + if product_has_patches(prod_info): + patches = [] + try: + for patch in prod_info.patches: + patch_path = patch + # If only a filename, then search for the patch in the PRODUCTPATH + if os.path.basename(patch_path) == patch_path: + # Search in the PRODUCTPATH/patches + patch_path = src.find_file_in_lpath(patch, + config.PATHS.PRODUCTPATH, + "patches") + if not patch_path: + msg = _("Patch %(patch_name)s for %(prod_name)s not found:" + "\n" % {"patch_name" : patch, + "prod_name" : prod_info.name}) + raise src.SatException(msg) + patches.append(patch_path) + except: + DBG.tofix("problem in prod_info.patches", prod_info) + prod_info.patches = patches + + # Get the full paths of the environment scripts + if product_has_env_script(prod_info): + env_script_path = prod_info.environ.env_script + # If only a filename, then search for the environment script + # in the PRODUCTPATH/env_scripts + if os.path.basename(env_script_path) == env_script_path: + # Search in the PRODUCTPATH/env_scripts + env_script_path = src.find_file_in_lpath( + prod_info.environ.env_script, + config.PATHS.PRODUCTPATH, + "env_scripts") + if not env_script_path: + msg = _("Environment script %(env_name)s for %(prod_name)s not " + "found.\n" % {"env_name" : env_script_path, + "prod_name" : prod_info.name}) + raise src.SatException(msg) + + prod_info.environ.env_script = env_script_path + + if with_install_dir: + # The variable with_install_dir is at false only for internal use + # of the function get_install_dir + + # Save the install_dir key if there is any + if "install_dir" in prod_info and not "install_dir_save" in prod_info: + prod_info.install_dir_save = prod_info.install_dir + + # if it is not the first time the install_dir is computed, it means + # that install_dir_save exists and it has to be taken into account. + if "install_dir_save" in prod_info: + prod_info.install_dir = prod_info.install_dir_save + + # Set the install_dir key + prod_info.install_dir = get_install_dir(config, base, version, prod_info) + + return prod_info +
+
[docs]def get_product_section(config, product_name, version, section=None): + """Get the product description from the configuration + + :param config Config: The global configuration + :param product_name str: The product name + :param version str: The version of the product + :param section str: The searched section (if not None, the section is + explicitly given + :return: The product description + :rtype: Config + """ + + # if section is not None, try to get the corresponding section + if section: + if section not in config.PRODUCTS[product_name]: + return None + # returns specific information for the given version + prod_info = config.PRODUCTS[product_name][section] + prod_info.section = section + prod_info.from_file = config.PRODUCTS[product_name].from_file + return prod_info + + # If it exists, get the information of the product_version + if "version_" + version in config.PRODUCTS[product_name]: + # returns specific information for the given version + prod_info = config.PRODUCTS[product_name]["version_" + version] + prod_info.section = "version_" + version + prod_info.from_file = config.PRODUCTS[product_name].from_file + return prod_info + + # Else, check if there is a description for multiple versions + l_section_name = config.PRODUCTS[product_name].keys() + l_section_ranges = [section_name for section_name in l_section_name + if VERSION_DELIMITER in section_name] + for section_range in l_section_ranges: + minimum, maximum = section_range.split(VERSION_DELIMITER) + if (src.only_numbers(version) >= src.only_numbers(minimum) + and src.only_numbers(version) <= src.only_numbers(maximum)): + # returns specific information for the versions + prod_info = config.PRODUCTS[product_name][section_range] + prod_info.section = section_range + prod_info.from_file = config.PRODUCTS[product_name].from_file + return prod_info + + # Else, get the standard informations + if "default" in config.PRODUCTS[product_name]: + # returns the generic information (given version not found) + prod_info = config.PRODUCTS[product_name].default + prod_info.section = "default" + prod_info.from_file = config.PRODUCTS[product_name].from_file + return prod_info + + # if noting was found, return None + return None +
+
[docs]def get_install_dir(config, base, version, prod_info): + """Compute the installation directory of a given product + + :param config Config: The global configuration + :param base str: This corresponds to the value given by user in its + application.pyconf for the specific product. If "yes", the + user wants the product to be in base. If "no", he wants the + product to be in the application workdir + :param version str: The version of the product + :param product_info Config: The configuration specific to + the product + + :return: The path of the product installation + :rtype: str + """ + install_dir = "" + in_base = False + if (("install_dir" in prod_info and prod_info.install_dir == "base") + or base == "yes"): + in_base = True + if (base == "no" or ("no_base" in config.APPLICATION + and config.APPLICATION.no_base == "yes")): + in_base = False + + if in_base: + install_dir = get_base_install_dir(config, prod_info, version) + else: + if "install_dir" not in prod_info or prod_info.install_dir == "base": + # Set it to the default value (in application directory) + install_dir = os.path.join(config.APPLICATION.workdir, + "INSTALL", + prod_info.name) + else: + install_dir = prod_info.install_dir + + return install_dir +
+
[docs]def get_base_install_dir(config, prod_info, version): + """Compute the installation directory of a product in base + + :param config Config: The global configuration + :param product_info Config: The configuration specific to + the product + :param version str: The version of the product + :return: The path of the product installation + :rtype: str + """ + base_path = src.get_base_path(config) + prod_dir = os.path.join(base_path, prod_info.name + "-" + version) + if not os.path.exists(prod_dir): + return os.path.join(prod_dir, "config-1") + + exists, install_dir = check_config_exists(config, prod_dir, prod_info) + if exists: + return install_dir + + # Find the first config-<i> directory that is available in the product + # directory + found = False + label = 1 + while not found: + install_dir = os.path.join(prod_dir, "config-%i" % label) + if os.path.exists(install_dir): + label+=1 + else: + found = True + + return install_dir +
+
[docs]def check_config_exists(config, prod_dir, prod_info): + """\ + Verify that the installation directory of a product in a base exists + Check all the config-<i> directory and verify the sat-config.pyconf file + that is in it + + :param config Config: The global configuration + :param prod_dir str: The product installation directory path + (without config-<i>) + :param product_info Config: The configuration specific to + the product + :return: True or false is the installation is found or not + and if it is found, the path of the found installation + :rtype: (boolean, str) + """ + # check if the directories or files of the directory corresponds to the + # directory installation of the product + l_dir_and_files = os.listdir(prod_dir) + for dir_or_file in l_dir_and_files: + oExpr = re.compile(config_expression) + if not(oExpr.search(dir_or_file)): + # not config-<i>, not interesting + continue + # check if there is the file sat-config.pyconf file in the installation + # directory + config_file = os.path.join(prod_dir, dir_or_file, src.CONFIG_FILENAME) + if not os.path.exists(config_file): + continue + + # If there is no dependency, it is the right path + if len(prod_info.depend)==0: + compile_cfg = src.pyconf.Config(config_file) + if len(compile_cfg) == 0: + return True, os.path.join(prod_dir, dir_or_file) + continue + + # check if there is the config described in the file corresponds the + # dependencies of the product + config_corresponds = True + compile_cfg = src.pyconf.Config(config_file) + for prod_dep in prod_info.depend: + # if the dependency is not in the config, + # the config does not correspond + if prod_dep not in compile_cfg: + config_corresponds = False + break + else: + prod_dep_info = get_product_config(config, prod_dep, False) + # If the version of the dependency does not correspond, + # the config does not correspond + if prod_dep_info.version != compile_cfg[prod_dep]: + config_corresponds = False + break + + for prod_name in compile_cfg: + if prod_name not in prod_info.depend: + config_corresponds = False + break + + if config_corresponds: + return True, os.path.join(prod_dir, dir_or_file) + + return False, None + + +
+
[docs]def get_products_infos(lproducts, config): + """Get the specific configuration of a list of products + + :param lproducts List: The list of product names + :param config Config: The global configuration + :return: the list of tuples + (product name, specific configuration of the product) + :rtype: [(str, Config)] + """ + products_infos = [] + # Loop on product names + for prod in lproducts: + # Get the specific configuration of the product + prod_info = get_product_config(config, prod) + if prod_info is not None: + products_infos.append((prod, prod_info)) + else: + msg = _("The %s product has no definition " + "in the configuration.") % prod + raise src.SatException(msg) + return products_infos +
+
[docs]def get_product_dependencies(config, product_info): + """\ + Get recursively the list of products that are + in the product_info dependencies + + :param config Config: The global configuration + :param product_info Config: The configuration specific to + the product + :return: the list of products in dependence + :rtype: list + """ + if "depend" not in product_info or product_info.depend == []: + return [] + res = [] + for prod in product_info.depend: + if prod == product_info.name: + continue + if prod not in res: + res.append(prod) + prod_info = get_product_config(config, prod) + dep_prod = get_product_dependencies(config, prod_info) + for prod_in_dep in dep_prod: + if prod_in_dep not in res: + res.append(prod_in_dep) + return res +
+
[docs]def check_installation(product_info): + """\ + Verify if a product is well installed. Checks install directory presence + and some additional files if it is defined in the config + + :param product_info Config: The configuration specific to + the product + :return: True if it is well installed + :rtype: boolean + """ + if not product_compiles(product_info): + return True + install_dir = product_info.install_dir + if not os.path.exists(install_dir): + return False + if ("present_files" in product_info and + "install" in product_info.present_files): + for file_relative_path in product_info.present_files.install: + file_path = os.path.join(install_dir, file_relative_path) + if not os.path.exists(file_path): + return False + return True +
+
[docs]def check_source(product_info): + """Verify if a sources of product is preset. Checks source directory presence + + :param product_info Config: The configuration specific to + the product + :return: True if it is well installed + :rtype: boolean + """ + DBG.write("check_source product_info", product_info) + source_dir = product_info.source_dir + if not os.path.exists(source_dir): + return False + if ("present_files" in product_info and + "source" in product_info.present_files): + for file_relative_path in product_info.present_files.source: + file_path = os.path.join(source_dir, file_relative_path) + if not os.path.exists(file_path): + return False + return True +
+
[docs]def product_is_sample(product_info): + """Know if a product has the sample type + + :param product_info Config: The configuration specific to + the product + :return: True if the product has the sample type, else False + :rtype: boolean + """ + if 'type' in product_info: + ptype = product_info.type + return ptype.lower() == 'sample' + else: + return False +
+
[docs]def product_is_salome(product_info): + """Know if a product is a SALOME module + + :param product_info Config: The configuration specific to + the product + :return: True if the product is a SALOME module, else False + :rtype: boolean + """ + return ("properties" in product_info and + "is_SALOME_module" in product_info.properties and + product_info.properties.is_SALOME_module == "yes") +
+
[docs]def product_is_fixed(product_info): + """Know if a product is fixed + + :param product_info Config: The configuration specific to + the product + :return: True if the product is fixed, else False + :rtype: boolean + """ + get_src = product_info.get_source + return get_src.lower() == 'fixed' +
+
[docs]def product_is_native(product_info): + """Know if a product is native + + :param product_info Config: The configuration specific to + the product + :return: True if the product is native, else False + :rtype: boolean + """ + get_src = product_info.get_source + return get_src.lower() == 'native' +
+
[docs]def product_is_dev(product_info): + """Know if a product is in dev mode + + :param product_info Config: The configuration specific to + the product + :return: True if the product is in dev mode, else False + :rtype: boolean + """ + dev = product_info.dev + res = (dev.lower() == 'yes') + DBG.write('product_is_dev %s' % product_info.name, res) + # if product_info.name == "XDATA": return True #test #10569 + return res +
+
[docs]def product_is_debug(product_info): + """Know if a product is in debug mode + + :param product_info Config: The configuration specific to + the product + :return: True if the product is in debug mode, else False + :rtype: boolean + """ + debug = product_info.debug + return debug.lower() == 'yes' +
+
[docs]def product_is_autotools(product_info): + """Know if a product is compiled using the autotools + + :param product_info Config: The configuration specific to + the product + :return: True if the product is autotools, else False + :rtype: boolean + """ + build_src = product_info.build_source + return build_src.lower() == 'autotools' +
+
[docs]def product_is_cmake(product_info): + """Know if a product is compiled using the cmake + + :param product_info Config: The configuration specific to + the product + :return: True if the product is cmake, else False + :rtype: boolean + """ + build_src = product_info.build_source + return build_src.lower() == 'cmake' +
+
[docs]def product_is_vcs(product_info): + """Know if a product is download using git, svn or cvs (not archive) + + :param product_info Config: The configuration specific to + the product + :return: True if the product is vcs, else False + :rtype: boolean + """ + return product_info.get_source in AVAILABLE_VCS +
+
[docs]def product_is_smesh_plugin(product_info): + """Know if a product is a SMESH plugin + + :param product_info Config: The configuration specific to + the product + :return: True if the product is a SMESH plugin, else False + :rtype: boolean + """ + return ("properties" in product_info and + "smesh_plugin" in product_info.properties and + product_info.properties.smesh_plugin == "yes") +
+
[docs]def product_is_cpp(product_info): + """Know if a product is cpp + + :param product_info Config: The configuration specific to + the product + :return: True if the product is a cpp, else False + :rtype: boolean + """ + return ("properties" in product_info and + "cpp" in product_info.properties and + product_info.properties.cpp == "yes") +
+
[docs]def product_compiles(product_info): + """\ + Know if a product compiles or not + (some products do not have a compilation procedure) + + :param product_info Config: The configuration specific to + the product + :return: True if the product compiles, else False + :rtype: boolean + """ + return not("properties" in product_info and + "compilation" in product_info.properties and + product_info.properties.compilation == "no") +
+
[docs]def product_has_script(product_info): + """Know if a product has a compilation script + + :param product_info Config: The configuration specific to + the product + :return: True if the product it has a compilation script, else False + :rtype: boolean + """ + if "build_source" not in product_info: + # Native case + return False + build_src = product_info.build_source + return build_src.lower() == 'script' +
+
[docs]def product_has_env_script(product_info): + """Know if a product has an environment script + + :param product_info Config: The configuration specific to + the product + :return: True if the product it has an environment script, else False + :rtype: boolean + """ + return "environ" in product_info and "env_script" in product_info.environ +
+
[docs]def product_has_patches(product_info): + """Know if a product has one or more patches + + :param product_info Config: The configuration specific to + the product + :return: True if the product has one or more patches + :rtype: boolean + """ + res = ( "patches" in product_info and len(product_info.patches) > 0 ) + DBG.write('product_has_patches %s' % product_info.name, res) + # if product_info.name == "XDATA": return True #test #10569 + return res +
+ +
[docs]def product_has_salome_gui(product_info): + """Know if a product has a SALOME gui + + :param product_info Config: The configuration specific to + the product + :return: True if the product has a SALOME gui, else False + :rtype: Boolean + """ + return ("properties" in product_info and + "has_salome_gui" in product_info.properties and + product_info.properties.has_salome_gui == "yes") +
+
[docs]def product_is_mpi(product_info): + """Know if a product has openmpi in its dependencies + + :param product_info Config: The configuration specific to + the product + :return: True if the product has openmpi inits dependencies + :rtype: boolean + """ + return "openmpi" in product_info.depend +
+
[docs]def product_is_generated(product_info): + """Know if a product is generated (YACSGEN) + + :param product_info Config: The configuration specific to + the product + :return: True if the product is generated + :rtype: boolean + """ + return ("properties" in product_info and + "generate" in product_info.properties and + product_info.properties.generate == "yes") +
+
[docs]def get_product_components(product_info): + """Get the component list to generate with the product + + :param product_info Config: The configuration specific to + the product + :return: The list of names of the components + :rtype: List + + """ + if not product_is_generated(product_info): + return [] + + compo_list = [] + if "component_name" in product_info: + compo_list = product_info.component_name + + if isinstance(compo_list, str): + compo_list = [ compo_list ] + + return compo_list
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/pyconf.html b/doc/build/html/_modules/src/pyconf.html new file mode 100644 index 0000000..fd3372e --- /dev/null +++ b/doc/build/html/_modules/src/pyconf.html @@ -0,0 +1,1836 @@ + + + + + + + + + src.pyconf — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.pyconf

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+# Copyright 2004-2007 by Vinay Sajip. All Rights Reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of Vinay Sajip
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+# CEA adds : 
+# Possibility to overwrites value in a pyconf file
+# Python 3 porting
+
+
+"""
+This is a configuration module for Python.
+
+This module should work under Python versions >= 2.2, and cannot be used with
+earlier versions since it uses new-style classes.
+
+Development and testing has only been carried out (so far) on Python 2.3.4 and
+Python 2.4.2. See the test module (test_config.py) included in the
+U{distribution<http://www.red-dove.com/python_config.html|_blank>} (follow the
+download link).
+
+A simple example - with the example configuration file::
+
+    messages:
+    [
+      {
+        stream : `sys.stderr`
+        message: 'Welcome'
+        name: 'Harry'
+      }
+      {
+        stream : `sys.stdout`
+        message: 'Welkom'
+        name: 'Ruud'
+      }
+      {
+        stream : $messages[0].stream
+        message: 'Bienvenue'
+        name: Yves
+      }
+    ]
+
+a program to read the configuration would be::
+
+    from config import Config
+
+    f = file('simple.cfg')
+    cfg = Config(f)
+    for m in cfg.messages:
+        s = '%s, %s' % (m.message, m.name)
+        try:
+            print >> m.stream, s
+        except IOError, e:
+            print e
+
+which, when run, would yield the console output::
+
+    Welcome, Harry
+    Welkom, Ruud
+    Bienvenue, Yves
+
+See U{this tutorial<http://www.red-dove.com/python_config.html|_blank>} for more
+information.
+
+#modified for salomeTools
+@version: 0.3.7.1
+
+@author: Vinay Sajip
+
+@copyright: Copyright (C) 2004-2007 Vinay Sajip. All Rights Reserved.
+
+
+@var streamOpener: The default stream opener. This is a factory function which
+takes a string (e.g. filename) and returns a stream suitable for reading. If
+unable to open the stream, an IOError exception should be thrown.
+
+The default value of this variable is L{defaultStreamOpener}. For an example
+of how it's used, see test_config.py (search for streamOpener).
+"""
+
+__author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
+__status__  = "alpha"
+__version__ = "0.3.7.1" #modified for salomeTools
+__date__    = "05 October 2007"
+
+import codecs
+import os
+import sys
+
+WORD = 'a'
+NUMBER = '9'
+STRING = '"'
+EOF = ''
+LCURLY = '{'
+RCURLY = '}'
+LBRACK = '['
+LBRACK2 = 'a['
+RBRACK = ']'
+LPAREN = '('
+LPAREN2 = '(('
+RPAREN = ')'
+DOT = '.'
+COMMA = ','
+COLON = ':'
+AT = '@'
+PLUS = '+'
+MINUS = '-'
+STAR = '*'
+SLASH = '/'
+MOD = '%'
+BACKTICK = '`'
+DOLLAR = '$'
+TRUE = 'True'
+FALSE = 'False'
+NONE = 'None'
+
+WORDCHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
+
+if sys.platform == 'win32':
+    NEWLINE = '\r\n'
+elif os.name == 'mac':
+    NEWLINE = '\r'
+else:
+    NEWLINE = '\n'
+
+try:
+    has_utf32 = True
+except:
+    has_utf32 = False
+
+
[docs]class ConfigInputStream(object): + """ + An input stream which can read either ANSI files with default encoding + or Unicode files with BOMs. + + Handles UTF-8, UTF-16LE, UTF-16BE. Could handle UTF-32 if Python had + built-in support. + """ + def __init__(self, stream): + """ + Initialize an instance. + + @param stream: The underlying stream to be read. Should be seekable. + @type stream: A stream (file-like object). + """ + encoding = None + signature = stream.read(4) + used = -1 + if has_utf32: + if signature == codecs.BOM_UTF32_LE: + encoding = 'utf-32le' + elif signature == codecs.BOM_UTF32_BE: + encoding = 'utf-32be' + if encoding is None: + if signature[:3] == codecs.BOM_UTF8: + used = 3 + encoding = 'utf-8' + elif signature[:2] == codecs.BOM_UTF16_LE: + used = 2 + encoding = 'utf-16le' + elif signature[:2] == codecs.BOM_UTF16_BE: + used = 2 + encoding = 'utf-16be' + else: + used = 0 + if used >= 0: + stream.seek(used) + if encoding: + reader = codecs.getreader(encoding) + stream = reader(stream) + self.stream = stream + self.encoding = encoding + +
[docs] def read(self, size): + if (size == 0) or (self.encoding is None): + rv = self.stream.read(size) + else: + rv = u'' + while size > 0: + rv += self.stream.read(1) + size -= 1 + return rv +
+
[docs] def close(self): + self.stream.close() +
+
[docs] def readline(self): + if self.encoding is None: + line = '' + else: + line = u'' + while True: + c = self.stream.read(1) + if isinstance(c, bytes): + c = c.decode() + if c: + line += c + if c == '\n': + break + return line +
+
[docs]class ConfigOutputStream(object): + """ + An output stream which can write either ANSI files with default encoding + or Unicode files with BOMs. + + Handles UTF-8, UTF-16LE, UTF-16BE. Could handle UTF-32 if Python had + built-in support. + """ + + def __init__(self, stream, encoding=None): + """ + Initialize an instance. + + @param stream: The underlying stream to be written. + @type stream: A stream (file-like object). + @param encoding: The desired encoding. + @type encoding: str + """ + if encoding is not None: + encoding = str(encoding).lower() + self.encoding = encoding + if encoding == "utf-8": + stream.write(codecs.BOM_UTF8) + elif encoding == "utf-16be": + stream.write(codecs.BOM_UTF16_BE) + elif encoding == "utf-16le": + stream.write(codecs.BOM_UTF16_LE) + elif encoding == "utf-32be": + stream.write(codecs.BOM_UTF32_BE) + elif encoding == "utf-32le": + stream.write(codecs.BOM_UTF32_LE) + + if encoding is not None: + writer = codecs.getwriter(encoding) + stream = writer(stream) + self.stream = stream + +
[docs] def write(self, data): + self.stream.write(data) +
+
[docs] def flush(self): + self.stream.flush() +
+
[docs] def close(self): + self.stream.close() +
+
[docs]def defaultStreamOpener(name): + """\ + This function returns a read-only stream, given its name. The name passed + in should correspond to an existing stream, otherwise an exception will be + raised. + + This is the default value of L{streamOpener}; assign your own callable to + streamOpener to return streams based on names. For example, you could use + urllib2.urlopen(). + + @param name: The name of a stream, most commonly a file name. + @type name: str + @return: A stream with the specified name. + @rtype: A read-only stream (file-like object) + """ + return ConfigInputStream(open(name, 'rb')) +
+streamOpener = None + +__resolveOverwrite__ = True + +
[docs]class ConfigError(Exception): + """ + This is the base class of exceptions raised by this module. + """ + pass +
+
[docs]class ConfigFormatError(ConfigError): + """ + This is the base class of exceptions raised due to syntax errors in + configurations. + """ + pass +
+
[docs]class ConfigResolutionError(ConfigError): + """ + This is the base class of exceptions raised due to semantic errors in + configurations. + """ + pass +
+
[docs]def isWord(s): + """ + See if a passed-in value is an identifier. If the value passed in is not a + string, False is returned. An identifier consists of alphanumerics or + underscore characters. + + Examples:: + + isWord('a word') ->False + isWord('award') -> True + isWord(9) -> False + isWord('a_b_c_') ->True + + @note: isWord('9abc') will return True - not exactly correct, but adequate + for the way it's used here. + + @param s: The name to be tested + @type s: any + @return: True if a word, else False + @rtype: bool + """ + if type(s) != type(''): + return False + s = s.replace('_', '') + return s.isalnum() +
+
[docs]def makePath(prefix, suffix): + """\ + Make a path from a prefix and suffix. + + Examples: + makePath('', 'suffix') -> 'suffix' + makePath('prefix', 'suffix') -> 'prefix.suffix' + makePath('prefix', '[1]') -> 'prefix[1]' + + @param prefix: The prefix to use. If it evaluates as false, the suffix is returned. + @type prefix: str + @param suffix: The suffix to use. It is either an identifier or an index in brackets. + @type suffix: str + @return: The path concatenation of prefix and suffix, with adot if the suffix is not a bracketed index. + @rtype: str + """ + if not prefix: + rv = suffix + elif suffix[0] == '[': + rv = prefix + suffix + else: + rv = prefix + '.' + suffix + return rv + +
+
[docs]class Container(object): + """ + This internal class is the base class for mappings and sequences. + + @ivar path: A string which describes how to get + to this instance from the root of the hierarchy. + + Example:: + + a.list.of[1].or['more'].elements + """ + def __init__(self, parent): + """ + Initialize an instance. + + @param parent: The parent of this instance in the hierarchy. + @type parent: A L{Container} instance. + """ + object.__setattr__(self, 'parent', parent) + +
[docs] def setPath(self, path): + """ + Set the path for this instance. + @param path: The path - a string which describes how to get + to this instance from the root of the hierarchy. + @type path: str + """ + object.__setattr__(self, 'path', path) +
+
[docs] def evaluate(self, item): + """ + Evaluate items which are instances of L{Reference} or L{Expression}. + + L{Reference} instances are evaluated using L{Reference.resolve}, + and L{Expression} instances are evaluated using + L{Expression.evaluate}. + + @param item: The item to be evaluated. + @type item: any + @return: If the item is an instance of L{Reference} or L{Expression}, + the evaluated value is returned, otherwise the item is returned + unchanged. + """ + if isinstance(item, Reference): + item = item.resolve(self) + elif isinstance(item, Expression): + item = item.evaluate(self) + return item +
+
[docs] def writeToStream(self, stream, indent, container): + """ + Write this instance to a stream at the specified indentation level. + + Should be redefined in subclasses. + + @param stream: The stream to write to + @type stream: A writable stream (file-like object) + @param indent: The indentation level + @type indent: int + @param container: The container of this instance + @type container: L{Container} + @raise NotImplementedError: If a subclass does not override this + """ + raise NotImplementedError +
+
[docs] def writeValue(self, value, stream, indent): + if isinstance(self, Mapping): + indstr = ' ' + else: + indstr = indent * ' ' + if isinstance(value, Reference) or isinstance(value, Expression): + stream.write('%s%r%s' % (indstr, value, NEWLINE)) + else: + if isinstance(value, str): # and not isWord(value): + value = repr(value) + stream.write('%s%s%s' % (indstr, value, NEWLINE)) +
+
[docs]class Mapping(Container): + """ + This internal class implements key-value mappings in configurations. + """ + + def __init__(self, parent=None): + """ + Initialize an instance. + + @param parent: The parent of this instance in the hierarchy. + @type parent: A L{Container} instance. + """ + Container.__init__(self, parent) + object.__setattr__(self, 'path', '') + object.__setattr__(self, 'data', {}) + object.__setattr__(self, 'order', []) # to preserve ordering + object.__setattr__(self, 'comments', {}) + + def __delitem__(self, key): + """ + Remove an item + """ + data = object.__getattribute__(self, 'data') + if key not in data: + raise AttributeError(key) + order = object.__getattribute__(self, 'order') + comments = object.__getattribute__(self, 'comments') + del data[key] + order.remove(key) + del comments[key] + + def __getitem__(self, key): + data = object.__getattribute__(self, 'data') + if key not in data: + raise AttributeError(key) + rv = data[key] + return self.evaluate(rv) + + __getattr__ = __getitem__ + + ''' + def __getattribute__(self, name): + if name == "__dict__": + return {} + if name in ["__methods__", "__members__"]: + return [] + #if name == "__class__": + # return '' + data = object.__getattribute__(self, "data") + useData = data.has_key(name) + if useData: + rv = getattr(data, name) + else: + rv = object.__getattribute__(self, name) + if rv is None: + raise AttributeError(name) + return rv + ''' + +
[docs] def iteritems(self): + for key in self.keys(): + yield(key, self[key]) + raise StopIteration +
+ def __contains__(self, item): + order = object.__getattribute__(self, 'order') + return item in order + +
[docs] def addMapping(self, key, value, comment, setting=False): + """ + Add a key-value mapping with a comment. + + @param key: The key for the mapping. + @type key: str + @param value: The value for the mapping. + @type value: any + @param comment: The comment for the key (can be None). + @type comment: str + @param setting: If True, ignore clashes. This is set + to true when called from L{__setattr__}. + @raise ConfigFormatError: If an existing key is seen + again and setting is False. + """ + data = object.__getattribute__(self, 'data') + order = object.__getattribute__(self, 'order') + comments = object.__getattribute__(self, 'comments') + + data[key] = value + if key not in order: + order.append(key) + elif not setting: + raise ConfigFormatError("repeated key: %s" % key) + comments[key] = comment +
+ def __setattr__(self, name, value): + self.addMapping(name, value, None, True) + + __setitem__ = __setattr__ + +
[docs] def keys(self): + """ + Return the keys in a similar way to a dictionary. + """ + return object.__getattribute__(self, 'order') +
+
[docs] def get(self, key, default=None): + """ + Allows a dictionary-style get operation. + """ + if key in self: + return self[key] + return default +
+ def __str__(self): + return str(object.__getattribute__(self, 'data')) + + def __repr__(self): + return repr(object.__getattribute__(self, 'data')) + + def __len__(self): + return len(object.__getattribute__(self, 'order')) + + def __iter__(self): + return self.iterkeys() + +
[docs] def iterkeys(self): + order = object.__getattribute__(self, 'order') + return order.__iter__() +
+
[docs] def writeToStream(self, stream, indent, container): + """ + Write this instance to a stream at the specified indentation level. + + Should be redefined in subclasses. + + @param stream: The stream to write to + @type stream: A writable stream (file-like object) + @param indent: The indentation level + @type indent: int + @param container: The container of this instance + @type container: L{Container} + """ + indstr = indent * ' ' + if len(self) == 0: + stream.write(' { }%s' % NEWLINE) + else: + if isinstance(container, Mapping): + stream.write(NEWLINE) + stream.write('%s{%s' % (indstr, NEWLINE)) + self.__save__(stream, indent + 1) + stream.write('%s}%s' % (indstr, NEWLINE)) +
+ def __save__(self, stream, indent=0): + """ + Save this configuration to the specified stream. + @param stream: A stream to which the configuration is written. + @type stream: A write-only stream (file-like object). + @param indent: The indentation level for the output. + @type indent: int + """ + indstr = indent * ' ' + order = object.__getattribute__(self, 'order') + data = object.__getattribute__(self, 'data') + maxlen = 0 # max(map(lambda x: len(x), order)) + for key in order: + comment = self.comments[key] + if isWord(key): + skey = key + else: + skey = repr(key) + if comment: + stream.write('%s#%s' % (indstr, comment)) + if skey.startswith("u'"): + skey = skey[1:] + stream.write('%s%-*s :' % (indstr, maxlen, skey)) + value = data[key] + if isinstance(value, Container): + value.writeToStream(stream, indent, self) + else: + self.writeValue(value, stream, indent) +
+
[docs]class Config(Mapping): + """ + This class represents a configuration, and is the only one which clients + need to interface to, under normal circumstances. + """ + +
[docs] class Namespace(object): + """ + This internal class is used for implementing default namespaces. + + An instance acts as a namespace. + """ + def __init__(self): + self.sys = sys + self.os = os +
+ def __init__(self, streamOrFile=None, parent=None, PWD = None): + """ + Initializes an instance. + + @param streamOrFile: If specified, causes this instance to be loaded + from the stream (by calling L{load}). If a string is provided, it is + passed to L{streamOpener} to open a stream. Otherwise, the passed + value is assumed to be a stream and used as is. + @type streamOrFile: A readable stream (file-like object) or a name. + @param parent: If specified, this becomes the parent of this instance + in the configuration hierarchy. + @type parent: a L{Container} instance. + """ + try: # Python 3 compatibility + if isinstance(streamOrFile, unicode): + streamOrFile = streamOrFile.encode() + except NameError: + pass + Mapping.__init__(self, parent) + object.__setattr__(self, 'reader', ConfigReader(self)) + object.__setattr__(self, 'namespaces', [Config.Namespace()]) + if streamOrFile is not None: + if isinstance(streamOrFile, str) or isinstance(streamOrFile, bytes): + global streamOpener + if streamOpener is None: + streamOpener = defaultStreamOpener + streamOrFile = streamOpener(streamOrFile) + load = object.__getattribute__(self, "load") + load(streamOrFile) + # Specific add for salomeTools : PWD + if PWD: + key, pwd = PWD + if key == "": + self.PWD = pwd + else: + self[key].PWD = pwd + +
[docs] def load(self, stream): + """ + Load the configuration from the specified stream. Multiple streams can + be used to populate the same instance, as long as there are no + clashing keys. The stream is closed. + @param stream: A stream from which the configuration is read. + @type stream: A read-only stream (file-like object). + @raise ConfigError: if keys in the loaded configuration clash with + existing keys. + @raise ConfigFormatError: if there is a syntax error in the stream. + """ + reader = object.__getattribute__(self, 'reader') + reader.load(stream) + stream.close() +
+
[docs] def addNamespace(self, ns, name=None): + """ + Add a namespace to this configuration which can be used to evaluate + (resolve) dotted-identifier expressions. + @param ns: The namespace to be added. + @type ns: A module or other namespace suitable for passing as an + argument to vars(). + @param name: A name for the namespace, which, if specified, provides + an additional level of indirection. + @type name: str + """ + namespaces = object.__getattribute__(self, 'namespaces') + if name is None: + namespaces.append(ns) + else: + setattr(namespaces[0], name, ns) +
+
[docs] def removeNamespace(self, ns, name=None): + """ + Remove a namespace added with L{addNamespace}. + @param ns: The namespace to be removed. + @param name: The name which was specified when L{addNamespace} was + called. + @type name: str + """ + namespaces = object.__getattribute__(self, 'namespaces') + if name is None: + namespaces.remove(ns) + else: + delattr(namespaces[0], name) +
+ def __save__(self, stream, indent=0, no_close=False): + """ + Save this configuration to the specified stream. The stream is + closed if this is the top-level configuration in the hierarchy. + L{Mapping.__save__} is called to do all the work. + @param stream: A stream to which the configuration is written. + @type stream: A write-only stream (file-like object). + @param indent: The indentation level for the output. + @type indent: int + """ + Mapping.__save__(self, stream, indent) + if indent == 0 and not no_close: + stream.close() + +
[docs] def getByPath(self, path): + """ + Obtain a value in the configuration via its path. + @param path: The path of the required value + @type path: str + @return the value at the specified path. + @rtype: any + @raise ConfigError: If the path is invalid + """ + s = 'self.' + path + try: + return eval(s) + except Exception as e: + raise ConfigError(str(e)) +
+
[docs]class Sequence(Container): + """ + This internal class implements a value which is a sequence of other values. + """ +
[docs] class SeqIter(object): + """ + This internal class implements an iterator for a L{Sequence} instance. + """ + def __init__(self, seq): + self.seq = seq + self.limit = len(object.__getattribute__(seq, 'data')) + self.index = 0 + + def __iter__(self): + return self + +
[docs] def next(self): + if self.index >= self.limit: + raise StopIteration + rv = self.seq[self.index] + self.index += 1 + return rv + + # This method is for python3 compatibility
+ def __next__(self): + if self.index >= self.limit: + raise StopIteration + rv = self.seq[self.index] + self.index += 1 + return rv +
+ def __init__(self, parent=None): + """ + Initialize an instance. + + @param parent: The parent of this instance in the hierarchy. + @type parent: A L{Container} instance. + """ + Container.__init__(self, parent) + object.__setattr__(self, 'data', []) + object.__setattr__(self, 'comments', []) + +
[docs] def append(self, item, comment): + """ + Add an item to the sequence. + + @param item: The item to add. + @type item: any + @param comment: A comment for the item. + @type comment: str + """ + data = object.__getattribute__(self, 'data') + comments = object.__getattribute__(self, 'comments') + data.append(item) + comments.append(comment) +
+ def __getitem__(self, index): + data = object.__getattribute__(self, 'data') + try: + rv = data[index] + except (IndexError, KeyError, TypeError): + raise ConfigResolutionError('%r is not a valid index for %r' % (index, object.__getattribute__(self, 'path'))) + if not isinstance(rv, list): + rv = self.evaluate(rv) + else: + # deal with a slice + result = [] + for a in rv: + result.append(self.evaluate(a)) + rv = result + return rv + + def __iter__(self): + return Sequence.SeqIter(self) + + def __repr__(self): + return repr(object.__getattribute__(self, 'data')) + + def __str__(self): + return str(self[:]) # using the slice evaluates the contents + + def __len__(self): + return len(object.__getattribute__(self, 'data')) + +
[docs] def writeToStream(self, stream, indent, container): + """ + Write this instance to a stream at the specified indentation level. + + Should be redefined in subclasses. + + @param stream: The stream to write to + @type stream: A writable stream (file-like object) + @param indent: The indentation level + @type indent: int + @param container: The container of this instance + @type container: L{Container} + """ + indstr = indent * ' ' + if len(self) == 0: + stream.write(' [ ]%s' % NEWLINE) + else: + if isinstance(container, Mapping): + stream.write(NEWLINE) + stream.write('%s[%s' % (indstr, NEWLINE)) + self.__save__(stream, indent + 1) + stream.write('%s]%s' % (indstr, NEWLINE)) +
+ def __save__(self, stream, indent): + """ + Save this instance to the specified stream. + @param stream: A stream to which the configuration is written. + @type stream: A write-only stream (file-like object). + @param indent: The indentation level for the output, > 0 + @type indent: int + """ + if indent == 0: + raise ConfigError("sequence cannot be saved as a top-level item") + data = object.__getattribute__(self, 'data') + comments = object.__getattribute__(self, 'comments') + indstr = indent * ' ' + for i in range(0, len(data)): + value = data[i] + comment = comments[i] + if comment: + stream.write('%s#%s' % (indstr, comment)) + if isinstance(value, Container): + value.writeToStream(stream, indent, self) + else: + self.writeValue(value, stream, indent) +
+
[docs]class Reference(object): + """ + This internal class implements a value which is a reference to another value. + """ + def __init__(self, config, type, ident): + """ + Initialize an instance. + + @param config: The configuration which contains this reference. + @type config: A L{Config} instance. + @param type: The type of reference. + @type type: BACKTICK or DOLLAR + @param ident: The identifier which starts the reference. + @type ident: str + """ + self.config = config + self.type = type + self.elements = [ident] + +
[docs] def addElement(self, type, ident): + """ + Add an element to the reference. + + @param type: The type of reference. + @type type: BACKTICK or DOLLAR + @param ident: The identifier which continues the reference. + @type ident: str + """ + self.elements.append((type, ident)) +
+
[docs] def findConfig(self, container): + """ + Find the closest enclosing configuration to the specified container. + + @param container: The container to start from. + @type container: L{Container} + @return: The closest enclosing configuration, or None. + @rtype: L{Config} + """ + while (container is not None) and not isinstance(container, Config): + container = object.__getattribute__(container, 'parent') + return container +
+
[docs] def resolve(self, container): + """ + Resolve this instance in the context of a container. + + @param container: The container to resolve from. + @type container: L{Container} + @return: The resolved value. + @rtype: any + @raise ConfigResolutionError: If resolution fails. + """ + rv = None + path = object.__getattribute__(container, 'path') + current = container + while current is not None: + if self.type == BACKTICK: + namespaces = object.__getattribute__(current, 'namespaces') + found = False + for ns in namespaces: + try: + rv = eval(str(self)[1:-1], vars(ns)) + found = True + break + except: + pass + if found: + break + else: + key = self.elements[0] + try: + rv = current[key] + for item in self.elements[1:]: + key = item[1] + rv = rv[key] + break + except: + rv = None + pass + current = object.__getattribute__(current, 'parent') + if current is None: + raise ConfigResolutionError("unable to evaluate %r in the configuration %s" % (self, path)) + return rv +
+ def __str__(self): + s = self.elements[0] + for tt, tv in self.elements[1:]: + if tt == DOT: + s += '.%s' % tv + else: + s += '[%r]' % tv + if self.type == BACKTICK: + return BACKTICK + s + BACKTICK + else: + return DOLLAR + s + + def __repr__(self): + return self.__str__() +
+
[docs]class Expression(object): + """ + This internal class implements a value which is obtained by evaluating an expression. + """ + def __init__(self, op, lhs, rhs): + """ + Initialize an instance. + + @param op: the operation expressed in the expression. + @type op: PLUS, MINUS, STAR, SLASH, MOD + @param lhs: the left-hand-side operand of the expression. + @type lhs: any Expression or primary value. + @param rhs: the right-hand-side operand of the expression. + @type rhs: any Expression or primary value. + """ + self.op = op + self.lhs = lhs + self.rhs = rhs + + def __str__(self): + return '%r %s %r' % (self.lhs, self.op, self.rhs) + + def __repr__(self): + return self.__str__() + +
[docs] def evaluate(self, container): + """ + Evaluate this instance in the context of a container. + + @param container: The container to evaluate in from. + @type container: L{Container} + @return: The evaluated value. + @rtype: any + @raise ConfigResolutionError: If evaluation fails. + @raise ZeroDivideError: If division by zero occurs. + @raise TypeError: If the operation is invalid, e.g. + subtracting one string from another. + """ + lhs = self.lhs + if isinstance(lhs, Reference): + lhs = lhs.resolve(container) + elif isinstance(lhs, Expression): + lhs = lhs.evaluate(container) + rhs = self.rhs + if isinstance(rhs, Reference): + rhs = rhs.resolve(container) + elif isinstance(rhs, Expression): + rhs = rhs.evaluate(container) + op = self.op + if op == PLUS: + rv = lhs + rhs + elif op == MINUS: + rv = lhs - rhs + elif op == STAR: + rv = lhs * rhs + elif op == SLASH: + rv = lhs / rhs + else: + rv = lhs % rhs + return rv +
+
[docs]class ConfigReader(object): + """ + This internal class implements a parser for configurations. + """ + + def __init__(self, config): + self.filename = None + self.config = config + self.lineno = 0 + self.colno = 0 + self.lastc = None + self.last_token = None + self.commentchars = '#' + self.whitespace = ' \t\r\n' + self.quotes = '\'"' + self.punct = ':-+*/%,.{}[]()@`$' + self.digits = '0123456789' + self.wordchars = '%s' % WORDCHARS # make a copy + self.identchars = self.wordchars + self.digits + self.pbchars = [] + self.pbtokens = [] + self.comment = None + +
[docs] def location(self): + """ + Return the current location (filename, line, column) in the stream + as a string. + + Used when printing error messages, + + @return: A string representing a location in the stream being read. + @rtype: str + """ + return "%s(%d,%d)" % (self.filename, self.lineno, self.colno) +
+
[docs] def getChar(self): + """ + Get the next char from the stream. Update line and column numbers + appropriately. + + @return: The next character from the stream. + @rtype: str + """ + if self.pbchars: + c = self.pbchars.pop() + if isinstance(c,bytes): + c = c.decode() + else: + c = self.stream.read(1) + if isinstance(c,bytes): + c = c.decode() + self.colno += 1 + if c == '\n': + self.lineno += 1 + self.colno = 1 + return c +
+ def __repr__(self): + return "<ConfigReader at 0x%08x>" % id(self) + + __str__ = __repr__ + +
[docs] def getToken(self): + """ + Get a token from the stream. String values are returned in a form + where you need to eval() the returned value to get the actual + string. The return value is (token_type, token_value). + + Multiline string tokenizing is thanks to David Janes (BlogMatrix) + + @return: The next token. + @rtype: A token tuple. + """ + if self.pbtokens: + return self.pbtokens.pop() + stream = self.stream + self.comment = None + token = '' + tt = EOF + while True: + c = self.getChar() + if not c: + break + elif c == '#': + if self.comment : + self.comment += '#' + stream.readline() + else : + self.comment = stream.readline() + self.lineno += 1 + continue + if c in self.quotes: + token = c + quote = c + tt = STRING + escaped = False + multiline = False + c1 = self.getChar() + if c1 == quote: + c2 = self.getChar() + if c2 == quote: + multiline = True + token += quote + token += quote + else: + self.pbchars.append(c2) + self.pbchars.append(c1) + else: + self.pbchars.append(c1) + while True: + c = self.getChar() + if not c: + break + token += c + if (c == quote) and not escaped: + if not multiline or (len(token) >= 6 and token.endswith(token[:3]) and token[-4] != '\\'): + break + if c == '\\': + escaped = not escaped + else: + escaped = False + if not c: + raise ConfigFormatError('%s: Unterminated quoted string: %r, %r' % (self.location(), token, c)) + break + if c in self.whitespace: + self.lastc = c + continue + elif c in self.punct: + token = c + tt = c + if (self.lastc == ']') or (self.lastc in self.identchars): + if c == '[': + tt = LBRACK2 + elif c == '(': + tt = LPAREN2 + break + elif c in self.digits: + token = c + tt = NUMBER + while True: + c = self.getChar() + if not c: + break + if c in self.digits: + token += c + elif (c == '.') and token.find('.') < 0: + token += c + else: + if c and (c not in self.whitespace): + self.pbchars.append(c) + break + break + elif c in self.wordchars: + token = c + tt = WORD + c = self.getChar() + while c and (c in self.identchars): + token += c + c = self.getChar() + if c: # and c not in self.whitespace: + self.pbchars.append(c) + if token == "True": + tt = TRUE + elif token == "False": + tt = FALSE + elif token == "None": + tt = NONE + break + else: + raise ConfigFormatError('%s: Unexpected character: %r' % (self.location(), c)) + if token: + self.lastc = token[-1] + else: + self.lastc = None + self.last_token = tt + + # Python 2.x specific unicode conversion + if sys.version_info[0] == 2 and tt == WORD and isinstance(token, unicode): + token = token.encode('ascii') + return (tt, token) +
+
[docs] def load(self, stream, parent=None, suffix=None): + """ + Load the configuration from the specified stream. + + @param stream: A stream from which to load the configuration. + @type stream: A stream (file-like object). + @param parent: The parent of the configuration (to which this reader + belongs) in the hierarchy. Specified when the configuration is + included in another one. + @type parent: A L{Container} instance. + @param suffix: The suffix of this configuration in the parent + configuration. Should be specified whenever the parent is not None. + @raise ConfigError: If parent is specified but suffix is not. + @raise ConfigFormatError: If there are syntax errors in the stream. + """ + if parent is not None: + if suffix is None: + raise ConfigError("internal error: load called with parent but no suffix") + self.config.setPath(makePath(object.__getattribute__(parent, 'path'), suffix)) + self.setStream(stream) + self.token = self.getToken() + self.parseMappingBody(self.config) + if self.token[0] != EOF: + raise ConfigFormatError('%s: expecting EOF, found %r' % (self.location(), self.token[1])) +
+
[docs] def setStream(self, stream): + """ + Set the stream to the specified value, and prepare to read from it. + + @param stream: A stream from which to load the configuration. + @type stream: A stream (file-like object). + """ + self.stream = stream + if hasattr(stream, 'name'): + filename = stream.name + else: + filename = '?' + self.filename = filename + self.lineno = 1 + self.colno = 1 +
+
[docs] def match(self, t): + """ + Ensure that the current token type matches the specified value, and + advance to the next token. + + @param t: The token type to match. + @type t: A valid token type. + @return: The token which was last read from the stream before this + function is called. + @rtype: a token tuple - see L{getToken}. + @raise ConfigFormatError: If the token does not match what's expected. + """ + if self.token[0] != t: + raise ConfigFormatError("%s: expecting %s, found %r" % (self.location(), t, self.token[1])) + rv = self.token + self.token = self.getToken() + return rv +
+
[docs] def parseMappingBody(self, parent): + """ + Parse the internals of a mapping, and add entries to the provided + L{Mapping}. + + @param parent: The mapping to add entries to. + @type parent: A L{Mapping} instance. + """ + while self.token[0] in [WORD, STRING]: + self.parseKeyValuePair(parent) +
+
[docs] def parseKeyValuePair(self, parent): + """ + Parse a key-value pair, and add it to the provided L{Mapping}. + + @param parent: The mapping to add entries to. + @type parent: A L{Mapping} instance. + @raise ConfigFormatError: if a syntax error is found. + """ + comment = self.comment + tt, tv = self.token + if tt == WORD: + key = tv + suffix = tv + elif tt == STRING: + key = eval(tv) + suffix = '[%s]' % tv + else: + msg = "%s: expecting word or string, found %r" + raise ConfigFormatError(msg % (self.location(), tv)) + self.token = self.getToken() + # for now, we allow key on its own as a short form of key : True + if self.token[0] == COLON: + self.token = self.getToken() + value = self.parseValue(parent, suffix) + else: + value = True + try: + parent.addMapping(key, value, comment) + except Exception as e: + raise ConfigFormatError("%s: %s, %r" % (self.location(), e, + self.token[1])) + tt = self.token[0] + if tt not in [EOF, WORD, STRING, RCURLY, COMMA]: + msg = "%s: expecting one of EOF, WORD, STRING, \ +RCURLY, COMMA, found %r" + raise ConfigFormatError(msg % (self.location(), self.token[1])) + if tt == COMMA: + self.token = self.getToken() +
+
[docs] def parseValue(self, parent, suffix): + """ + Parse a value. + + @param parent: The container to which the value will be added. + @type parent: A L{Container} instance. + @param suffix: The suffix for the value. + @type suffix: str + @return: The value + @rtype: any + @raise ConfigFormatError: if a syntax error is found. + """ + tt = self.token[0] + if tt in [STRING, WORD, NUMBER, LPAREN, DOLLAR, + TRUE, FALSE, NONE, BACKTICK, MINUS]: + rv = self.parseScalar() + elif tt == LBRACK: + rv = self.parseSequence(parent, suffix) + elif tt in [LCURLY, AT]: + rv = self.parseMapping(parent, suffix) + else: + raise ConfigFormatError("%s: unexpected input: %r" % + (self.location(), self.token[1])) + return rv +
+
[docs] def parseSequence(self, parent, suffix): + """ + Parse a sequence. + + @param parent: The container to which the sequence will be added. + @type parent: A L{Container} instance. + @param suffix: The suffix for the value. + @type suffix: str + @return: a L{Sequence} instance representing the sequence. + @rtype: L{Sequence} + @raise ConfigFormatError: if a syntax error is found. + """ + rv = Sequence(parent) + rv.setPath(makePath(object.__getattribute__(parent, 'path'), suffix)) + self.match(LBRACK) + comment = self.comment + tt = self.token[0] + while tt in [STRING, WORD, NUMBER, LCURLY, LBRACK, LPAREN, DOLLAR, + TRUE, FALSE, NONE, BACKTICK]: + suffix = '[%d]' % len(rv) + value = self.parseValue(parent, suffix) + rv.append(value, comment) + tt = self.token[0] + comment = self.comment + if tt == COMMA: + self.match(COMMA) + tt = self.token[0] + comment = self.comment + continue + self.match(RBRACK) + return rv +
+
[docs] def parseMapping(self, parent, suffix): + """ + Parse a mapping. + + @param parent: The container to which the mapping will be added. + @type parent: A L{Container} instance. + @param suffix: The suffix for the value. + @type suffix: str + @return: a L{Mapping} instance representing the mapping. + @rtype: L{Mapping} + @raise ConfigFormatError: if a syntax error is found. + """ + if self.token[0] == LCURLY: + self.match(LCURLY) + rv = Mapping(parent) + rv.setPath( + makePath(object.__getattribute__(parent, 'path'), suffix)) + self.parseMappingBody(rv) + self.match(RCURLY) + else: + self.match(AT) + _, fn = self.match(STRING) + rv = Config(eval(fn), parent) + return rv +
+
[docs] def parseScalar(self): + """ + Parse a scalar - a terminal value such as a string or number, or + an L{Expression} or L{Reference}. + + @return: the parsed scalar + @rtype: any scalar + @raise ConfigFormatError: if a syntax error is found. + """ + lhs = self.parseTerm() + tt = self.token[0] + while tt in [PLUS, MINUS]: + self.match(tt) + rhs = self.parseTerm() + lhs = Expression(tt, lhs, rhs) + tt = self.token[0] + return lhs +
+
[docs] def parseTerm(self): + """ + Parse a term in an additive expression (a + b, a - b) + + @return: the parsed term + @rtype: any scalar + @raise ConfigFormatError: if a syntax error is found. + """ + lhs = self.parseFactor() + tt = self.token[0] + while tt in [STAR, SLASH, MOD]: + self.match(tt) + rhs = self.parseFactor() + lhs = Expression(tt, lhs, rhs) + tt = self.token[0] + return lhs +
+
[docs] def parseFactor(self): + """ + Parse a factor in an multiplicative expression (a * b, a / b, a % b) + + @return: the parsed factor + @rtype: any scalar + @raise ConfigFormatError: if a syntax error is found. + """ + tt = self.token[0] + if tt in [NUMBER, WORD, STRING, TRUE, FALSE, NONE]: + rv = self.token[1] + if tt != WORD: + rv = eval(rv) + self.match(tt) + elif tt == LPAREN: + self.match(LPAREN) + rv = self.parseScalar() + self.match(RPAREN) + elif tt == DOLLAR: + self.match(DOLLAR) + rv = self.parseReference(DOLLAR) + elif tt == BACKTICK: + self.match(BACKTICK) + rv = self.parseReference(BACKTICK) + self.match(BACKTICK) + elif tt == MINUS: + self.match(MINUS) + rv = -self.parseScalar() + else: + raise ConfigFormatError("%s: unexpected input: %r" % + (self.location(), self.token[1])) + return rv +
+
[docs] def parseReference(self, type): + """ + Parse a reference. + + @return: the parsed reference + @rtype: L{Reference} + @raise ConfigFormatError: if a syntax error is found. + """ + word = self.match(WORD) + rv = Reference(self.config, type, word[1]) + while self.token[0] in [DOT, LBRACK2]: + self.parseSuffix(rv) + return rv +
+
[docs] def parseSuffix(self, ref): + """ + Parse a reference suffix. + + @param ref: The reference of which this suffix is a part. + @type ref: L{Reference}. + @raise ConfigFormatError: if a syntax error is found. + """ + tt = self.token[0] + if tt == DOT: + self.match(DOT) + word = self.match(WORD) + ref.addElement(DOT, word[1]) + else: + self.match(LBRACK2) + tt, tv = self.token + if tt not in [NUMBER, STRING]: + raise ConfigFormatError("%s: expected number or string, found %r" % (self.location(), tv)) + self.token = self.getToken() + tv = eval(tv) + self.match(RBRACK) + ref.addElement(LBRACK, tv) +
+
[docs]def defaultMergeResolve(map1, map2, key): + """\ + A default resolver for merge conflicts. + Returns a string indicating what action to take to resolve the conflict. + + @param map1: The map being merged into. + @type map1: L{Mapping}. + @param map2: The map being used as the merge operand. + @type map2: L{Mapping}. + @param key: The key in map2 (which also exists in map1). + @type key: str + + @return: One of "merge", "append", "mismatch" or "overwrite" + indicating what action should be taken. This should + be appropriate to the objects being merged - e.g. + there is no point returning "merge" if the two objects + are instances of L{Sequence}. + + @rtype: str + """ + obj1 = map1[key] + obj2 = map2[key] + if isinstance(obj1, Mapping) and isinstance(obj2, Mapping): + rv = "merge" + elif isinstance(obj1, Sequence) and isinstance(obj2, Sequence): + rv = "append" + else: + rv = "mismatch" + return rv +
+
[docs]def overwriteMergeResolve(map1, map2, key): + """ + An overwriting resolver for merge conflicts. Calls L{defaultMergeResolve}, + but where a "mismatch" is detected, returns "overwrite" instead. + + @param map1: The map being merged into. + @type map1: L{Mapping}. + @param map2: The map being used as the merge operand. + @type map2: L{Mapping}. + @param key: The key in map2 (which also exists in map1). + @type key: str + """ + rv = defaultMergeResolve(map1, map2, key) + if rv == "mismatch": + rv = "overwrite" + return rv +
+
[docs]def deepCopyMapping(inMapping): + res = Mapping() + for element in inMapping: + res[element] = inMapping[element] + return res +
+
[docs]class ConfigMerger(object): + """ + This class is used for merging two configurations. If a key exists in the + merge operand but not the merge target, then the entry is copied from the + merge operand to the merge target. If a key exists in both configurations, + then a resolver (a callable) is called to decide how to handle the + conflict. + """ + + def __init__(self, resolver=defaultMergeResolve): + """ + Initialise an instance. + + @param resolver: + @type resolver: A callable which takes the argument list + (map1, map2, key) where map1 is the mapping being merged into, + map2 is the merge operand and key is the clashing key. The callable + should return a string indicating how the conflict should be resolved. + For possible return values, see L{defaultMergeResolve}. The default + value preserves the old behaviour + """ + self.resolver = resolver + +
[docs] def merge(self, merged, mergee): + """ + Merge two configurations. The second configuration is unchanged, + and the first is changed to reflect the results of the merge. + + @param merged: The configuration to merge into. + @type merged: L{Config}. + @param mergee: The configuration to merge. + @type mergee: L{Config}. + """ + self.mergeMapping(merged, mergee) +
+
[docs] def overwriteKeys(self, map1, seq2): + """ + Renint variables. The second mapping is unchanged, + and the first is changed depending the keys of the second mapping. + @param map1: The mapping to reinit keys into. + @type map1: L{Mapping}. + @param map2: The mapping container reinit information. + @type map2: L{Mapping}. + """ + + overwrite_list = object.__getattribute__(seq2, 'data') + for overwrite_instruction in overwrite_list: + object.__setattr__(overwrite_instruction, 'parent', map1) + if "__condition__" in overwrite_instruction.keys(): + overwrite_condition = overwrite_instruction["__condition__"] + if eval(overwrite_condition, globals(), map1): + for key in overwrite_instruction.keys(): + if key == "__condition__": + continue + try: + exec( 'map1.' + key + " = " + repr(overwrite_instruction[key])) + except: + exec('map1.' + key + " = " + str(overwrite_instruction[key])) + else: + for key in overwrite_instruction.keys(): + try: + exec('map1.' + key + " = " + repr(overwrite_instruction[key])) + except: + exec('map1.' + key + " = " + str(overwrite_instruction[key])) +
+
[docs] def mergeMapping(self, map1, map2): + """ + Merge two mappings recursively. The second mapping is unchanged, + and the first is changed to reflect the results of the merge. + + @param map1: The mapping to merge into. + @type map1: L{Mapping}. + @param map2: The mapping to merge. + @type map2: L{Mapping}. + """ + keys = map1.keys() + global __resolveOverwrite__ + for key in map2.keys(): + if __resolveOverwrite__ and key == "__overwrite__": + self.overwriteKeys(map1,map2[key]) + + elif key not in keys: + map1[key] = map2[key] + if isinstance(map1[key], Container) : + object.__setattr__(map1[key], 'parent', map1) + else: + obj1 = map1[key] + obj2 = map2[key] + decision = self.resolver(map1, map2, key) + if decision == "merge": + self.mergeMapping(obj1, obj2) + elif decision == "append": + self.mergeSequence(obj1, obj2) + elif decision == "overwrite": + map1[key] = obj2 + if isinstance(map1[key], Container): + object.__setattr__(map1[key], 'parent', map1) + elif decision == "mismatch": + self.handleMismatch(obj1, obj2) + else: + msg = "unable to merge: don't know how to implement %r" + raise ValueError(msg % decision) +
+
[docs] def mergeSequence(self, seq1, seq2): + """ + Merge two sequences. The second sequence is unchanged, + and the first is changed to have the elements of the second + appended to it. + + @param seq1: The sequence to merge into. + @type seq1: L{Sequence}. + @param seq2: The sequence to merge. + @type seq2: L{Sequence}. + """ + data1 = object.__getattribute__(seq1, 'data') + data2 = object.__getattribute__(seq2, 'data') + for obj in data2: + data1.append(obj) + comment1 = object.__getattribute__(seq1, 'comments') + comment2 = object.__getattribute__(seq2, 'comments') + for obj in comment2: + comment1.append(obj) +
+
[docs] def handleMismatch(self, obj1, obj2): + """ + Handle a mismatch between two objects. + + @param obj1: The object to merge into. + @type obj1: any + @param obj2: The object to merge. + @type obj2: any + """ + raise ConfigError("unable to merge %r with %r" % (obj1, obj2)) +
+
[docs]class ConfigList(list): + """ + This class implements an ordered list of configurations and allows you + to try getting the configuration from each entry in turn, returning + the first successfully obtained value. + """ + +
[docs] def getByPath(self, path): + """ + Obtain a value from the first configuration in the list which defines + it. + + @param path: The path of the value to retrieve. + @type path: str + @return: The value from the earliest configuration in the list which + defines it. + @rtype: any + @raise ConfigError: If no configuration in the list has an entry with + the specified path. + """ + found = False + rv = None + for entry in self: + try: + rv = entry.getByPath(path) + found = True + break + except ConfigError: + pass + if not found: + raise ConfigError("unable to resolve %r" % path) + return rv
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/system.html b/doc/build/html/_modules/src/system.html new file mode 100644 index 0000000..e500c7a --- /dev/null +++ b/doc/build/html/_modules/src/system.html @@ -0,0 +1,311 @@ + + + + + + + + + src.system — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.system

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+'''
+In this file : all functions that do a system call, 
+like open a browser or an editor, or call a git command
+'''
+
+import subprocess
+import os
+import tarfile
+
+from . import printcolors
+
+
[docs]def show_in_editor(editor, filePath, logger): + '''open filePath using editor. + + :param editor str: The editor to use. + :param filePath str: The path to the file to open. + ''' + # default editor is vi + if editor is None or len(editor) == 0: + editor = 'vi' + + if '%s' not in editor: + editor += ' %s' + + try: + # launch cmd using subprocess.Popen + cmd = editor % filePath + logger.write('Launched command:\n' + cmd + '\n', 5) + p = subprocess.Popen(cmd, shell=True) + p.communicate() + except: + logger.write(printcolors.printcError(_("Unable to edit file %s\n") + % filePath), 1) + +
+
[docs]def git_extract(from_what, tag, where, logger, environment=None): + '''Extracts sources from a git repository. + + :param from_what str: The remote git repository. + :param tag str: The tag. + :param where str: The path where to extract. + :param logger Logger: The logger instance to use. + :param environment src.environment.Environ: The environment to source when + extracting. + :return: True if the extraction is successful + :rtype: boolean + ''' + if not where.exists(): + where.make() + if tag == "master" or tag == "HEAD": + command = "git clone %(remote)s %(where)s" % \ + { 'remote': from_what, 'tag': tag, 'where': str(where) } + else: + # NOTICE: this command only works with recent version of git + # because --work-tree does not work with an absolute path + where_git = os.path.join( str(where), ".git" ) + command = "rmdir %(where)s && git clone %(remote)s %(where)s && " + \ + "git --git-dir=%(where_git)s --work-tree=%(where)s checkout %(tag)s" + command = command % {'remote': from_what, + 'tag': tag, + 'where': str(where), + 'where_git': where_git } + + logger.write(command + "\n", 5) + + logger.logTxtFile.write("\n" + command + "\n") + logger.logTxtFile.flush() + res = subprocess.call(command, + cwd=str(where.dir()), + env=environment.environ.environ, + shell=True, + stdout=logger.logTxtFile, + stderr=subprocess.STDOUT) + return (res == 0) +
+
[docs]def archive_extract(from_what, where, logger): + '''Extracts sources from an archive. + + :param from_what str: The path to the archive. + :param where str: The path where to extract. + :param logger Logger: The logger instance to use. + :return: True if the extraction is successful + :rtype: boolean + ''' + try: + archive = tarfile.open(from_what) + for i in archive.getmembers(): + archive.extract(i, path=str(where)) + return True, os.path.commonprefix(archive.getnames()) + except Exception as exc: + logger.write("archive_extract: %s\n" % exc) + return False, None +
+
[docs]def cvs_extract(protocol, user, server, base, tag, product, where, + logger, checkout=False, environment=None): + '''Extracts sources from a cvs repository. + + :param protocol str: The cvs protocol. + :param user str: The user to be used. + :param server str: The remote cvs server. + :param base str: . + :param tag str: The tag. + :param product str: The product. + :param where str: The path where to extract. + :param logger Logger: The logger instance to use. + :param checkout boolean: If true use checkout cvs. + :param environment src.environment.Environ: The environment to source when + extracting. + :return: True if the extraction is successful + :rtype: boolean + ''' + + opttag = '' + if tag is not None and len(tag) > 0: + opttag = '-r ' + tag + + cmd = 'export' + if checkout: + cmd = 'checkout' + elif len(opttag) == 0: + opttag = '-DNOW' + + if len(protocol) > 0: + root = "%s@%s:%s" % (user, server, base) + command = "cvs -d :%(protocol)s:%(root)s %(command)s -d %(where)s %(tag)s %(product)s" % \ + { 'protocol': protocol, 'root': root, 'where': str(where.base()), + 'tag': opttag, 'product': product, 'command': cmd } + else: + command = "cvs -d %(root)s %(command)s -d %(where)s %(tag)s %(base)s/%(product)s" % \ + { 'root': server, 'base': base, 'where': str(where.base()), + 'tag': opttag, 'product': product, 'command': cmd } + + logger.write(command + "\n", 5) + + if not where.dir().exists(): + where.dir().make() + + logger.logTxtFile.write("\n" + command + "\n") + logger.logTxtFile.flush() + res = subprocess.call(command, + cwd=str(where.dir()), + env=environment.environ.environ, + shell=True, + stdout=logger.logTxtFile, + stderr=subprocess.STDOUT) + return (res == 0) +
+
[docs]def svn_extract(user, + from_what, + tag, + where, + logger, + checkout=False, + environment=None): + '''Extracts sources from a svn repository. + + :param user str: The user to be used. + :param from_what str: The remote git repository. + :param tag str: The tag. + :param where str: The path where to extract. + :param logger Logger: The logger instance to use. + :param checkout boolean: If true use checkout svn. + :param environment src.environment.Environ: The environment to source when + extracting. + :return: True if the extraction is successful + :rtype: boolean + ''' + if not where.exists(): + where.make() + + if checkout: + command = "svn checkout --username %(user)s %(remote)s %(where)s" % \ + { 'remote': from_what, 'user' : user, 'where': str(where) } + else: + command = "" + if os.path.exists(str(where)): + command = "/bin/rm -rf %(where)s && " % \ + { 'remote': from_what, 'where': str(where) } + + if tag == "master": + command += "svn export --username %(user)s %(remote)s %(where)s" % \ + { 'remote': from_what, 'user' : user, 'where': str(where) } + else: + command += "svn export -r %(tag)s --username %(user)s %(remote)s %(where)s" % \ + { 'tag' : tag, 'remote': from_what, 'user' : user, 'where': str(where) } + + logger.logTxtFile.write(command + "\n") + + logger.write(command + "\n", 5) + logger.logTxtFile.write("\n" + command + "\n") + logger.logTxtFile.flush() + res = subprocess.call(command, + cwd=str(where.dir()), + env=environment.environ.environ, + shell=True, + stdout=logger.logTxtFile, + stderr=subprocess.STDOUT) + return (res == 0)
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/template.html b/doc/build/html/_modules/src/template.html new file mode 100644 index 0000000..48ccb8e --- /dev/null +++ b/doc/build/html/_modules/src/template.html @@ -0,0 +1,123 @@ + + + + + + + + + src.template — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.template

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+import string
+
+
[docs]class MyTemplate(string.Template): + delimiter = '¤' +
+
[docs]def substitute(template_file, subst_dic): + template = open(template_file, 'r') + template = MyTemplate(template.read()) + + return template.safe_substitute(subst_dic) +
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/test_module.html b/doc/build/html/_modules/src/test_module.html new file mode 100644 index 0000000..ea3f4f3 --- /dev/null +++ b/doc/build/html/_modules/src/test_module.html @@ -0,0 +1,995 @@ + + + + + + + + + src.test_module — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.test_module

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+# Python 2/3 compatibility for execfile function
+try:
+    execfile
+except:
+    def execfile(somefile, global_vars, local_vars):
+        with open(somefile) as f:
+            code = compile(f.read(), somefile, 'exec')
+            exec(code, global_vars, local_vars)
+
+
+import os
+import sys
+import datetime
+import shutil
+import string
+import imp
+import subprocess
+
+from . import fork
+import src
+
+# directories not considered as test grids
+C_IGNORE_GRIDS = ['.git', '.svn', 'RESSOURCES']
+
+DEFAULT_TIMEOUT = 150
+
+# Get directory to be used for the temporary files.
+#
+
[docs]def getTmpDirDEFAULT(): + if src.architecture.is_windows(): + directory = os.getenv("TEMP") + else: + # for Linux: use /tmp/logs/{user} folder + directory = os.path.join( '/tmp', 'logs', os.getenv("USER", "unknown")) + return directory +
+
[docs]class Test: + def __init__(self, + config, + logger, + tmp_working_dir, + testbase="", + grids=None, + sessions=None, + launcher="", + show_desktop=True): + self.grids = grids + self.config = config + self.logger = logger + self.tmp_working_dir = tmp_working_dir + self.sessions = sessions + self.launcher = launcher + self.show_desktop = show_desktop + + res = self.prepare_testbase(testbase) + self.test_base_found = True + if res == 1: + # Fail + self.test_base_found = False + + self.settings = {} + self.known_errors = None + + # create section for results + self.config.TESTS = src.pyconf.Sequence(self.config) + + self.nb_run = 0 + self.nb_succeed = 0 + self.nb_timeout = 0 + self.nb_not_run = 0 + self.nb_acknoledge = 0 + + def _copy_dir(self, source, target): + if self.config.VARS.python >= "2.6": + shutil.copytree(source, target, + symlinks=True, + ignore=shutil.ignore_patterns('.git*','.svn*')) + else: + shutil.copytree(source, target, + symlinks=True) + +
[docs] def prepare_testbase_from_dir(self, testbase_name, testbase_dir): + self.logger.write(_("get test base from dir: %s\n") % \ + src.printcolors.printcLabel(testbase_dir), 3) + if not os.access(testbase_dir, os.X_OK): + raise src.SatException(_("testbase %(name)s (%(dir)s) does not " + "exist ...\n") % { 'name': testbase_name, + 'dir': testbase_dir }) + + self._copy_dir(testbase_dir, + os.path.join(self.tmp_working_dir, 'BASES', testbase_name)) +
+
[docs] def prepare_testbase_from_git(self, + testbase_name, + testbase_base, + testbase_tag): + self.logger.write( + _("get test base '%(testbase)s' with '%(tag)s' tag from git\n") % { + "testbase" : src.printcolors.printcLabel(testbase_name), + "tag" : src.printcolors.printcLabel(testbase_tag)}, + 3) + try: + def set_signal(): # pragma: no cover + """see http://bugs.python.org/issue1652""" + import signal + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + cmd = "git clone --depth 1 %(base)s %(dir)s" + cmd += " && cd %(dir)s" + if testbase_tag=='master': + cmd += " && git fetch origin %(branch)s" + else: + cmd += " && git fetch origin %(branch)s:%(branch)s" + cmd += " && git checkout %(branch)s" + cmd = cmd % { 'branch': testbase_tag, + 'base': testbase_base, + 'dir': testbase_name } + + self.logger.write("> %s\n" % cmd, 5) + if src.architecture.is_windows(): + # preexec_fn not supported on windows platform + res = subprocess.call(cmd, + cwd=os.path.join(self.tmp_working_dir, 'BASES'), + shell=True, + stdout=self.logger.logTxtFile, + stderr=subprocess.PIPE) + else: + res = subprocess.call(cmd, + cwd=os.path.join(self.tmp_working_dir, 'BASES'), + shell=True, + preexec_fn=set_signal, + stdout=self.logger.logTxtFile, + stderr=subprocess.PIPE) + if res != 0: + raise src.SatException(_("Error: unable to get test base " + "'%(name)s' from git '%(repo)s'.") % \ + { 'name': testbase_name, + 'repo': testbase_base }) + + except OSError: + self.logger.error(_("git is not installed. exiting...\n")) + sys.exit(0) +
+
[docs] def prepare_testbase_from_svn(self, user, testbase_name, testbase_base): + self.logger.write(_("get test base '%s' from svn\n") % \ + src.printcolors.printcLabel(testbase_name), 3) + try: + def set_signal(): # pragma: no cover + """see http://bugs.python.org/issue1652""" + import signal + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + cmd = "svn checkout --username %(user)s %(base)s %(dir)s" + cmd = cmd % { 'user': user, + 'base': testbase_base, + 'dir': testbase_name } + + # Get the application environment + self.logger.write(_("Set the application environment\n"), 5) + env_appli = src.environment.SalomeEnviron(self.config, + src.environment.Environ(dict(os.environ))) + env_appli.set_application_env(self.logger) + + self.logger.write("> %s\n" % cmd, 5) + if src.architecture.is_windows(): + # preexec_fn not supported on windows platform + res = subprocess.call(cmd, + cwd=os.path.join(self.tmp_working_dir, 'BASES'), + shell=True, + stdout=self.logger.logTxtFile, + stderr=subprocess.PIPE) + else: + res = subprocess.call(cmd, + cwd=os.path.join(self.tmp_working_dir, 'BASES'), + shell=True, + preexec_fn=set_signal, + stdout=self.logger.logTxtFile, + stderr=subprocess.PIPE, + env=env_appli.environ.environ,) + + if res != 0: + raise src.SatException(_("Error: unable to get test base '%(nam" + "e)s' from svn '%(repo)s'.") % \ + { 'name': testbase_name, + 'repo': testbase_base }) + + except OSError: + self.logger.error(_("svn is not installed. exiting...\n")) + sys.exit(0) + + ## + # Configure tests base.
+
[docs] def prepare_testbase(self, test_base_name): + src.printcolors.print_value(self.logger, + _("Test base"), + test_base_name, + 3) + self.logger.write("\n", 3, False) + + # search for the test base + test_base_info = None + for project_name in self.config.PROJECTS.projects: + project_info = self.config.PROJECTS.projects[project_name] + if "test_bases" not in project_info: + continue + for t_b_info in project_info.test_bases: + if t_b_info.name == test_base_name: + test_base_info = t_b_info + + if not test_base_info: + if os.path.exists(test_base_name): + self.prepare_testbase_from_dir("DIR", test_base_name) + self.currentTestBase = "DIR" + return 0 + + if not test_base_info: + message = (_("########## ERROR: test base '%s' not found\n") % + test_base_name) + self.logger.write("%s\n" % src.printcolors.printcError(message)) + return 1 + + if test_base_info.get_sources == "dir": + self.prepare_testbase_from_dir(test_base_name, + test_base_info.info.dir) + elif test_base_info.get_sources == "git": + self.prepare_testbase_from_git(test_base_name, + test_base_info.info.base, + self.config.APPLICATION.test_base.tag) + elif test_base_info.get_sources == "svn": + svn_user = src.get_cfg_param(test_base_info.info, + "svn_user", + self.config.USER.svn_user) + self.prepare_testbase_from_svn(svn_user, + test_base_name, + test_base_info.info.base) + else: + raise src.SatException(_("unknown source type '%(type)s' for test b" + "ase '%(base)s' ...\n") % { + 'type': test_base_info.get_sources, + 'base': test_base_name }) + + self.currentTestBase = test_base_name + + ## + # Searches if the script is declared in known errors pyconf. + # Update the status if needed.
+
[docs] def search_known_errors(self, status, test_grid, test_session, test): + test_path = os.path.join(test_grid, test_session, test) + if not src.config_has_application(self.config): + return status, [] + + if self.known_errors is None: + return status, [] + + platform = self.config.VARS.arch + application = self.config.VARS.application + error = self.known_errors.get_error(test_path, application, platform) + if error is None: + return status, [] + + if status == src.OK_STATUS: + if not error.fixed: + # the error is fixed + self.known_errors.fix_error(error) + #import testerror + #testerror.write_test_failures( + # self.config.TOOLS.testerror.file_path, + # self.known_errors.errors) + return status, [ error.date, + error.expected, + error.comment, + error.fixed ] + + if error.fixed: + self.known_errors.unfix_error(error) + #import testerror + #testerror.write_test_failures(self.config.TOOLS.testerror.file_path, + # self.known_errors.errors) + + delta = self.known_errors.get_expecting_days(error) + kfres = [ error.date, error.expected, error.comment, error.fixed ] + if delta < 0: + return src.KO_STATUS, kfres + return src.KNOWNFAILURE_STATUS, kfres + + ## + # Read the *.result.py files.
+
[docs] def read_results(self, listTest, has_timed_out): + results = {} + for test in listTest: + resfile = os.path.join(self.currentDir, + self.currentgrid, + self.currentsession, + test[:-3] + ".result.py") + + # check if <test>.result.py file exists + if not os.path.exists(resfile): + results[test] = ["?", -1, "", []] + else: + gdic, ldic = {}, {} + execfile(resfile, gdic, ldic) + + status = src.TIMEOUT_STATUS + if not has_timed_out: + status = src.KO_STATUS + + if ldic.has_key('status'): + status = ldic['status'] + + expected = [] + if status == src.KO_STATUS or status == src.OK_STATUS: + status, expected = self.search_known_errors(status, + self.currentgrid, + self.currentsession, + test) + + callback = "" + if ldic.has_key('callback'): + callback = ldic['callback'] + elif status == src.KO_STATUS: + callback = "CRASH" + + exec_time = -1 + if ldic.has_key('time'): + try: + exec_time = float(ldic['time']) + except: + pass + + results[test] = [status, exec_time, callback, expected] + + # check if <test>.py file exists + testfile = os.path.join(self.currentDir, + self.currentgrid, + self.currentsession, + test) + + if not os.path.exists(testfile): + results[test].append('') + else: + text = open(testfile, "r").read() + results[test].append(text) + + # check if <test>.out.py file exists + outfile = os.path.join(self.currentDir, + self.currentgrid, + self.currentsession, + test[:-3] + ".out.py") + + if not os.path.exists(outfile): + results[test].append('') + else: + text = open(outfile, "r").read() + results[test].append(text) + + return results + + ## + # Generates the script to be run by Salome. + # This python script includes init and close statements and a loop + # calling all the scripts of a single directory.
+
[docs] def generate_script(self, listTest, script_path, ignoreList): + # open template file + template_file = open(os.path.join(self.config.VARS.srcDir, + "test", + "scriptTemplate.py"), 'r') + template = string.Template(template_file.read()) + + # create substitution dictionary + d = dict() + d['resourcesWay'] = os.path.join(self.currentDir, 'RESSOURCES') + d['tmpDir'] = os.path.join(self.tmp_working_dir, 'WORK') + d['toolsWay'] = os.path.join(self.config.VARS.srcDir, "test") + d['sessionDir'] = os.path.join(self.currentDir, + self.currentgrid, + self.currentsession) + d['resultFile'] = os.path.join(self.tmp_working_dir, + 'WORK', + 'exec_result') + d['listTest'] = listTest + d['sessionName'] = self.currentsession + d['ignore'] = ignoreList + + # create script with template + script = open(script_path, 'w') + script.write(template.safe_substitute(d)) + script.close() + + # Find the getTmpDir function that gives access to *pidict file directory. + # (the *pidict file exists when SALOME is launched)
+
[docs] def get_tmp_dir(self): + # Rare case where there is no KERNEL in grid list + # (for example MED_STANDALONE) + if ('APPLICATION' in self.config + and 'KERNEL' not in self.config.APPLICATION.products + and 'KERNEL_ROOT_DIR' not in os.environ): + return getTmpDirDEFAULT + + # Case where "sat test" is launched in an existing SALOME environment + if 'KERNEL_ROOT_DIR' in os.environ: + root_dir = os.environ['KERNEL_ROOT_DIR'] + + if ('APPLICATION' in self.config + and 'KERNEL' in self.config.APPLICATION.products): + root_dir = src.product.get_product_config(self.config, + "KERNEL").install_dir + + # Case where there the appli option is called (with path to launcher) + if len(self.launcher) > 0: + # There are two cases : The old application (runAppli) + # and the new one + launcherName = os.path.basename(self.launcher) + launcherDir = os.path.dirname(self.launcher) + if launcherName == 'runAppli': + # Old application + cmd = ("for i in " + launcherDir + "/env.d/*.sh; do source ${i};" + " done ; echo $KERNEL_ROOT_DIR") + else: + # New application + cmd = ("echo -e 'import os\nprint os.environ[\"KERNEL_" + + "ROOT_DIR\"]' > tmpscript.py; %s shell" + + " tmpscript.py") % self.launcher + + # OP 14/11/2017 Ajout de traces pour essayer de decouvrir le pb + # de remontee de log des tests + #root_dir = subprocess.Popen(cmd, + # stdout=subprocess.PIPE, + # shell=True, + # executable='/bin/bash').communicate()[0].split()[-1] + subproc_res = subprocess.Popen(cmd, + stdout=subprocess.PIPE, + shell=True, + executable='/bin/bash').communicate() + #print "TRACES OP - test_module.py/Test.get_tmp_dir() subproc_res = " + for resLine in subproc_res: + print "- '#%s#'" %resLine + + root_dir = subproc_res[0].split()[-1] + + # OP 14/11/2017 Ajout de traces pour essayer de decouvrir le pb + # de remontee de log des tests + #print "TRACES OP - test_module.py/Test.get_tmp_dir() root_dir = '#%s#'" %root_dir + + # import grid salome_utils from KERNEL that gives + # the right getTmpDir function + (file_, pathname, description) = imp.find_module("salome_utils", + [os.path.join(root_dir, + 'bin', + 'salome')]) + try: + grid = imp.load_module("salome_utils", + file_, + pathname, + description) + return grid.getLogDir + except: + grid = imp.load_module("salome_utils", + file_, + pathname, + description) + return grid.getTmpDir + finally: + if file_: + file_.close() + +
+
[docs] def get_test_timeout(self, test_name, default_value): + if ("timeout" in self.settings and + test_name in self.settings["timeout"]): + return self.settings["timeout"][test_name] + + return default_value +
+
[docs] def generate_launching_commands(self): + # Case where "sat test" is launched in an existing SALOME environment + if 'KERNEL_ROOT_DIR' in os.environ: + binSalome = "runSalome" + binPython = "python" + killSalome = "killSalome.py" + + # Rare case where there is no KERNEL in grid list + # (for example MED_STANDALONE) + if ('APPLICATION' in self.config and + 'KERNEL' not in self.config.APPLICATION.products): + binSalome = "runSalome" + binPython = "python" + killSalome = "killSalome.py" + src.environment.load_environment(self.config, False, self.logger) + return binSalome, binPython, killSalome + + # Case where there the appli option is called (with path to launcher) + if len(self.launcher) > 0: + # There are two cases : The old application (runAppli) + # and the new one + launcherName = os.path.basename(self.launcher) + launcherDir = os.path.dirname(self.launcher) + if launcherName == 'runAppli': + # Old application + binSalome = self.launcher + binPython = ("for i in " + + launcherDir + + "/env.d/*.sh; do source ${i}; done ; python") + killSalome = ("for i in " + + launcherDir + + "/env.d/*.sh; do source ${i}; done ; killSalome.py'") + return binSalome, binPython, killSalome + else: + # New application + binSalome = self.launcher + binPython = self.launcher + ' shell' + killSalome = self.launcher + ' killall' + return binSalome, binPython, killSalome + + # SALOME version detection and APPLI repository detection + VersionSalome = src.get_salome_version(self.config) + appdir = 'APPLI' + if "APPLI" in self.config and "application_name" in self.config.APPLI: + appdir = self.config.APPLI.application_name + + # Case where SALOME has NOT the launcher that uses the SalomeContext API + if VersionSalome < 730: + binSalome = os.path.join(self.config.APPLICATION.workdir, + appdir, + "runAppli") + binPython = "python" + killSalome = "killSalome.py" + src.environment.load_environment(self.config, False, self.logger) + return binSalome, binPython, killSalome + + # Case where SALOME has the launcher that uses the SalomeContext API + else: + launcher_name = src.get_launcher_name(self.config) + binSalome = os.path.join(self.config.APPLICATION.workdir, + launcher_name) + + binPython = binSalome + ' shell' + killSalome = binSalome + ' killall' + return binSalome, binPython, killSalome + + return binSalome, binPython, killSalome + + + ## + # Runs tests of a session (using a single instance of Salome).
+
[docs] def run_tests(self, listTest, ignoreList): + out_path = os.path.join(self.currentDir, + self.currentgrid, + self.currentsession) + sessionname = "%s/%s" % (self.currentgrid, self.currentsession) + time_out = self.get_test_timeout(sessionname, + DEFAULT_TIMEOUT) + + time_out_salome = DEFAULT_TIMEOUT + + # generate wrapper script + script_path = os.path.join(out_path, 'wrapperScript.py') + self.generate_script(listTest, script_path, ignoreList) + + tmpDir = self.get_tmp_dir() + + binSalome, binPython, killSalome = self.generate_launching_commands() + if self.settings.has_key("run_with_grids") \ + and self.settings["run_with_grids"].has_key(sessionname): + binSalome = (binSalome + + " -m %s" % self.settings["run_with_grids"][sessionname]) + + logWay = os.path.join(self.tmp_working_dir, "WORK", "log_cxx") + + status = False + elapsed = -1 + if self.currentsession.startswith("NOGUI_"): + # runSalome -t (bash) + status, elapsed = fork.batch(binSalome, self.logger, + os.path.join(self.tmp_working_dir, + "WORK"), + [ "-t", + "--shutdown-server=1", + script_path ], + delai=time_out, + log=logWay) + + elif self.currentsession.startswith("PY_"): + # python script.py + status, elapsed = fork.batch(binPython, self.logger, + os.path.join(self.tmp_working_dir, + "WORK"), + [script_path], + delai=time_out, log=logWay) + + else: + opt = "-z 0" + if self.show_desktop: opt = "--show-desktop=0" + status, elapsed = fork.batch_salome(binSalome, + self.logger, + os.path.join( + self.tmp_working_dir, + "WORK"), + [ opt, + "--shutdown-server=1", + script_path ], + getTmpDir=tmpDir, + fin=killSalome, + delai=time_out, + log=logWay, + delaiapp=time_out_salome) + + self.logger.write("status = %s, elapsed = %s\n" % (status, elapsed), + 5) + + # create the test result to add in the config object + test_info = src.pyconf.Mapping(self.config) + test_info.testbase = self.currentTestBase + test_info.grid = self.currentgrid + test_info.session = self.currentsession + test_info.script = src.pyconf.Sequence(self.config) + + script_results = self.read_results(listTest, elapsed == time_out) + for sr in sorted(script_results.keys()): + self.nb_run += 1 + + # create script result + script_info = src.pyconf.Mapping(self.config) + script_info.name = sr + script_info.res = script_results[sr][0] + script_info.time = script_results[sr][1] + if script_info.res == src.TIMEOUT_STATUS: + script_info.time = time_out + if script_info.time < 1e-3: script_info.time = 0 + + callback = script_results[sr][2] + if script_info.res != src.OK_STATUS and len(callback) > 0: + script_info.callback = callback + + kfres = script_results[sr][3] + if len(kfres) > 0: + script_info.known_error = src.pyconf.Mapping(self.config) + script_info.known_error.date = kfres[0] + script_info.known_error.expected = kfres[1] + script_info.known_error.comment = kfres[2] + script_info.known_error.fixed = kfres[3] + + script_info.content = script_results[sr][4] + script_info.out = script_results[sr][5] + + # add it to the list of results + test_info.script.append(script_info, '') + + # display the results + if script_info.time > 0: + exectime = "(%7.3f s)" % script_info.time + else: + exectime = "" + + sp = "." * (35 - len(script_info.name)) + self.logger.write(self.write_test_margin(3), 3) + self.logger.write("script %s %s %s %s\n" % ( + src.printcolors.printcLabel(script_info.name), + sp, + src.printcolors.printc(script_info.res), + exectime), 3, False) + if script_info and len(callback) > 0: + self.logger.write("Exception in %s\n%s\n" % \ + (script_info.name, + src.printcolors.printcWarning(callback)), 2, False) + + if script_info.res == src.OK_STATUS: + self.nb_succeed += 1 + elif script_info.res == src.KNOWNFAILURE_STATUS: + self.nb_acknoledge += 1 + elif script_info.res == src.TIMEOUT_STATUS: + self.nb_timeout += 1 + elif script_info.res == src.NA_STATUS: + self.nb_run -= 1 + elif script_info.res == "?": + self.nb_not_run += 1 + + self.config.TESTS.append(test_info, '') + + ## + # Runs all tests of a session.
+
[docs] def run_session_tests(self): + + self.logger.write(self.write_test_margin(2), 3) + self.logger.write("Session = %s\n" % src.printcolors.printcLabel( + self.currentsession), 3, False) + + # prepare list of tests to run + tests = os.listdir(os.path.join(self.currentDir, + self.currentgrid, + self.currentsession)) + tests = filter(lambda l: l.endswith(".py"), tests) + tests = sorted(tests, key=str.lower) + + # build list of known failures + cat = "%s/%s/" % (self.currentgrid, self.currentsession) + ignoreDict = {} + for k in self.ignore_tests.keys(): + if k.startswith(cat): + ignoreDict[k[len(cat):]] = self.ignore_tests[k] + + self.run_tests(tests, ignoreDict) + + ## + # Runs all tests of a grid.
+
[docs] def run_grid_tests(self): + self.logger.write(self.write_test_margin(1), 3) + self.logger.write("grid = %s\n" % src.printcolors.printcLabel( + self.currentgrid), 3, False) + + grid_path = os.path.join(self.currentDir, self.currentgrid) + + sessions = [] + if self.sessions is not None: + sessions = self.sessions # user choice + else: + # use all scripts in grid + sessions = filter(lambda l: l not in C_IGNORE_GRIDS, + os.listdir(grid_path)) + sessions = filter(lambda l: os.path.isdir(os.path.join(grid_path, + l)), sessions) + + sessions = sorted(sessions, key=str.lower) + for session_ in sessions: + if not os.path.exists(os.path.join(grid_path, session_)): + self.logger.write(self.write_test_margin(2), 3) + self.logger.write(src.printcolors.printcWarning("Session %s not" + " found" % session_) + "\n", 3, False) + else: + self.currentsession = session_ + self.run_session_tests() + + ## + # Runs test testbase.
+
[docs] def run_testbase_tests(self): + res_dir = os.path.join(self.currentDir, "RESSOURCES") + os.environ['PYTHONPATH'] = (res_dir + + os.pathsep + + os.environ['PYTHONPATH']) + os.environ['TT_BASE_RESSOURCES'] = res_dir + src.printcolors.print_value(self.logger, + "TT_BASE_RESSOURCES", + res_dir, + 4) + self.logger.write("\n", 4, False) + + self.logger.write(self.write_test_margin(0), 3) + testbase_label = "Test base = %s\n" % src.printcolors.printcLabel( + self.currentTestBase) + self.logger.write(testbase_label, 3, False) + self.logger.write("-" * len(src.printcolors.cleancolor(testbase_label)), + 3) + self.logger.write("\n", 3, False) + + # load settings + settings_file = os.path.join(res_dir, "test_settings.py") + if os.path.exists(settings_file): + gdic, ldic = {}, {} + execfile(settings_file, gdic, ldic) + self.logger.write(_("Load test settings\n"), 3) + self.settings = ldic['settings_dic'] + self.ignore_tests = ldic['known_failures_list'] + if isinstance(self.ignore_tests, list): + self.ignore_tests = {} + self.logger.write(src.printcolors.printcWarning("known_failur" + "es_list must be a dictionary (not a list)") + "\n", 1, False) + else: + self.ignore_tests = {} + self.settings.clear() + + # read known failures pyconf + if "testerror" in self.config.LOCAL: + #import testerror + #self.known_errors = testerror.read_test_failures( + # self.config.TOOLS.testerror.file_path, + # do_error=False) + pass + else: + self.known_errors = None + + if self.grids is not None: + grids = self.grids # given by user + else: + # select all the grids (i.e. directories) in the directory + grids = filter(lambda l: l not in C_IGNORE_GRIDS, + os.listdir(self.currentDir)) + grids = filter(lambda l: os.path.isdir( + os.path.join(self.currentDir, l)), + grids) + + grids = sorted(grids, key=str.lower) + for grid in grids: + if not os.path.exists(os.path.join(self.currentDir, grid)): + self.logger.write(self.write_test_margin(1), 3) + self.logger.write(src.printcolors.printcWarning( + "grid %s does not exist\n" % grid), 3, False) + else: + self.currentgrid = grid + self.run_grid_tests() +
+
[docs] def run_script(self, script_name): + if ('APPLICATION' in self.config and + script_name in self.config.APPLICATION): + script = self.config.APPLICATION[script_name] + if len(script) == 0: + return + + self.logger.write("\n", 2, False) + if not os.path.exists(script): + self.logger.write(src.printcolors.printcWarning("WARNING: scrip" + "t not found: %s" % script) + "\n", 2) + else: + self.logger.write(src.printcolors.printcHeader("----------- sta" + "rt %s" % script_name) + "\n", 2) + self.logger.write("Run script: %s\n" % script, 2) + subprocess.Popen(script, shell=True).wait() + self.logger.write(src.printcolors.printcHeader("----------- end" + " %s" % script_name) + "\n", 2) +
+
[docs] def run_all_tests(self): + initTime = datetime.datetime.now() + + self.run_script('test_setup') + self.logger.write("\n", 2, False) + + self.logger.write(src.printcolors.printcHeader( + _("=== STARTING TESTS")) + "\n", 2) + self.logger.write("\n", 2, False) + self.currentDir = os.path.join(self.tmp_working_dir, + 'BASES', + self.currentTestBase) + self.run_testbase_tests() + + # calculate total execution time + totalTime = datetime.datetime.now() - initTime + totalTime -= datetime.timedelta(microseconds=totalTime.microseconds) + self.logger.write("\n", 2, False) + self.logger.write(src.printcolors.printcHeader(_("=== END TESTS")), 2) + self.logger.write(" %s\n" % src.printcolors.printcInfo(str(totalTime)), + 2, + False) + + # + # Start the tests + # + self.run_script('test_cleanup') + self.logger.write("\n", 2, False) + + # evaluate results + res_count = "%d / %d" % (self.nb_succeed, + self.nb_run - self.nb_acknoledge) + + res_out = _("Tests Results: %(succeed)d / %(total)d\n") % \ + { 'succeed': self.nb_succeed, 'total': self.nb_run } + if self.nb_succeed == self.nb_run: + res_out = src.printcolors.printcSuccess(res_out) + else: + res_out = src.printcolors.printcError(res_out) + self.logger.write(res_out, 1) + + if self.nb_timeout > 0: + self.logger.write(_("%d tests TIMEOUT\n") % self.nb_timeout, 1) + res_count += " TO: %d" % self.nb_timeout + if self.nb_not_run > 0: + self.logger.write(_("%d tests not executed\n") % self.nb_not_run, 1) + res_count += " NR: %d" % self.nb_not_run + + status = src.OK_STATUS + if self.nb_run - self.nb_succeed - self.nb_acknoledge > 0: + status = src.KO_STATUS + elif self.nb_acknoledge: + status = src.KNOWNFAILURE_STATUS + + self.logger.write(_("Status: %s\n" % status), 3) + + return self.nb_run - self.nb_succeed - self.nb_acknoledge + + ## + # Write margin to show test results.
+
[docs] def write_test_margin(self, tab): + if tab == 0: + return "" + return "| " * (tab - 1) + "+ " +
+ +
+
+ +
+
+
+

Related Topics

+ +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/doc/build/html/_modules/src/xmlManager.html b/doc/build/html/_modules/src/xmlManager.html new file mode 100644 index 0000000..1656e12 --- /dev/null +++ b/doc/build/html/_modules/src/xmlManager.html @@ -0,0 +1,307 @@ + + + + + + + + + src.xmlManager — salomeTools 5.0.0dev documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for src.xmlManager

+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+import os
+try: # For python2
+    import sys
+    reload(sys)  
+    sys.setdefaultencoding('utf8')
+except:
+    pass
+
+import src
+from . import ElementTree as etree
+
+
[docs]class XmlLogFile(object): + '''Class to manage writing in salomeTools xml log file + ''' + def __init__(self, filePath, rootname, attrib = {}): + '''Initialization + + :param filePath str: The path to the file where to write the log file + :param rootname str: The name of the root node of the xml file + :param attrib dict: the dictionary that contains the attributes + and value of the root node + ''' + # Initialize the filePath and ensure that the directory + # that contain the file exists (make it if necessary) + self.logFile = filePath + src.ensure_path_exists(os.path.dirname(filePath)) + # Initialize the field that contain the xml in memory + self.xmlroot = etree.Element(rootname, attrib = attrib) + +
[docs] def write_tree(self, stylesheet=None, file_path = None): + '''Write the xml tree in the log file path. Add the stylesheet if asked. + + :param stylesheet str: The stylesheet to apply to the xml file + ''' + log_file_path = self.logFile + if file_path: + log_file_path = file_path + try: + f = open(log_file_path, 'w') + f.write("<?xml version='1.0' encoding='utf-8'?>\n") + if stylesheet: + f.write("<?xml-stylesheet type='text/xsl' href='%s'?>\n" % + stylesheet) + f.write(etree.tostring(self.xmlroot, encoding='utf-8')) + f.close() + except IOError: + pass +
+
[docs] def add_simple_node(self, node_name, text=None, attrib={}): + '''Add a node with some attibutes and text to the root node. + + :param node_name str: the name of the node to add + :param text str: the text of the node + :param attrib dict: the dictionary containing the + attribute of the new node + ''' + n = etree.Element(node_name, attrib=attrib) + n.text = text + self.xmlroot.append(n) + return n +
+
[docs] def append_node_text(self, node_name, text): + '''Append a new text to the node that has node_name as name + + :param node_name str: The name of the node on which append text + :param text str: The text to append + ''' + # find the corresponding node + for field in self.xmlroot: + if field.tag == node_name: + # append the text + field.text += text +
+
[docs] def append_node_attrib(self, node_name, attrib): + '''Append a new attributes to the node that has node_name as name + + :param node_name str: The name of the node on which append text + :param attrib dixt: The attrib to append + ''' + self.xmlroot.find(node_name).attrib.update(attrib) +
+
[docs]class ReadXmlFile(object): + '''Class to manage reading of an xml log file + ''' + def __init__(self, filePath): + '''Initialization + + :param filePath str: The xml file to be read + ''' + self.filePath = filePath + etree_inst = etree.parse(filePath) + self.xmlroot = etree_inst.parse(filePath) + +
[docs] def getRootAttrib(self): + '''Get the attibutes of the self.xmlroot + + :return: The attributes of the root node + :rtype: dict + ''' + return self.xmlroot.attrib +
+
[docs] def get_attrib(self, node_name): + '''Get the attibutes of the node node_name in self.xmlroot + + :param node_name str: the name of the node + :return: the attibutes of the node node_name in self.xmlroot + :rtype: dict + ''' + attrib = self.xmlroot.find(node_name).attrib + # To be python 3 compatible, convert bytes to str if there are any + fixedAttrib = {} + for k in attrib.keys(): + if isinstance(k, bytes): + key = k.decode() + else: + key = k + if isinstance(attrib[k], bytes): + value = attrib[k].decode() + else: + value = attrib[k] + fixedAttrib[key] = value + return fixedAttrib +
+
[docs] def get_node_text(self, node): + '''Get the text of the first node that has name + that corresponds to the parameter node + + :param node str: the name of the node from which get the text + :return: the text of the first node that has name + that corresponds to the parameter node + :rtype: str + ''' + return self.xmlroot.find(node).text +
+
[docs]def add_simple_node(root_node, node_name, text=None, attrib={}): + '''Add a node with some attibutes and text to the root node. + + :param root_node etree.Element: the Etree element where to add the new node + :param node_name str: the name of the node to add + :param text str: the text of the node + :param attrib dict: the dictionary containing the + attribute of the new node + ''' + n = etree.Element(node_name, attrib=attrib) + n.text = text + root_node.append(n) + return n +
+
[docs]def append_node_attrib(root_node, attrib): + '''Append a new attributes to the node that has node_name as name + + :param root_node etree.Element: the Etree element + where to append the new attibutes + :param attrib dixt: The attrib to append + ''' + root_node.attrib.update(attrib) +
+
[docs]def find_node_by_attrib(xmlroot, name_node, key, value): + '''Find the nfirst ode from xmlroot that has name name_node and that has in + its attributes {key : value}. Return the node + + :param xmlroot etree.Element: the Etree element where to search + :param name_node str: the name of node to search + :param key str: the key to search + :param value str: the value to search + :return: the found node + :rtype: xmlroot etree.Element + ''' + l_nodes = xmlroot.findall(name_node) + for node in l_nodes: + if key not in node.attrib.keys(): + continue + if node.attrib[key] == value: + return node + return None + +
+
[docs]def write_report(filename, xmlroot, stylesheet): + """Writes a report file from a XML tree. + + :param filename str: The path to the file to create + :param xmlroot etree.Element: the Etree element to write to the file + :param stylesheet str: The stylesheet to add to the begin of the file + """ + if not os.path.exists(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + + f = open(filename, "w") + f.write("<?xml version='1.0' encoding='utf-8'?>\n") + if len(stylesheet) > 0: + f.write("<?xml-stylesheet type='text/xsl' href='%s'?>\n" % stylesheet) + f.write(etree.tostring(xmlroot, encoding='utf-8')) + f.close() +
+
+ +
+
+
+
+
+
+

Related Topics

+ +
+ + +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/doc/build/html/_sources/commands/apidoc/modules.txt b/doc/build/html/_sources/commands/apidoc/modules.txt new file mode 100644 index 0000000..e9ff8ac --- /dev/null +++ b/doc/build/html/_sources/commands/apidoc/modules.txt @@ -0,0 +1,7 @@ +src +=== + +.. toctree:: + :maxdepth: 4 + + src diff --git a/doc/build/html/_sources/commands/apidoc/src.colorama.txt b/doc/build/html/_sources/commands/apidoc/src.colorama.txt new file mode 100644 index 0000000..ba8c5f6 --- /dev/null +++ b/doc/build/html/_sources/commands/apidoc/src.colorama.txt @@ -0,0 +1,51 @@ +colorama Package +================ + +:mod:`colorama` Package +----------------------- + +.. automodule:: src.colorama + :members: + :undoc-members: + :show-inheritance: + +:mod:`ansi` Module +------------------ + +.. automodule:: src.colorama.ansi + :members: + :undoc-members: + :show-inheritance: + +:mod:`ansitowin32` Module +------------------------- + +.. automodule:: src.colorama.ansitowin32 + :members: + :undoc-members: + :show-inheritance: + +:mod:`initialise` Module +------------------------ + +.. automodule:: src.colorama.initialise + :members: + :undoc-members: + :show-inheritance: + +:mod:`win32` Module +------------------- + +.. automodule:: src.colorama.win32 + :members: + :undoc-members: + :show-inheritance: + +:mod:`winterm` Module +--------------------- + +.. automodule:: src.colorama.winterm + :members: + :undoc-members: + :show-inheritance: + diff --git a/doc/build/html/_sources/commands/apidoc/src.txt b/doc/build/html/_sources/commands/apidoc/src.txt new file mode 100644 index 0000000..ac8627e --- /dev/null +++ b/doc/build/html/_sources/commands/apidoc/src.txt @@ -0,0 +1,146 @@ +src Package +=========== + +:mod:`src` Package +------------------ + +.. automodule:: src.__init__ + :members: + :undoc-members: + :show-inheritance: + +:mod:`ElementTree` Module +------------------------- + +.. automodule:: src.ElementTree + :members: + :undoc-members: + :show-inheritance: + +:mod:`architecture` Module +-------------------------- + +.. automodule:: src.architecture + :members: + :undoc-members: + :show-inheritance: + +:mod:`compilation` Module +------------------------- + +.. automodule:: src.compilation + :members: + :undoc-members: + :show-inheritance: + +:mod:`debug` Module +------------------- + +.. automodule:: src.debug + :members: + :undoc-members: + :show-inheritance: + +:mod:`environment` Module +------------------------- + +.. automodule:: src.environment + :members: + :undoc-members: + :show-inheritance: + +:mod:`fileEnviron` Module +------------------------- + +.. automodule:: src.fileEnviron + :members: + :undoc-members: + :show-inheritance: + +:mod:`fork` Module +------------------ + +.. automodule:: src.fork + :members: + :undoc-members: + :show-inheritance: + +:mod:`logger` Module +-------------------- + +.. automodule:: src.logger + :members: + :undoc-members: + :show-inheritance: + +:mod:`options` Module +--------------------- + +.. automodule:: src.options + :members: + :undoc-members: + :show-inheritance: + +:mod:`printcolors` Module +------------------------- + +.. automodule:: src.printcolors + :members: + :undoc-members: + :show-inheritance: + +:mod:`product` Module +--------------------- + +.. automodule:: src.product + :members: + :undoc-members: + :show-inheritance: + +:mod:`pyconf` Module +-------------------- + +.. automodule:: src.pyconf + :members: + :undoc-members: + :show-inheritance: + +:mod:`system` Module +-------------------- + +.. automodule:: src.system + :members: + :undoc-members: + :show-inheritance: + +:mod:`template` Module +---------------------- + +.. automodule:: src.template + :members: + :undoc-members: + :show-inheritance: + +:mod:`test_module` Module +------------------------- + +.. automodule:: src.test_module + :members: + :undoc-members: + :show-inheritance: + +:mod:`xmlManager` Module +------------------------ + +.. automodule:: src.xmlManager + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + + src.colorama + diff --git a/doc/build/html/_sources/commands/application.txt b/doc/build/html/_sources/commands/application.txt new file mode 100644 index 0000000..2052da0 --- /dev/null +++ b/doc/build/html/_sources/commands/application.txt @@ -0,0 +1,55 @@ + +.. include:: ../../rst_prolog.rst + +Command application +********************* + +Description +=========== +The **application** command creates a virtual SALOME_ application. +Virtual SALOME applications are used to start SALOME when distribution is needed. + +Usage +===== +* Create an application: :: + + sat application + + Create the virtual application directory in the salomeTool application directory ``$APPLICATION.workdir``. + +* Give a name to the application: :: + + sat application --name + + *Remark*: this option overrides the name given in the virtual_app section of the configuration file ``$APPLICATION.virtual_app.name``. + +* Change the directory where the application is created: :: + + sat application --target + +* Set a specific SALOME_ resources catalog (it will be used for the distribution of components on distant machines): :: + + sat application --catalog + + Note that the catalog specified will be copied to the application directory. + +* Generate the catalog for a list of machines: :: + + sat application --gencat machine1,machine2,machine3 + + This will create a catalog by querying each machine through ssh protocol (memory, number of processor) with ssh. + +* Generate a mesa application (if mesa and llvm are parts of the application). Use this option only if you have to use salome through ssh and have problems with ssh X forwarding of OpengGL modules (like Paravis): :: + + sat launcher --use_mesa + +Some useful configuration pathes +================================= + +The virtual application can be configured with the virtual_app section of the configutation file. + +* **APPLICATION.virtual_app** + + * **name** : name of the launcher (to replace the default runAppli). + * **application_name** : (optional) the name of the virtual application directory, if missing the default value is ``$name + _appli``. + diff --git a/doc/build/html/_sources/commands/clean.txt b/doc/build/html/_sources/commands/clean.txt new file mode 100644 index 0000000..e5d2f38 --- /dev/null +++ b/doc/build/html/_sources/commands/clean.txt @@ -0,0 +1,61 @@ + +.. include:: ../../rst_prolog.rst + +Command clean +**************** + +Description +============ + +The **clean** command removes products in the *source, build, or install* directories of an application. Theses directories are usually named ``SOURCES, BUILD, INSTALL``. + +Use the options to define what directories you want to suppress and to set the list of products + + +Usage +======= + +* Clean all previously created *build* and *install* directories (example application as *SALOME_xx*): + + .. code-block:: bash + + # take care, is long time to restore, sometimes + sat clean SALOME-xx --build --install + +* Clean previously created *build* and *install* directories, only for products with property *is_salome_module*: + + .. code-block:: bash + + sat clean SALOME-xxx --build --install \ + --properties is_salome_module:yes + + +Availables options +====================== + + * **--products** : Products to clean. + + * **--properties** : + + | Filter the products by their properties. + | Syntax: *--properties :* + + * **--sources** : Clean the product source directories. + + * **--build** : Clean the product build directories. + + * **--install** : Clean the product install directories. + + * **--all** : Clean the product source, build and install directories. + + * **--sources_without_dev** : + + | Do not clean the products in development mode, + | (they could have VCS_ commits pending). + + + +Some useful configuration pathes +================================= + +No specific configuration. diff --git a/doc/build/html/_sources/commands/compile.txt b/doc/build/html/_sources/commands/compile.txt new file mode 100644 index 0000000..915705e --- /dev/null +++ b/doc/build/html/_sources/commands/compile.txt @@ -0,0 +1,75 @@ + +.. include:: ../../rst_prolog.rst + +Command compile +**************** + +Description +=========== +The **compile** command allows compiling the products of a SALOME_ application. + + +Usage +===== +* Compile a complete application: :: + + sat compile + +* Compile only some products: :: + + sat compile --products , ... + +* Use *sat -t* to duplicate the logs in the terminal (by default the log are stored and displayed with *sat log* command): :: + + sat -t compile --products + +* Compile a module and its dependencies: :: + + sat compile --products med --with_fathers + +* Compile a module and the modules depending on it (for example plugins): :: + + sat compile --products med --with_children + +* Clean the build and install directories before starting compilation: :: + + sat compile --products GEOM --clean_all + + .. note:: | a warning will be shown if option *--products* is missing + | (as it will clean everything) + +* Clean only the install directories before starting compilation: :: + + sat compile --clean_install + +* Add options for make: :: + + sat compile --products --make_flags + +* Use the *--check* option to execute the unit tests after compilation: :: + + sat compile --check + +* Remove the build directory after successful compilation (some build directory like qt are big): :: + + sat compile --products qt --clean_build_after + +* Stop the compilation as soon as the compilation of a module fails: :: + + sat compile --stop_first_fail + +* Do not compile, just show if products are installed or not, and where is the installation: :: + + sat compile --show + + +Some useful configuration pathes +================================= + +The way to compile a product is defined in the *pyconf file configuration*. +The main options are: + + * **build_source** : the method used to build the product (cmake/autotools/script) + * **compil_script** : the compilation script if build_source is equal to "script" + * **cmake_options** : additional options for cmake. + * **nb_proc** : number of jobs to use with make for this product. diff --git a/doc/build/html/_sources/commands/config.txt b/doc/build/html/_sources/commands/config.txt new file mode 100644 index 0000000..79a4a46 --- /dev/null +++ b/doc/build/html/_sources/commands/config.txt @@ -0,0 +1,89 @@ + +.. include:: ../../rst_prolog.rst + +Command config +****************** + +Description +=========== +The **config** command manages sat configuration. +It allows display, manipulation and operation on configuration files + +Usage +===== +* Edit the user personal configuration file ``$HOME/.salomeTools/SAT.pyconf``. It is used to store the user personal choices, like the favorite editor, browser, pdf viewer: :: + + sat config --edit + +* List the available applications (they come from the sat projects defined in ``data/local.pyconf``: :: + + sat config --list + +* Edit the configuration of an application: :: + + sat config --edit + +* Copy an application configuration file into the user personal directory: :: + + sat config --copy [new_name] + +* | Print the value of a configuration parameter. + | Use the automatic completion to get recursively the parameter names. + | Use *--no_label* option to get *only* the value, *without* label (useful in automatic scripts). + | Examples (with *SALOME-xx* as *SALOME-8.4.0* ): + + .. code-block:: bash + + # sat config --value + sat config --value . # all the configuration + sat config --value LOCAL + sat config --value LOCAL.workdir + + # sat config --value + sat config SALOME-xx --value APPLICATION.workdir + sat config SALOME-xx --no_label --value APPLICATION.workdir + +* | Print in one-line-by-value mode the value of a configuration parameter, + | with its source *expression*, if any. + | This is a debug mode, useful for developers. + | Prints the parameter path, the source expression if any, and the final value: + + :: + + sat config SALOME-xx -g USER + + .. note:: And so, *not only for fun*, to get **all expressions** of configuration + + .. code-block:: bash + + sat config SALOME-xx -g . | grep -e "-->" + + +* Print the patches that are applied: :: + + sat config SALOME-xx --show_patchs + +* Get information on a product configuration: + + .. code-block:: bash + + # sat config --info + sat config SALOME-xx --info KERNEL + sat config SALOME-xx --info qt + +Some useful configuration pathes +================================= + +Exploring a current configuration. + +* **PATHS**: To get list of directories where to find files. + +* **USER**: To get user preferences (editor, pdf viewer, web browser, default working dir). + +sat commands: :: + + sat config SALOME-xx -v PATHS + sat config SALOME-xx -v USERS + + + diff --git a/doc/build/html/_sources/commands/environ.txt b/doc/build/html/_sources/commands/environ.txt new file mode 100644 index 0000000..13b9508 --- /dev/null +++ b/doc/build/html/_sources/commands/environ.txt @@ -0,0 +1,139 @@ + +.. include:: ../../rst_prolog.rst + +Command environ +**************** + +Description +=========== +The **environ** command generates the environment files used +to run and compile your application (as SALOME_ is an example). + +.. note :: + these files are **not** required, + salomeTool set the environment himself, when compiling. + And so does the salome launcher. + + These files are useful when someone wants to check the environment. + They could be used in debug mode to set the environment for *gdb*. + +The configuration part at the end of this page explains how +to specify the environment used by sat (at build or run time), +and saved in some files by *sat environ* command. + +Usage +===== +* Create the shell environment files of the application: :: + + sat environ + +* Create the environment files of the application for a given shell. + Options are bash, bat (for windows) and cfg (the configuration format used by SALOME_): :: + + sat environ --shell [bash|cfg|all] + +* Use a different prefix for the files (default is 'env'): + + .. code-block:: bash + + # This will create file _launch.sh, _build.sh + sat environ --prefix + +* Use a different target directory for the files: + + .. code-block:: bash + + # This will create file env_launch.sh, env_build.sh + # in the directory corresponding to + sat environ --target + +* Generate the environment files only with the given products: + + .. code-block:: bash + + # This will create the environment files only for the given products + # and their prerequisites. + # It is useful when you want to visualise which environment uses + # sat to compile a given product. + sat environ --product ,, ... + + +Configuration +============= + +The specification of the environment can be done through several mechanisms. + +1. For salome products (the products with the property ``is_SALOME_module`` as ``yes``) the environment is set automatically by sat, in respect with SALOME_ requirements. + +2. For other products, the environment is set with the use of the environ section within the pyconf file of the product. The user has two possibilities, either set directly the environment within the section, or specify a python script which wil be used to set the environment programmatically. + +Within the section, the user can define environment variables. He can also modify PATH variables, by appending or prepending directories. +In the following example, we prepend */lib* to ``LD_LIBRARY_PATH`` (note the *left first* underscore), append */lib* to ``PYTHONPATH`` (note the *right last* underscore), and set ``LAPACK_ROOT_DIR`` to **: + +.. code-block:: python + + environ : + { + _LD_LIBRARY_PATH : $install_dir + $VARS.sep + "lib" + PYTHONPATH_ : $install_dir + $VARS.sep + "lib" + LAPACK_ROOT_DIR : $install_dir + } + +It is possible to distinguish the build environment from the launch environment: use a subsection called *build* or *launch*. In the example below, ``LD_LIBRARY_PATH`` and ``PYTHONPATH`` are only modified at run time, not at compile time: + +.. code-block:: python + + environ : + { + build : + { + LAPACK_ROOT_DIR : $install_dir + } + launch : + { + LAPACK_ROOT_DIR : $install_dir + _LD_LIBRARY_PATH : $install_dir + $VARS.sep + "lib" + PYTHONPATH_ : $install_dir + $VARS.sep + "lib" + } + } + +3. The last possibility is to set the environment with a python script. The script should be provided in the *products/env_scripts* directory of the sat project, and its name is specified in the environment section with the key ``environ.env_script``: + +.. code-block:: python + + environ : + { + env_script : 'lapack.py' + } + +Please note that the two modes are complementary and are both taken into account. +Most of the time, the first mode is sufficient. + +The second mode can be used when the environment has to be set programmatically. +The developer implements a handle (as a python method) +which is called by sat to set the environment. +Here is an example: + +.. code-block:: python + + + #!/usr/bin/env python + #-*- coding:utf-8 -*- + + import os.path + import platform + + def set_env(env, prereq_dir, version): + env.set("TRUST_ROOT_DIR",prereq_dir) + env.prepend('PATH', os.path.join(prereq_dir, 'bin')) + env.prepend('PATH', os.path.join(prereq_dir, 'include')) + env.prepend('LD_LIBRARY_PATH', os.path.join(prereq_dir, 'lib')) + return + +SalomeTools defines four handles: + +* **set_env(env, prereq_dir, version)** : used at build and run time. +* **set_env_launch(env, prereq_dir, version)** : used only at run time (if defined!) +* **set_env_build(env, prereq_dir, version)** : used only at build time (if defined!) +* **set_native_env(env)** : used only for native products, at build and run time. + diff --git a/doc/build/html/_sources/commands/generate.txt b/doc/build/html/_sources/commands/generate.txt new file mode 100644 index 0000000..f753261 --- /dev/null +++ b/doc/build/html/_sources/commands/generate.txt @@ -0,0 +1,39 @@ + +.. include:: ../../rst_prolog.rst + +Command generate +**************** + +Description +=========== +The **generate** command generates and compile SALOME modules from cpp modules using YACSGEN. + +.. note:: This command uses YACSGEN to generate the module. It needs to be specified with *--yacsgen* option, or defined in the product or by the environment variable ``$YACSGEN_ROOT_DIR``. + + +Remarks +======= +* This command will only apply on the CPP modules of the application, those who have both properties: :: + + cpp : "yes" + generate : "yes" + +* The cpp module are usually computational components, and the generated module brings the CORBA layer which allows distributing the compononent on remore machines. cpp modules should conform to YACSGEN/hxx2salome requirements (please refer to YACSGEN documentation) + + +Usage +===== +* Generate all the modules of a product: :: + + sat generate + +* Generate only specific modules: :: + + sat generate --products + + Remark: modules which don't have the *generate* property are ignored. + +* Use a specific version of YACSGEN: :: + + sat generate --yacsgen + diff --git a/doc/build/html/_sources/commands/launcher.txt b/doc/build/html/_sources/commands/launcher.txt new file mode 100644 index 0000000..864a31a --- /dev/null +++ b/doc/build/html/_sources/commands/launcher.txt @@ -0,0 +1,52 @@ + +.. include:: ../../rst_prolog.rst + +Command launcher +****************** + +Description +=========== +The **launcher** command creates a SALOME launcher, a python script file to start SALOME_. + + +Usage +===== +* Create a launcher: :: + + sat launcher + + Generate a launcher in the application directory, i.e ``$APPLICATION.workdir``. + +* Create a launcher with a given name (default name is ``APPLICATION.profile.launcher_name``) :: + + sat launcher --name ZeLauncher + + The launcher will be called *ZeLauncher*. + +* Set a specific resources catalog: :: + + sat launcher --catalog + + Note that the catalog specified will be copied to the profile directory. + +* Generate the catalog for a list of machines: :: + + sat launcher --gencat + + This will create a catalog by querying each machine (memory, number of processor) with ssh. + +* Generate a mesa launcher (if mesa and llvm are parts of the application). Use this option only if you have to use salome through ssh and have problems with ssh X forwarding of OpengGL modules (like Paravis): :: + + sat launcher --use_mesa + + +Configuration +============= + +Some useful configuration pathes: + +* **APPLICATION.profile** + + * **product** : the name of the profile product (the product in charge of holding the application stuff, like logos, splashscreen) + * **launcher_name** : the name of the launcher. + diff --git a/doc/build/html/_sources/commands/log.txt b/doc/build/html/_sources/commands/log.txt new file mode 100644 index 0000000..9908f4b --- /dev/null +++ b/doc/build/html/_sources/commands/log.txt @@ -0,0 +1,46 @@ + +.. include:: ../../rst_prolog.rst + +Command log +**************** + +Description +=========== +The **log** command displays sat log in a web browser or in a terminal. + +Usage +===== +* Show (in a web browser) the log of the commands corresponding to an application: :: + + sat log + +* Show the log for commands that do not use any application: :: + + sat log + +* The --terminal (or -t) display the log directly in the terminal, through a CLI_ interactive menu: :: + + sat log --terminal + +* The --last option displays only the last command: :: + + sat log --last + +* To access the last compilation log in terminal mode, use --last_terminal option: :: + + sat log --last_terminal + +* The --clean (int) option erases the n older log files and print the number of remaining log files: :: + + sat log --clean 50 + + + +Some useful configuration pathes +================================= + +* **USER** + + * **browser** : The browser used to show the log (by default *firefox*). + * **log_dir** : The directory used to store the log files. + diff --git a/doc/build/html/_sources/commands/package.txt b/doc/build/html/_sources/commands/package.txt new file mode 100644 index 0000000..6d6648a --- /dev/null +++ b/doc/build/html/_sources/commands/package.txt @@ -0,0 +1,81 @@ + +.. include:: ../../rst_prolog.rst + +Command package +**************** + +Description +============ +The **package** command creates a SALOME_ archive (usually a compressed Tar_ file .tgz). +This tar file is used later to intall SALOME on other remote computer. + +Depending on the selected options, the archive includes sources and binaries +of SALOME products and prerequisites. + +Usually utility *salomeTools* is included in the archive. + +.. note:: + By default the package includes the sources of prerequisites and products. + To select a subset use the *--without_property* or *--with_vcs* options. + + +Usage +===== +* Create a package for a product (example as *SALOME_xx*): :: + + sat package SALOME_xx + + This command will create an archive named ``SALOME_xx.tgz`` + in the working directory (``USER.workDir``). + If the archive already exists, do nothing. + + +* Create a package with a specific name: :: + + sat package SALOME_xx --name YourSpecificName + +.. note:: + By default, the archive is created in the working directory of the user (``USER.workDir``). + + If the option *--name* is used with a path (relative or absolute) it will be used. + + If the option *--name* is not used and binaries (prerequisites and products) + are included in the package, the OS_ architecture + will be appended to the name (example: ``SALOME_xx-CO7.tgz``). + + Examples: :: + + # Creates SALOME_xx.tgz in $USER.workDir + sat package SALOME_xx + + # Creates SALOME_xx_.tgz in $USER.workDir + sat package SALOME_xx --binaries + + # Creates MySpecificName.tgz in $USER.workDir + sat package SALOME_xx --name MySpecificName + + +* Force the creation of the archive (if it already exists): :: + + sat package SALOME_xx --force + + +* Include the binaries in the archive (products and prerequisites): :: + + sat package SALOME_xx --binaries + + This command will create an archive named ``SALOME_xx _.tgz`` + where is the OS_ architecture of the machine. + + +* Do not delete Version Control System (VCS_) informations from the configurations files of the embedded salomeTools: :: + + sat package SALOME_xx --with_vcs + + The version control systems known by this option are CVS_, SVN_ and Git_. + + +Some useful configuration pathes +================================= + +No specific configuration. diff --git a/doc/build/html/_sources/commands/prepare.txt b/doc/build/html/_sources/commands/prepare.txt new file mode 100644 index 0000000..a28fdae --- /dev/null +++ b/doc/build/html/_sources/commands/prepare.txt @@ -0,0 +1,100 @@ + +.. include:: ../../rst_prolog.rst + +Command prepare +**************** + +Description +=========== +The **prepare** command brings the sources of an application in the *sources +application directory*, in order to compile them with the compile command. + +The sources can be prepared from VCS software (*cvs, svn, git*), an archive or a directory. + +.. warning:: When sat prepares a product, it first removes the + existing directory, except if the development mode is activated. + When you are working on a product, you need to declare in + the application configuration this product in **dev** mode. + +Remarks +======= + +VCS bases (git, svn, cvs) +------------------------- + +The *prepare* command does not manage authentication on the cvs server. +For example, to prepare modules from a cvs server, you first need to login once. + +To avoid typing a password for each product, +you may use a ssh key with passphrase, or store your password +(in .cvspass or .gitconfig files). +If you have security concerns, it is also possible to use +a bash agent and type your password only once. + + + +Dev mode +-------- + +By default *prepare* uses *export* mode: it creates an image +of the sources, corresponding to the tag or branch specified, +without any link to the VCS base. +To perform a *checkout* (svn, cvs) or a *git clone* (git), +you need to declare the product in dev mode in your application configuration: +edit the application configuration file (pyconf) and modify the product declaration: + +.. code-block:: bash + + sat config -e + # and edit the product section: + # : {tag : "my_tag", dev : "yes", debug : "yes"} + +The first time you will execute the *sat prepare* command, +your module will be downloaded in *checkout* mode +(inside the SOURCES directory of the application. +Then, you can develop in this repository, and finally push +them in the base when they are ready. +If you type during the development process by mistake +a *sat prepare* command, the sources in dev mode will +not be altered/removed (Unless you use -f option) + + +Usage +===== +* Prepare the sources of a complete application in SOURCES directory (all products): :: + + sat prepare + +* Prepare only some modules: :: + + sat prepare --products , ... + +* Use --force to force to prepare the products in development mode + (this will remove the sources and do a new clone/checkout): :: + + sat prepare --force + +* Use --force_patch to force to apply patch to the products + in development mode (otherwise they are not applied): :: + + sat prepare --force_patch + + +Some useful configuration pathes +================================= + +Command *sat prepare* uses the *pyconf file configuration* of each product to know how to get the sources. + +.. note:: to verify configuration of a product, and get name of this *pyconf files configuration* + + .. code-block :: bash + + sat config --info + + +* **get_method**: the method to use to prepare the module, possible values are cvs, git, archive, dir. +* **git_info** : (used if get_method = git) information to prepare sources from git. +* **svn_info** : (used if get_method = svn) information to prepare sources from cvs. +* **cvs_info** : (used if get_method = cvs) information to prepare sources from cvs. +* **archive_info** : (used if get_method = archive) the path to the archive. +* **dir_info** : (used if get_method = dir) the directory with the sources. diff --git a/doc/build/html/_sources/configuration.txt b/doc/build/html/_sources/configuration.txt new file mode 100644 index 0000000..7f415a3 --- /dev/null +++ b/doc/build/html/_sources/configuration.txt @@ -0,0 +1,88 @@ +************* +Configuration +************* + +*salomeTools* uses files to store its configuration parameters. + +There are several configuration files which are loaded by salomeTools in a specific order. +When all the files are loaded a *config* object is created. +Then, this object is passed to all command scripts. + + +Syntax +====== +The configuration files use a python-like structure format +(see `config module `_ for a complete description). + +* **{}** define a dictionary, +* **[]** define a list, +* **@** can be used to include a file, +* **$prefix** reference to another parameter (ex: ``$PRODUCT.name``), +* **#** comments. + +.. note:: in this documentation a reference to a configuration parameter will be noted ``XXX.YYY``. + +Description +=========== + +.. _VARS-Section: + +VARS section +------------- +| This section is dynamically created by salomeTools at run time. +| It contains information about the environment: date, time, OS, architecture etc. + +:: + + # to get the current setting + sat config --value VARS + +PRODUCTS section +------------------ +| This section is defined in the product file. +| It contains instructions on how to build a version of SALOME (list of prerequisites-products and versions) + +:: + + # to get the current setting + sat config SALOME-xx --value PRODUCTS + +APPLICATION section +--------------------- +| This section is optional, it is also defined in the product file. +| It gives additional parameters to create an application based on SALOME, as versions of products to use. + +:: + + # to get the current setting + sat config SALOME-xx --value APPLICATION + + +.. _USER-Section: + +USER section +-------------- +This section is defined by the user configuration file, +``~/.salomeTools/salomeTools.pyconf``. + +The ``USER`` section defines some parameters (not exhaustive): + +* **workDir** : + + | The working directory. + | Each product will be usually installed here (in sub-directories). + +* **browser** : The web browser to use (*firefox*). + +* **editor** : The editor to use (*vi, pluma*). + +* and other user preferences. + +:: + + # to get the current setting + sat config SALOME-xx --value USER + + + + diff --git a/doc/build/html/_sources/index.txt b/doc/build/html/_sources/index.txt new file mode 100644 index 0000000..2cfb090 --- /dev/null +++ b/doc/build/html/_sources/index.txt @@ -0,0 +1,76 @@ + +.. include:: ../rst_prolog.rst + +************ +Salome Tools +************ + +.. image:: images/sat_about.png + :scale: 100 % + :align: center + +.. warning:: This documentation is under construction. + +The **Sa**\ lome\ **T**\ ools (sat) is a suite of commands +that can be used to perform operations on SALOME_. + +For example, sat allows you to compile SALOME's codes +(prerequisites, products) +create application, run tests, create package, etc. + +This utility code is a set of Python_ scripts files. + + +Quick start +=========== + +.. toctree:: + :maxdepth: 1 + + Installation of salomeTools + Configuration + Usage of salomeTools + +List of Commands +================ + +.. toctree:: + :maxdepth: 1 + + config + prepare + compile + launcher + application + log + environ + clean + package + generate + +Developer documentation +======================= + +.. toctree:: + :maxdepth: 1 + + Add a command + + +Code documentation +================== + +.. toctree:: + :maxdepth: 1 + + SAT modules + + +Release Notes +============= + +.. toctree:: + :maxdepth: 1 + + Release Notes 5.0.0 + diff --git a/doc/build/html/_sources/installation_of_sat.txt b/doc/build/html/_sources/installation_of_sat.txt new file mode 100644 index 0000000..da661be --- /dev/null +++ b/doc/build/html/_sources/installation_of_sat.txt @@ -0,0 +1,15 @@ +************ +Installation +************ + +Usually user could find (and use) command **sat** directly after a 'detar' installation of SALOME. + +.. code-block:: bash + + tar -xf .../SALOME_xx.tgz + cd SALOME_xx + ls -l sat # sat -> salomeTools/sat + + +Python package (scripts of salomeTools) actually remains in directory *salomeTools*. + diff --git a/doc/build/html/_sources/release_notes/release_notes_5.0.0.txt b/doc/build/html/_sources/release_notes/release_notes_5.0.0.txt new file mode 100644 index 0000000..55b6aad --- /dev/null +++ b/doc/build/html/_sources/release_notes/release_notes_5.0.0.txt @@ -0,0 +1,5 @@ +*************** +Release notes +*************** + +In construction. diff --git a/doc/build/html/_sources/usage_of_sat.txt b/doc/build/html/_sources/usage_of_sat.txt new file mode 100644 index 0000000..80c7b46 --- /dev/null +++ b/doc/build/html/_sources/usage_of_sat.txt @@ -0,0 +1,97 @@ + +.. include:: ../rst_prolog.rst + +******************** +Usage of SAlomeTools +******************** + +Usage +===== +sat usage is a Command Line Interface (CLI_). + +.. code-block:: bash + + sat [generic_options] [command] [product] [command_options] + +Options of sat +-------------- + +Useful *not exhaustive* generic options of *sat* CLI. + +*--help or -h* +............... + +Get help as simple text. + +.. code-block:: bash + + sat --help # get the list of existing commands + sat --help compile # get the help on a specific command 'compile' + + +*--debug or -g* +................ + +Execution in debug mode allows to see more trace and *stack* if an exception is raised. + +*--verbose or -v* +.................. + +Change verbosity level (default is 3). + +.. code-block:: bash + + # for product 'SALOME_xx' for example + # execute compile command in debug mode with trace level 4 + sat -g -v 4 compile SALOME_xx + + +Build a SALOME product +====================== + +Get the list of available products +---------------------------------- + +To get the list of the current available products in your context: + +.. code-block:: bash + + sat config --list + +Prepare sources of a product +---------------------------- + +To prepare (get) *all* the sources of a product (*SALOME_xx* for example): + +.. code-block:: bash + + sat prepare SALOME_xx + +| The sources are usually copied in directories +| *$USER.workDir + SALOME_xx... + SOURCES + $PRODUCT.name* + + +Compile SALOME +---------------- + +To compile products: + +.. code-block:: bash + + # compile all prerequisites/products + sat compile SALOME_xx + + # compile only 2 products (KERNEL and SAMPLES), if not done yet + sat compile SALOME_xx --products KERNEL,SAMPLES + + # compile only 2 products, unconditionaly + sat compile SALOME_xx ---products SAMPLES --clean_all + + +| The products are usually build in the directories +| *$USER.workDir + SALOME_xx... + BUILD + $PRODUCT.name* +| +| The products are usually installed in the directories +| *$USER.workDir + SALOME_xx... + INSTALL + $PRODUCT.name* + + diff --git a/doc/build/html/_sources/write_command.txt b/doc/build/html/_sources/write_command.txt new file mode 100644 index 0000000..9a68de8 --- /dev/null +++ b/doc/build/html/_sources/write_command.txt @@ -0,0 +1,157 @@ + +.. include:: ../rst_prolog.rst + + +Add a user custom command +*************************** + +Introduction +============ + +.. note:: This documentation is for Python_ developers. + + +The salomeTools product provides a simple way to develop commands. +The first thing to do is to add a file with *.py* extension in the ``commands`` directory of salomeTools. + +Here are the basic requirements that must be followed in this file in order to add a command. + +Basic requirements +================== + +By adding a file *mycommand.py* in the ``commands`` directory, salomeTools will define a new command named ``mycommand``. + +In *mycommand.py*, there must be the following method: :: + + def run(args, runner, logger): + # your algorithm ... + pass + +In fact, at this point, the command will already be functional. +But there are some useful services provided by salomeTools : + +* You can give some options to your command: + +.. code-block:: python + + import src + + # Define all possible option for mycommand command : 'sat mycommand ' + parser = src.options.Options() + parser.add_option('m', 'myoption', \ + 'boolean', 'myoption', \ + 'My option changes the behavior of my command.') + + def run(args, runner, logger): + # Parse the options + (options, args) = parser.parse_args(args) + # algorithm + + +* You can add a *description* method that will display a message when the user will call the help: + + +.. code-block:: python + :emphasize-lines: 9,10 + + import src + + # Define all possible option for mycommand command : 'sat mycommand ' + parser = src.options.Options() + parser.add_option('m', 'myoption', \ + 'boolean', 'myoption', \ + 'My option changes the behavior of my command.') + + def description(): + return _("The help of mycommand.") + + def run(args, runner, logger): + # Parse the options + (options, args) = parser.parse_args(args) + # algorithm + +HowTo access salomeTools config and other commands +======================================================== + +The *runner* variable is an python instance of *Sat* class. +It gives access to *runner.cfg* which is the data model defined from all +*configuration pyconf files* of salomeTools +For example, *runner.cfg.APPLICATION.workdir* +contains the root directory of the current application. + +The *runner* variable gives also access to other commands of salomeTools: + +.. code-block:: python + + # as CLI_ 'sat prepare ...' + runner.prepare(runner.cfg.VARS.application) + +HowTo logger +============== + +The logger variable is an instance of the Logger class. +It gives access to the write method. + +When this method is called, the message passed as parameter +will be displayed in the terminal and written in an xml log file. + +.. code-block:: python + + logger.write("My message", 3) # 3 as default + +The second argument defines the level of verbosity +that is wanted for this message. +It has to be between 1 and 5 (the most verbose level). + +HELLO example +============== + +Here is a *hello* command, file *commands/hello.py*: + +.. code-block:: python + + import src + + """ + hello.py + Define all possible options for hello command: + sat hello + """ + + parser = src.options.Options() + parser.add_option('f', 'french', 'boolean', 'french', "french set hello message in french.") + + def description(): + return _("The help of hello.") + + def run(args, runner, logger): + # Parse the options + (options, args) = parser.parse_args(args) + # algorithm + if not options.french: + logger.write('HELLO! WORLD!\n') + else: + logger.write('Bonjour tout le monde!\n') + +A first call of hello: + +.. code-block:: bash + + # Get the help of hello: + ./sat --help hello + + # To get bonjour + ./sat hello --french + Bonjour tout le monde! + + # To get hello + ./sat hello + HELLO! WORLD! + + # To get the log + ./sat log + + + + + diff --git a/doc/build/html/_static/ajax-loader.gif b/doc/build/html/_static/ajax-loader.gif new file mode 100644 index 0000000..61faf8c Binary files /dev/null and b/doc/build/html/_static/ajax-loader.gif differ diff --git a/doc/build/html/_static/alabaster.css b/doc/build/html/_static/alabaster.css new file mode 100644 index 0000000..1d88b3e --- /dev/null +++ b/doc/build/html/_static/alabaster.css @@ -0,0 +1,689 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; + font-size: 0.9em; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 1000px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 250px; +} + +div.sphinxsidebar { + width: 250px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 1000px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: 'Garamond', 'Georgia', serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.8em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #fee; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} \ No newline at end of file diff --git a/doc/build/html/_static/basic.css b/doc/build/html/_static/basic.css new file mode 100644 index 0000000..43e8baf --- /dev/null +++ b/doc/build/html/_static/basic.css @@ -0,0 +1,540 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + width: 170px; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + width: 30px; +} + +img { + border: 0; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.refcount { + color: #060; +} + +.optional { + font-size: 1.3em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +tt.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +tt.descclassname { + background-color: transparent; +} + +tt.xref, a tt { + background-color: transparent; + font-weight: bold; +} + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/doc/build/html/_static/comment-bright.png b/doc/build/html/_static/comment-bright.png new file mode 100644 index 0000000..551517b Binary files /dev/null and b/doc/build/html/_static/comment-bright.png differ diff --git a/doc/build/html/_static/comment-close.png b/doc/build/html/_static/comment-close.png new file mode 100644 index 0000000..09b54be Binary files /dev/null and b/doc/build/html/_static/comment-close.png differ diff --git a/doc/build/html/_static/comment.png b/doc/build/html/_static/comment.png new file mode 100644 index 0000000..92feb52 Binary files /dev/null and b/doc/build/html/_static/comment.png differ diff --git a/doc/build/html/_static/custom.css b/doc/build/html/_static/custom.css new file mode 100644 index 0000000..3ddd34d --- /dev/null +++ b/doc/build/html/_static/custom.css @@ -0,0 +1,2 @@ +/* This file intentionally left blank. */ + diff --git a/doc/build/html/_static/doctools.js b/doc/build/html/_static/doctools.js new file mode 100644 index 0000000..d4619fd --- /dev/null +++ b/doc/build/html/_static/doctools.js @@ -0,0 +1,247 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +} + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s == 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * small function to check if an array contains + * a given item. + */ +jQuery.contains = function(arr, item) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] == item) + return true; + } + return false; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node) { + if (node.nodeType == 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this); + }); + } + } + return this.each(function() { + highlight(this); + }); +}; + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated == 'undefined') + return string; + return (typeof translated == 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated == 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) == 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this == '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/doc/build/html/_static/down-pressed.png b/doc/build/html/_static/down-pressed.png new file mode 100644 index 0000000..6f7ad78 Binary files /dev/null and b/doc/build/html/_static/down-pressed.png differ diff --git a/doc/build/html/_static/down.png b/doc/build/html/_static/down.png new file mode 100644 index 0000000..3003a88 Binary files /dev/null and b/doc/build/html/_static/down.png differ diff --git a/doc/build/html/_static/file.png b/doc/build/html/_static/file.png new file mode 100644 index 0000000..d18082e Binary files /dev/null and b/doc/build/html/_static/file.png differ diff --git a/doc/build/html/_static/jquery.js b/doc/build/html/_static/jquery.js new file mode 100644 index 0000000..7c24308 --- /dev/null +++ b/doc/build/html/_static/jquery.js @@ -0,0 +1,154 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
"; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/doc/build/html/_static/minus.png b/doc/build/html/_static/minus.png new file mode 100644 index 0000000..da1c562 Binary files /dev/null and b/doc/build/html/_static/minus.png differ diff --git a/doc/build/html/_static/plus.png b/doc/build/html/_static/plus.png new file mode 100644 index 0000000..b3cb374 Binary files /dev/null and b/doc/build/html/_static/plus.png differ diff --git a/doc/build/html/_static/pygments.css b/doc/build/html/_static/pygments.css new file mode 100644 index 0000000..1a14f2a --- /dev/null +++ b/doc/build/html/_static/pygments.css @@ -0,0 +1,62 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #303030 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/doc/build/html/_static/sat_v5.0.png b/doc/build/html/_static/sat_v5.0.png new file mode 100644 index 0000000..1057f5b Binary files /dev/null and b/doc/build/html/_static/sat_v5.0.png differ diff --git a/doc/build/html/_static/searchtools.js b/doc/build/html/_static/searchtools.js new file mode 100644 index 0000000..663be4c --- /dev/null +++ b/doc/build/html/_static/searchtools.js @@ -0,0 +1,560 @@ +/* + * searchtools.js_t + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilties for the full-text search. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words, hlwords is the list of normal, unstemmed + * words. the first one is used to find the occurance, the + * latter for highlighting it. + */ + +jQuery.makeSearchSummary = function(text, keywords, hlwords) { + var textLower = text.toLowerCase(); + var start = 0; + $.each(keywords, function() { + var i = textLower.indexOf(this.toLowerCase()); + if (i > -1) + start = i; + }); + start = Math.max(start - 120, 0); + var excerpt = ((start > 0) ? '...' : '') + + $.trim(text.substr(start, 240)) + + ((start + 240 - text.length) ? '...' : ''); + var rv = $('
').text(excerpt); + $.each(hlwords, function() { + rv = rv.highlightText(this, 'highlighted'); + }); + return rv; +} + + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + + +/** + * Search Module + */ +var Search = { + + _index : null, + _queued_query : null, + _pulse_status : -1, + + init : function() { + var params = $.getQueryParameters(); + if (params.q) { + var query = params.q[0]; + $('input[name="q"]')[0].value = query; + this.performSearch(query); + } + }, + + loadIndex : function(url) { + $.ajax({type: "GET", url: url, data: null, success: null, + dataType: "script", cache: true}); + }, + + setIndex : function(index) { + var q; + this._index = index; + if ((q = this._queued_query) !== null) { + this._queued_query = null; + Search.query(q); + } + }, + + hasIndex : function() { + return this._index !== null; + }, + + deferQuery : function(query) { + this._queued_query = query; + }, + + stopPulse : function() { + this._pulse_status = 0; + }, + + startPulse : function() { + if (this._pulse_status >= 0) + return; + function pulse() { + Search._pulse_status = (Search._pulse_status + 1) % 4; + var dotString = ''; + for (var i = 0; i < Search._pulse_status; i++) + dotString += '.'; + Search.dots.text(dotString); + if (Search._pulse_status > -1) + window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something + */ + performSearch : function(query) { + // create the required interface elements + this.out = $('#search-results'); + this.title = $('

' + _('Searching') + '

').appendTo(this.out); + this.dots = $('').appendTo(this.title); + this.status = $('

').appendTo(this.out); + this.output = $('