Fix pylint and pep8 issues for the following Python files:
./tools/devel/dot/trace2dot
./tools/devel/review/patch-tokenize.py
./src/imm/tools/immxml-merge
./src/imm/tools/immxml-validate
./src/imm/tools/baseimm.py
---
src/imm/tools/baseimm.py | 376 ++++++++-------
src/imm/tools/immxml-merge | 891 +++++++++++++++++++----------------
src/imm/tools/immxml-validate | 792 +++++++++++++++++--------------
tools/devel/dot/trace2dot | 70 +--
tools/devel/review/patch-tokenize.py | 16 +-
5 files changed, 1174 insertions(+), 971 deletions(-)
diff --git a/src/imm/tools/baseimm.py b/src/imm/tools/baseimm.py
index 09a9b85..fe1c3ce 100644
--- a/src/imm/tools/baseimm.py
+++ b/src/imm/tools/baseimm.py
@@ -1,221 +1,258 @@
-'''
- -*- OpenSAF -*-
-
- (C) Copyright 2009 The OpenSAF Foundation
-
- This program 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. This file and program are licensed
- under the GNU Lesser General Public License Version 2.1, February 1999.
- The complete license can be accessed from the following location:
- http://opensource.org/licenses/lgpl-license.php
- See the Copying file included with the OpenSAF distribution for full
- licensing terms.
-
- Author(s): Ericsson AB
-'''
-
-import sys,glob,os
+# -*- OpenSAF -*-
+#
+# (C) Copyright 2009 The OpenSAF Foundation
+# (C) Copyright Ericsson AB 2015, 2016, 2017. All rights reserved.
+#
+# This program 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. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson AB
+#
+""" Common utils to manipulate immxml files """
+from __future__ import print_function
+import os
+import sys
+import glob
+import xml.dom.minidom
from subprocess import call
-class BaseOptions:
+
+class BaseOptions(object):
+ """ Base options for immxml tools """
traceOn = False
@staticmethod
- def printOptionSettings():
- return 'Options:\n traceOn:%s\n' % (BaseOptions.traceOn)
-
+ def print_option_settings():
+ return 'Options:\n traceOn:%s\n' % BaseOptions.traceOn
-class BaseImmDocument:
+class BaseImmDocument(object):
+ """ Base class with common methods to manipulate IMM XML documents """
imm_content_element_name = "imm:IMM-contents"
imm_content_no_namespace_spec = "<imm:IMM-contents>"
- imm_content_with_namespace_spec = "<imm:IMM-contents xmlns:imm=\"http://www.saforum.org/IMMSchema\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xsi:noNamespaceSchemaLocation=\"SAI-AIS-IMM-XSD-A.02.13.xsd\">"
-
- # helper function to identify a problem where python/minidom
- # fails to parse some imm.xml files where the imm: namespace is missing
- # (for example the output of the immdump tool)
- def verifyInputXmlDocumentFileIsParsable(self, filename):
- if os.stat(filename).st_size == 0:
- abort_script("The inputfile %s is empty!", filename)
-
- f = open(filename)
- immContentsTagFound = False
- for line in f:
- s = line
- str = s.replace(self.imm_content_no_namespace_spec,
self.imm_content_with_namespace_spec)
- if len(str) != len(s):
- # there was a substitution....file will not be possible to
parse....
- abort_script("The inputfile lacks namespace specification in
<imm:IMM-contents> tag")
- elif s.find(self.imm_content_element_name) != -1:
- # Assume file is ok w.r.t namespace
+ imm_content_with_namespace_spec = \
+ "<imm:IMM-contents xmlns:imm=\"http://www.saforum.org/IMMSchema\" " \
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
+ "xsi:noNamespaceSchemaLocation=\"SAI-AIS-IMM-XSD-A.02.13.xsd\">"
+
+ def verify_input_xml_document_file_is_parsable(self, file_name):
+ """ Helper function to identify a problem where python/minidom fails to
+ parse some imm.xml files where the imm namespace is missing (for ex,
+ the output of the immdump tool)
+ """
+ if os.stat(file_name).st_size == 0:
+ abort_script("The input file %s is empty!", file_name)
+
+ doc = open(file_name)
+ for _line in doc:
+ line = _line
+ string = line.replace(self.imm_content_no_namespace_spec,
+ self.imm_content_with_namespace_spec)
+ if len(string) != len(line):
+ # There was a substitution....file will not be possible
+ # to parse....
+ abort_script("The input file lacks namespace specification in "
+ "<imm:IMM-contents> tag")
+ elif line.find(self.imm_content_element_name) != -1:
+ # Assume file is ok w.r.t namespace
return
-
-
- def validateXmlFileWithSchema(self, filename, schemaFilename):
+ @staticmethod
+ def validate_xml_file_with_schema(file_name, schema_file_name):
+ """ Validate xml file against its schema """
trace("")
-
- trace("validate xml file:%s", filename)
- # validate the result file with xmllint
- command = "/usr/bin/xmllint --noout"+" --schema "+schemaFilename+"
"+filename
+ trace("Validate xml file: %s", file_name)
+
+ # Validate the result file with xmllint
+ command = "/usr/bin/xmllint --noout"+" --schema " + schema_file_name \
+ + " " + file_name
print_info_stderr("XML Schema validation (using xmllint):")
- trace("validate command:%s", command)
- retCode = call(command, shell=True)
- if retCode != 0:
- return retCode
+ trace("Validate command: %s", command)
+ ret_code = call(command, shell=True)
+ if ret_code != 0:
+ return ret_code
-
- trace("Successfully validated xml document file: %s", filename)
+ trace("Successfully validated xml document file: %s", file_name)
return 0
- def formatXmlFileWithXmlLint(self, infilename, outfilename):
- trace("formatXmlFileWithXmlLint() prettify xml file:%s", infilename)
- # "prettify" the result file with xmllint (due to inadequate
python/minidom prettify functionality)
- #command = "/bin/sh -c 'XMLLINT_INDENT=\" \" ; export XMLLINT_INDENT; /usr/bin/xmllint
--format "+infilename+" --output "+outfilename +"'"
- command = "/bin/sh -c 'XMLLINT_INDENT=\""+"\t"+"\" ; export XMLLINT_INDENT; /usr/bin/xmllint
--format "+infilename+" --output "+outfilename +"'"
- trace("formatting command:%s", command)
- retCode = call(command, shell=True)
- #if retCode != 0:
- #return retCode
- #validate_failed("failed to validate input file %s:", filename)
- return retCode
-
- def printToStdoutAndRemoveTmpFile(self, tempfile):
+ @staticmethod
+ def format_xml_file_with_xmllint(in_file_name, out_file_name):
+ """ Format xml file with xmllint """
+ trace("formatXmlFileWithXmlLint() prettify xml file:%s", in_file_name)
+
+ # "prettify" the result file with xmllint
+ # (due to inadequate python/minidom prettify functionality)
+ command = "/bin/sh -c 'XMLLINT_INDENT=\"" + "\t" + \
+ "\"; export XMLLINT_INDENT; /usr/bin/xmllint --format " + \
+ in_file_name + " --output " + out_file_name + "'"
+ trace("Formatting command: %s", command)
+ ret_code = call(command, shell=True)
+ # if ret_code != 0:
+ # return ret_code
+ # validate_failed("Failed to validate input file: %s", file_name)
+ return ret_code
+
+ @staticmethod
+ def print_to_stdout_and_remove_tmp_file(temp_file):
+ """ Print the temp file content to stdout and remove the temp file """
# Print the tmp file to the standard output
- trace("Print the tmp file to the standard output: %s", tempfile)
- f = file(tempfile)
+ trace("Print the tmp file to the standard output: %s", temp_file)
+ tmp_file = open(temp_file)
while True:
- line = f.readline()
- if len(line) == 0:
+ line = tmp_file.readline()
+ if not line:
break
- print line, # notice comma
- f.close()
- # remove temp file
- trace("delete the stdout tmp file: %s", tempfile)
- os.remove(tempfile)
-
- # helper function to handle a problem where python/minidom
- # fails to parse some imm.xml files where the imm: namespace is missing
- # (for example the output of the immdump tool)
- # Currently NOT used.....
- def openXmlDocumentFileAndCheckNamespace(self, filename):
- f = open(filename)
+ print (line, end=" ") # Print on the same line
+ tmp_file.close()
+ # Remove temp file
+ trace("Delete the stdout tmp file: %s", temp_file)
+ os.remove(temp_file)
+
+ def open_xml_document_file_and_check_namespace(self, file_name):
+ """ Helper function to handle a problem where python/minidom fails to
+ parse some imm.xml files where the imm namespace is missing (for ex,
+ the output of the immdump tool).
+ *** This method is currently NOT used ****
+ """
+ doc = open(file_name)
str_list = []
- immContentsTagFound = False
- immContentsTagReplaced = False
- for line in f:
- s = line
- if (immContentsTagFound == False):
- str = s.replace(self.imm_content_no_namespace_spec,
self.imm_content_with_namespace_spec)
- if len(str) != len(s):
- s = str
- immContentsTagFound = True
- immContentsTagReplaced = True
- elif s.find(self.imm_content_element_name) != -1:
- immContentsTagFound = True
-
- str_list.append(s)
-
- xmlstr = ' '.join(str_list)
-
-
- if Options.schemaFilename != None:
- if immContentsTagReplaced == True:
- print_info_stderr("Cannot validate inputfile '%s' with schema file
because of missing namespace specification in element <imm:IMM-contents>. \nProceeding
with processing of modified input data!", filename)
- else:
- if self.validateXmlFile(filename) != 0:
- abort_script("Failed to validate the inputfile %s:",
filename)
-
-
- return xml.dom.minidom.parseString(xmlstr)
-
- # helper function to remove some whitespace which we do not want to have in
result of toPrettyXml
- # Currently NOT used.....
- def openXmlDocumentAndStrip(self, filename):
- f = open(filename)
+ imm_contents_tag_found = False
+ # imm_contents_tag_replaced = False
+ for _line in doc:
+ line = _line
+ if not imm_contents_tag_found:
+ string = line.replace(self.imm_content_no_namespace_spec,
+ self.imm_content_with_namespace_spec)
+ if len(string) != len(line):
+ line = string
+ imm_contents_tag_found = True
+ # imm_contents_tag_replaced = True
+ elif line.find(self.imm_content_element_name) != -1:
+ imm_contents_tag_found = True
+
+ str_list.append(line)
+
+ xml_str = ' '.join(str_list)
+
+ # if Options.schemaFilename is not None:
+ # if imm_contents_tag_replaced:
+ # print_info_stderr("Cannot validate input file '%s' with "
+ # "schema file because of missing namespace "
+ # "specification in element "
+ # "<imm:IMM-contents>. \nProceeding with "
+ # "processing of modified input data!",
+ # file_name)
+ # else:
+ # if self.validate_xml_file(file_name) != 0:
+ # abort_script("Failed to validate the input file: %s",
+ # file_name)
+ return xml.dom.minidom.parseString(xml_str)
+
+ @staticmethod
+ def open_xml_document_and_strip(file_name):
+ """ Helper function to remove some whitespace which we do not want to
+ have in result of to_pretty_xml
+ *** This method is currently NOT used ***
+ """
+ doc = open(file_name)
str_list = []
- for line in f:
- #s = line.rstrip().lstrip()
- s = line.strip('\t\n')
- if len(s) < 5:
- trace("short line *%s*", s)
- str_list.append(s)
-
- xmlstr = ' '.join(str_list)
- return xml.dom.minidom.parseString(xmlstr)
-# end of Class BaseImmDocument
+ for line in doc:
+ # string = line.rstrip().lstrip()
+ string = line.strip('\t\n')
+ if len(string) < 5:
+ trace("short line *%s*", string)
+ str_list.append(string)
+
+ xml_str = ' '.join(str_list)
+ return xml.dom.minidom.parseString(xml_str)
+
+# End of BaseImmDocument class
def trace(*args):
- if BaseOptions.traceOn == True:
+ """ Print traces to stderr if trace option is enabled """
+ if BaseOptions.traceOn:
printf_args = []
for i in range(1, len(args)):
printf_args.append(args[i])
-
- formatStr = "TRACE:\t" + args[0]
- print >> sys.stderr, formatStr % tuple(printf_args)
+ format_str = "TRACE:\t" + args[0]
+ print (format_str % tuple(printf_args), file=sys.stderr)
-def retrieveFilenames(args):
- fileList = []
- trace("before glob args:%s", args)
- fileList = glob.glob(args[0]) # wildcard expansion for WIN support,
however not tested....
- trace("after glob filelist:%s length:%d", fileList, len(fileList))
+def retrieve_file_names(args):
+ """ Retrieve file names """
+ trace("Before glob args:%s", args)
+ # Wildcard expansion for WIN support, however not tested....
+ file_list = glob.glob(args[0])
+ trace("After glob file list: %s length: %d", file_list, len(file_list))
- if (len(fileList) < 2 and len(args) >= 1):
- fileList = args
-
- trace("Final filelist:%s length:%d", fileList, len(fileList))
- return fileList
+ if len(file_list) < 2 and len(args) >= 1:
+ file_list = args
+
+ trace("Final file list: %s length: %d", file_list, len(file_list))
+ return file_list
def print_info_stderr(*args):
+ """ Print info to stderr """
printf_args = []
for i in range(1, len(args)):
printf_args.append(args[i])
-
- formatStr = args[0]
- print >> sys.stderr, formatStr % tuple(printf_args)
-
+
+ format_str = args[0]
+ print (format_str % tuple(printf_args), file=sys.stderr)
+
def abort_script(*args):
+ """ Abort the script and print info to stderr """
printf_args = []
for i in range(1, len(args)):
printf_args.append(args[i])
-
- formatStr = "\nAborting script: " + args[0]
- print >> sys.stderr, formatStr % tuple(printf_args)
+
+ format_str = "\nAborting script: " + args[0]
+ print (format_str % tuple(printf_args), file=sys.stderr)
sys.exit(2)
+
def exit_script(*args):
+ """ Exit the script and print info to stderr """
printf_args = []
for i in range(1, len(args)):
printf_args.append(args[i])
-
- formatStr = "\n" + args[0]
- print >> sys.stderr, formatStr % tuple(printf_args)
- sys.exit(0)
-def verifyInputFileReadAcess(filename):
- if os.access(filename, os.R_OK) == False:
- abort_script("Cannot access input file: %s", filename)
+ format_str = "\n" + args[0]
+ print (format_str % tuple(printf_args), file=sys.stderr)
+ sys.exit(0)
+
+
+def verify_input_file_read_access(file_name):
+ """ Verify if input file has read access """
+ if not os.access(file_name, os.R_OK):
+ abort_script("Cannot access input file: %s", file_name)
# An attempt to fix minidom pretty print functionality
-# see
http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/
-# however the result is still not nice..... (have replaced it with xmllint
formatting)
+# see http://ronrothman.com/public/leftbraned/ \
+# xml-dom-minidom-toprettyxml-and-silly-whitespace/
+# However the result is still not nice.
+# (have replaced it with xmllint formatting)
# This way the method gets replaced, worked when called from main()
- # attempt to replace minidom's function with a "hacked" version
- # to get decent prettyXml, however it does not look nice anyway....
- #xml.dom.minidom.Element.writexml = fixed_writexml
-
-def fixed_writexml(self, writer, indent="", addindent="", newl=""):
+# Attempt to replace minidom's function with a "hacked" version to get decent
+# prettyXml, however it does not look nice anyway.
+# xml.dom.minidom.Element.writexml = fixed_writexml
+def fixed_writexml(self, writer, indent="", add_indent="", new_line=""):
+ """ Customized pretty xml print function """
# indent = current indentation
- # addindent = indentation to add to higher levels
- # newl = newline string
- writer.write(indent+"<" + self.tagName)
+ # add_indent = indentation to add to higher levels
+ # new_line = newline string
+ writer.write(indent + "<" + self.tagName)
attrs = self._get_attributes()
a_names = attrs.keys()
@@ -230,12 +267,11 @@ def fixed_writexml(self, writer, indent="", addindent="",
newl=""):
and self.childNodes[0].nodeType == xml.dom.minidom.Node.TEXT_NODE:
writer.write(">")
self.childNodes[0].writexml(writer, "", "", "")
- writer.write("</%s>%s" % (self.tagName, newl))
+ writer.write("</%s>%s" % (self.tagName, new_line))
return
- writer.write(">%s"%(newl))
+ writer.write(">%s" % new_line)
for node in self.childNodes:
- node.writexml(writer,indent+addindent,addindent,newl)
- writer.write("%s</%s>%s" % (indent,self.tagName,newl))
+ node.writexml(writer, indent + add_indent, add_indent, new_line)
+ writer.write("%s</%s>%s" % (indent, self.tagName, new_line))
else:
- writer.write("/>%s"%(newl))
-
+ writer.write("/>%s" % new_line)
diff --git a/src/imm/tools/immxml-merge b/src/imm/tools/immxml-merge
index 5c30076..cd0d811 100755
--- a/src/imm/tools/immxml-merge
+++ b/src/imm/tools/immxml-merge
@@ -1,30 +1,35 @@
#! /usr/bin/env python
-
-'''
- -*- OpenSAF -*-
-
- (C) Copyright 2009 The OpenSAF Foundation
-
- This program 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. This file and program are licensed
- under the GNU Lesser General Public License Version 2.1, February 1999.
- The complete license can be accessed from the following location:
- http://opensource.org/licenses/lgpl-license.php
- See the Copying file included with the OpenSAF distribution for full
- licensing terms.
-
- Author(s): Ericsson AB
-'''
-
-import re, sys, getopt, shutil
+# -*- OpenSAF -*-
+#
+# (C) Copyright 2009 The OpenSAF Foundation
+# (C) Copyright Ericsson AB 2015, 2016, 2017. All rights reserved.
+#
+# This program 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. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson AB
+#
+# pylint: disable=invalid-name,unused-argument
+""" immxml-merge tool """
+from __future__ import print_function
+import os
+import sys
+import re
+import getopt
+import shutil
import xml.dom.minidom
-from baseimm import * # Base class and functions for Merge and
validation utils
-from subprocess import call
+from baseimm import BaseOptions, BaseImmDocument, trace, retrieve_file_names, \
+ print_info_stderr, abort_script, verify_input_file_read_access
+
-
class Options(BaseOptions):
- #traceOn = False
+ """ immxml-merge options"""
keepCommentElements = False
ignoreVariants = False
ignoreMissingClass = False
@@ -38,14 +43,22 @@ class Options(BaseOptions):
schemaFilename = None
isXmlLintFound = True
disableParentDnValidation = False
-
+
@staticmethod
- def printOptionSettings():
- return BaseOptions.printOptionSettings()+' keepCommentElements: %s \n
ignoreVariants: %s \n grep_class: %s\n grep_dn: %s\n negateGrep_dn: %s\n
negateGrep_class: %s \n sort:%s\n outputFilename: %s\n schemaFilename: %s\n' %
(Options.keepCommentElements, Options.ignoreVariants, Options.grep_class,
Options.grep_dn , Options.negateGrep_dn, Options.negateGrep_class,
Options.sort, Options.outputFilename, Options.schemaFilename)
+ def print_option_settings():
+ return BaseOptions.print_option_settings() + \
+ ' keepCommentElements: %s\n ignoreVariants: %s\n ' \
+ 'grep_class: %s\n grep_dn: %s\n negateGrep_dn: %s\n ' \
+ 'negateGrep_class: %s\n sort:%s\n outputFilename: %s\n ' \
+ 'schemaFilename: %s\n' % \
+ (Options.keepCommentElements, Options.ignoreVariants,
+ Options.grep_class, Options.grep_dn, Options.negateGrep_dn,
+ Options.negateGrep_class, Options.sort, Options.outputFilename,
+ Options.schemaFilename)
-
class MergedImmDocument(BaseImmDocument):
+ """ This class contains methods to process the merging of IMM XML files """
def __init__(self):
self.isResultDocInitialized = False
self.document = xml.dom.minidom.Document()
@@ -57,463 +70,537 @@ class MergedImmDocument(BaseImmDocument):
self.firstSourceDoc = None
self.objectList = []
self.objectDnNameDict = {}
- self.classes_parsed=0
- self.objects_parsed=0
-
+ self.classes_parsed = 0
+ self.objects_parsed = 0
def initialize(self):
+ """ Initialize matching patterns """
if Options.grep_class:
- trace("matching classes with pattern:%s", Options.grep_class)
+ trace("Matching classes with pattern: %s", Options.grep_class)
self.regexpObj = re.compile(Options.grep_class)
if Options.grep_dn:
- trace("grep_dn matching dn with pattern:%s", Options.grep_dn)
+ trace("grep_dn matching dn with pattern: %s", Options.grep_dn)
self.dn_regexpObj = re.compile(Options.grep_dn)
-
- def initResultDocument(self, doc):
+
+ def init_result_document(self, doc):
+ """ Initialize merge result document """
if self.isResultDocInitialized:
return
-
+
trace("Copy elements from first source document file")
for element in doc.childNodes:
- trace("nodeType:*%d*" ,element.nodeType)
- trace("nodeValue:*%s*" , element.nodeValue)
- trace("nodeName:*%s*" , element.nodeName)
- trace("parent:*%s*", element.parentNode.nodeName)
+ trace("nodeType: *%d*", element.nodeType)
+ trace("nodeValue: *%s*", element.nodeValue)
+ trace("nodeName: *%s*", element.nodeName)
+ trace("parent: *%s*", element.parentNode.nodeName)
clone = element.cloneNode(False)
self.document.appendChild(clone)
- if (element.nodeName == self.imm_content_element_name):
- self.imm_content_element = clone
- break
-
- if self.imm_content_element == None:
- abort_script("did not find <imm:IMM-contents element in first source
file")
-
- self.firstSourceDoc = doc
+ if element.nodeName == self.imm_content_element_name:
+ self.imm_content_element = clone
+ break
+
+ if self.imm_content_element is None:
+ abort_script("Did not find <imm:IMM-contents element in first "
+ "source file")
+
+ self.firstSourceDoc = doc
self.isResultDocInitialized = True
trace("Done copying elements from first source document.")
-
-
- def addClass(self, classElement, otherNodes):
- className = classElement.getAttribute("name")
- self.classes_parsed=self.classes_parsed+1
- trace("className: %s nodeType:%d nodeName:%s", className,
classElement.nodeType, classElement.nodeName)
-
- if self.regexpObj != None:
- trace ("Check if class %s match pattern %s", className,
Options.grep_class)
- if re.search(self.regexpObj, className) == None:
- if Options.negateGrep_class == False:
- trace ("Class %s does not match pattern %s", className,
Options.grep_class)
+
+ def add_class(self, class_element, other_nodes):
+ """ Add classes matching pattern """
+ class_name = class_element.getAttribute("name")
+ self.classes_parsed = self.classes_parsed + 1
+ trace("className: %s nodeType:%d nodeName:%s", class_name,
+ class_element.nodeType, class_element.nodeName)
+
+ if self.regexpObj is not None:
+ trace("Check if class %s match pattern %s", class_name,
+ Options.grep_class)
+ if re.search(self.regexpObj, class_name) is None:
+ if not Options.negateGrep_class:
+ trace("Class %s does not match pattern %s", class_name,
+ Options.grep_class)
return
elif Options.negateGrep_class:
- trace ("Class %s does not match negated pattern %s",
className, Options.grep_class)
+ trace("Class %s does not match negated pattern %s", class_name,
+ Options.grep_class)
return
- trace("match ok :%s", className);
-
- # check if class exist in dictionary map
- if className in self.classDict:
- # check if class clash is "acceptable"
+
+ trace("match ok :%s", class_name)
+
+ # Check if class exists in dictionary map
+ if class_name in self.classDict:
+ # Check if class clash is "acceptable"
# i.e. should we bail out or not??
- if self.checkClassClashAcceptable(classElement, className):
- trace("Ignore class definition duplicate %s. (Class is
compatible)", className)
- else:
- self.classDict[className] = classElement
- # add to ordered list
- self.classList.append((className, (otherNodes, classElement)))
-
-
- def addObject(self, objectElement, otherNodes):
- className = objectElement.getAttribute("class")
- trace("DUMPING Object with className: %s \n %s", className,
objectElement.toxml())
- self.objects_parsed=self.objects_parsed+1
-
- objectDnElement = None
- ## find "dn" childnode
- for childNode in objectElement.childNodes:
- if childNode.nodeName == "dn":
- objectDnElement = childNode
+ if self.check_class_clash_acceptable(class_element, class_name):
+ trace("Ignore class definition duplicate %s. "
+ "(Class is compatible)", class_name)
+ else:
+ self.classDict[class_name] = class_element
+ # Add to ordered list
+ self.classList.append((class_name, (other_nodes, class_element)))
+
+ def add_object(self, object_element, other_nodes):
+ """ Add objects matching pattern """
+ class_name = object_element.getAttribute("class")
+ trace("DUMPING Object with className: %s \n %s", class_name,
+ object_element.toxml())
+ self.objects_parsed = self.objects_parsed + 1
+
+ object_dn_element = None
+ # Find "dn" child node
+ for child_node in object_element.childNodes:
+ if child_node.nodeName == "dn":
+ object_dn_element = child_node
break
-
- if objectDnElement == None or className == None or
objectDnElement.firstChild == None:
- abort_script("Failed to find classname or the dn childnode in
object:%s. " ,objectElement.toxml())
-
-
- # objectDnName = objectDnElement.nodeValue
- ### NOTE dn name should be the nodeValue of objectDnName...
- ## however minidom probably gets confused by the equal sign in dn value
- # so it ends up adding a text node as a child......
- objectDnName = objectDnElement.firstChild.nodeValue
- trace("objectDn key: %s", objectDnName)
-
- trace("objectDnElement: %s", objectDnElement.toxml())
-
- # classname must exist in dictionary map (unless --ignore-noclass is
specified)
- if className not in self.classDict:
- if Options.ignoreMissingClass == False:
- if Options.grep_class != None:
- trace("ignoring object with class not matching pattern
classname:%s", className)
+
+ if object_dn_element is None or class_name is None \
+ or object_dn_element.firstChild is None:
+ abort_script("Failed to find class name or the dn child node in "
+ "object:%s. ", object_element.toxml())
+
+ # object_dn_name = object_dn_element.nodeValue
+ # NOTE: dn name should be the nodeValue of object_dn_name
+ # However minidom probably gets confused by the equal sign in dn value
+ # so it ends up adding a text node as a child.
+ object_dn_name = object_dn_element.firstChild.nodeValue
+ trace("objectDn key: %s", object_dn_name)
+ trace("objectDnElement: %s", object_dn_element.toxml())
+
+ # className must exist in dictionary map
+ # (unless --ignore-noclass is specified)
+ if class_name not in self.classDict:
+ if not Options.ignoreMissingClass:
+ if Options.grep_class is not None:
+ trace("Ignoring object with class not matching pattern "
+ "className:%s", class_name)
return
else:
- abort_script("failed to find class referred in: \n %s",
objectElement.toxml())
+ abort_script("Failed to find class referred in: \n %s",
+ object_element.toxml())
trace("zzz")
else:
- trace("Continue processing object with missing class
(--ignore-missing-class)")
-
- if self.dn_regexpObj != None:
- trace ("grep_dn check if object dn %s match pattern %s",
objectDnName, Options.grep_dn)
- if re.search(self.dn_regexpObj, objectDnName) == None:
- if Options.negateGrep_dn == False:
- trace ("Object dn %s does not match pattern %s",
objectDnName, Options.grep_dn)
+ trace("Continue processing object with missing class "
+ "(--ignore-missing-class)")
+
+ if self.dn_regexpObj is not None:
+ trace("Grep_dn check if object dn %s matches pattern %s",
+ object_dn_name, Options.grep_dn)
+ if re.search(self.dn_regexpObj, object_dn_name) is None:
+ if not Options.negateGrep_dn:
+ trace("Object dn %s does not match pattern %s",
+ object_dn_name, Options.grep_dn)
return
elif Options.negateGrep_dn:
- trace ("Object dn %s does not match negated pattern %s",
objectDnName, Options.grep_dn)
+ trace("Object dn %s does not match negated pattern %s",
+ object_dn_name, Options.grep_dn)
return
- trace("match ok :%s", objectDnName);
-
- if objectDnName in self.objectDnNameDict:
- if self.checkObjectClashAcceptable(objectDnName):
- trace("ignore duplicate object: %s with dn: %s", className,
objectDnName)
+
+ trace("match ok :%s", object_dn_name)
+
+ if object_dn_name in self.objectDnNameDict:
+ if self.check_object_clash_acceptable(object_dn_name):
+ trace("Ignore duplicate object: %s with dn: %s", class_name,
+ object_dn_name)
return
# TODO add code to check if this is valid clash
- #self.validateAndStoreDn(objectDnName, objectDnElement)
- self.objectDnNameDict[objectDnName] = objectDnElement
-
- # add to the complete object to ordered list (keyed by classname for
sorting)
- #self.objectList.append((className+objectDnName, objectElement))
- objectListKey = objectDnName # anything goes, its not used...
- if Options.sort == True:
- objectListKeyList = [self.getDnSortPrefix(objectDnName)]
- objectListKeyList.append(className)
- objectListKeyList.append(objectDnName)
- objectListKey = ''.join(objectListKeyList)
- #objectListKey = self.getDnSortPrefix(objectDnName)+className
- trace("Object sort order key: %s", objectListKey)
-
- self.objectList.append((objectListKey, (otherNodes, objectElement)))
-
- def getDnSortPrefix(self, objectDnName):
- sortKeyList = [ "A" ]
+ # self.validateAndStoreDn(object_dn_name, object_dn_element)
+ self.objectDnNameDict[object_dn_name] = object_dn_element
+
+ # Add the complete object to ordered list
+ # (keyed by class_name for sorting)
+ # self.objectList.append((class_name + object_dn_name, object_element))
+ object_list_key = object_dn_name # anything goes, it's not used...
+ if Options.sort:
+ object_list_key_list = [self.get_dn_sort_prefix(object_dn_name),
+ class_name, object_dn_name]
+ object_list_key = ''.join(object_list_key_list)
+ # objectListKey = self.get_dn_sort_prefix(objectDnName)+className
+ trace("Object sort order key: %s", object_list_key)
+
+ self.objectList.append((object_list_key,
+ (other_nodes, object_element)))
+
+ @staticmethod
+ def get_dn_sort_prefix(object_dn_name):
+ """ Get dn sort prefix """
+ sort_key_list = ["A"]
depth = 1
- maxDepth = 10
- # search for all unescaped comma (if any)
- for i in range(0, len(objectDnName)):
- if objectDnName[i] == ',':
- if i > 1 and objectDnName[i-1] != '\\':
- sortKeyList.append(",A")
- depth = depth +1
-
- if depth >= maxDepth:
- excStr = "Object reference depth is higher than expected (maximum
%d)" % maxDepth
- raise Exception(excStr)
-
- for i in range(depth+1, maxDepth):
- sortKeyList.append(" ")
-
- #sortKeyList.append("#")
- key = ''.join(sortKeyList)
- trace("getDnSortPrefix: %s", key)
+ max_depth = 10
+ # Search for all unescaped commas (if any)
+ for i in range(0, len(object_dn_name)):
+ if object_dn_name[i] == ',':
+ if i > 1 and object_dn_name[i - 1] != '\\':
+ sort_key_list.append(",A")
+ depth = depth + 1
+
+ if depth >= max_depth:
+ exc_str = "Object reference depth is higher than expected " \
+ "(maximum %d)" % max_depth
+ raise Exception(exc_str)
+
+ for i in range(depth + 1, max_depth):
+ sort_key_list.append(" ")
+
+ # sort_key_list.append("#")
+ key = ''.join(sort_key_list)
+ trace("get_dn_sort_prefix: %s", key)
return key
-
-
- def checkClassClashAcceptable(self, classElement, className):
- # previousClassValue = self.classDict.get(className)
- # TODO deep verify class Element clash is acceptable or not ?????
-
- if Options.ignoreVariants == False:
- abort_script("failed to merge input files class with name:%s exists in
multiple input files (use --ignore-variants to override)", className)
-
- return True
-
- def checkObjectClashAcceptable(self, objectDn):
- if Options.ignoreVariants == False:
- abort_script("failed to merge input files object with dn :%s exists in
multiple input files (use --ignore-variants to override)", objectDn)
- return True
-
-
- def processInputfile(self, filename):
+
+ @staticmethod
+ def check_class_clash_acceptable(class_element, class_name):
+ """ Check if class clash is acceptable """
+ # previous_class_value = self.classDict.get(class_name)
+ # TODO deep verify class element clash is acceptable or not ?????
+
+ if not Options.ignoreVariants:
+ abort_script("Failed to merge input files class with name: %s "
+ "exists in multiple input files "
+ "(use --ignore-variants to override)", class_name)
+
+ return True
+
+ @staticmethod
+ def check_object_clash_acceptable(object_dn):
+ """ Check if object clash is acceptable """
+ if not Options.ignoreVariants:
+ abort_script("Failed to merge input files object with dn: %s "
+ "exists in multiple input files "
+ "(use --ignore-variants to override)", object_dn)
+
+ return True
+
+ def process_input_file(self, file_name):
+ """ Process input file """
trace("")
- trace("processInputfile in file:%s", filename)
-
- if Options.isXmlLintFound and Options.schemaFilename != None:
- if self.validateXmlFileWithSchema(filename,
Options.schemaFilename) != 0:
- abort_script("failed to validate input file %s:", filename)
+ trace("process_input_file in file: %s", file_name)
+
+ if Options.isXmlLintFound and Options.schemaFilename is not None:
+ if self.validate_xml_file_with_schema(file_name,
+ Options.schemaFilename) != 0:
+ abort_script("Failed to validate input file %s:", file_name)
else:
- self.verifyInputXmlDocumentFileIsParsable(filename)
-
- doc = xml.dom.minidom.parse(filename)
- #doc = self.openXmlDocumentFileAndCheckNamespace(filename)
-
- if self.isResultDocInitialized == False:
- self.initResultDocument(doc)
-
-
- ## Fast forward to imm:contents element
+ self.verify_input_xml_document_file_is_parsable(file_name)
+
+ doc = xml.dom.minidom.parse(file_name)
+ # doc = self.open_xml_document_file_and_check_namespace(file_name)
+
+ if not self.isResultDocInitialized:
+ self.init_result_document(doc)
+
+ # Fast forward to imm:contents element
for element in doc.childNodes:
- otherNodes = []
- if (element.nodeName == self.imm_content_element_name):
- for childElement in element.childNodes:
- trace("imm:contents loop..... Nodename:%s NodeValue%s",
childElement.nodeName, childElement.nodeValue)
- if (childElement.nodeName == "class"):
- self.addClass(childElement, otherNodes)
- #for otherNode in :
- # trace("OtherNode: %s", otherNode.toxml())
- otherNodes = []
- elif (childElement.nodeName == "object"):
- self.addObject(childElement, otherNodes)
- #for otherNode in otherNodes:
- # trace("OtherNode: %s", otherNode.toxml())
- otherNodes = []
+ other_nodes = []
+ if element.nodeName == self.imm_content_element_name:
+ for child_element in element.childNodes:
+ trace("imm:contents loop.....nodeName: %s nodeValue: %s",
+ child_element.nodeName, child_element.nodeValue)
+ if child_element.nodeName == "class":
+ self.add_class(child_element, other_nodes)
+ # for other_node in other_nodes:
+ # trace("otherNode: %s", other_node.toxml())
+ other_nodes = []
+ elif child_element.nodeName == "object":
+ self.add_object(child_element, other_nodes)
+ # for other_node in other_nodes:
+ # trace("otherNode: %s", other_node.toxml())
+ other_nodes = []
else:
# probably text nodes....ignore if whitespace only
- childElementStr =
childElement.nodeValue.lstrip().rstrip()
- #if len(childElementStr) > 1:
- #otherNodes.append(childElement)
- otherNodes.append(childElement)
+ # child_element_str = \
+ # child_element.nodeValue.lstrip().rstrip()
+ # if len(child_element_str) > 1:
+ # other_nodes.append(child_element)
+ other_nodes.append(child_element)
-
return 0
-
- def saveResult(self):
+ def save_result(self):
+ """ Save merge result to file or print to stdout """
trace("")
-
- #if len(self.classList) < 1 and Options.grep_class != None:
- # exit_script("No classes matches pattern %s specified with
--grep-class. No document is saved. Exiting!", Options.grep_class)
- #if len(self.objectList) < 1 and Options.grep_dn != None:
- # exit_script("No objects matches pattern %s specified with --grep-dn.
No document is saved. Exiting!", Options.grep_dn)
+ # if len(self.classList) < 1 and Options.grep_class is not None:
+ # exit_script("No class matches pattern %s specified with
+ # --grep-class. No document is saved. Exiting!", Options.grep_class)
- # Use a temp file when output file is not specified. When this script finishes it prints the file to stdout
- # and removes the file
+ # if len(self.objectList) < 1 and Options.grep_dn is not None:
+ # exit_script("No object matches pattern %s specified with
+ # --grep-dn. No document is saved. Exiting!", Options.grep_dn)
+
+ # Use a temp file when output file is not specified.
+ # When this script finishes it prints the file to stdout and removes
+ # the file
if Options.stdout:
Options.outputFilename = "/tmp/merge_result.xml"
- if Options.sort == True:
- trace("sorting the classes & objects in resulting xml document")
+ if Options.sort:
+ trace("Sorting the classes & objects in resulting xml document")
self.classList.sort()
self.objectList.sort()
-
- trace("Number of classes in resulting xml document:%d",
len(self.classList))
-
- # iterate over all objects again to validate again when all objects
are parsed from inputfiles
- #if Options.disableParentDnValidation==False:
- # self.postValidateObjectList()
- #### I think there should not be imm validation functionality in merge
tool (use validate_immfile instead)
-
+
+ trace("Number of classes in resulting xml document: %d",
+ len(self.classList))
+
+ # Iterate over all objects again to validate again when all objects are
+ # parsed from input files
+ # if not Options.disableParentDnValidation:
+ # self.postValidateObjectList()
+ # I think there should not be imm validation functionality in merge
+ # tool (use validate_immfile instead)
+
for class_element_tuple in self.classList:
- if (Options.keepCommentElements):
- for textNode in class_element_tuple[1][0]:
- self.imm_content_element.appendChild(textNode)
+ if Options.keepCommentElements:
+ for text_node in class_element_tuple[1][0]:
+ self.imm_content_element.appendChild(text_node)
self.imm_content_element.appendChild(class_element_tuple[1][1])
for object_element_tuple in self.objectList:
- if (Options.keepCommentElements):
- for textNode in object_element_tuple[1][0]:
- self.imm_content_element.appendChild(textNode)
+ if Options.keepCommentElements:
+ for text_node in object_element_tuple[1][0]:
+ self.imm_content_element.appendChild(text_node)
self.imm_content_element.appendChild(object_element_tuple[1][1])
-
- tmpOutputFilename = Options.outputFilename+".tmp"
- file_object = open(tmpOutputFilename, "w")
-
- ## FIX for minidom problem with lost encoding info in saved xml
document
- trace("encoding in first source xml document:%s",
self.firstSourceDoc.encoding)
- if self.firstSourceDoc.encoding is not None and \
- self.firstSourceDoc.encoding.lower() == "utf-8":
+
+ tmp_output_file_name = Options.outputFilename+".tmp"
+ file_object = open(tmp_output_file_name, "w")
+
+ # Fix for minidom problem with lost encoding info in saved xml document
+ trace("Encoding in first source xml document: %s",
+ self.firstSourceDoc.encoding)
+ if self.firstSourceDoc.encoding is not None \
+ and self.firstSourceDoc.encoding.lower() == "utf-8":
xml_as_string = self.document.toxml("utf-8")
- #xml_as_string = self.document.toprettyxml("", "", "utf-8")
+ # xml_as_string = self.document.toprettyxml("", "", "utf-8")
else:
xml_as_string = self.document.toxml()
-
+
file_object.write(xml_as_string)
file_object.close()
- trace("Stored resulting xml document in tmp file: %s",
tmpOutputFilename)
-
+ trace("Stored resulting xml document in tmp file: %s",
+ tmp_output_file_name)
+
if Options.isXmlLintFound:
- #command = "/bin/sh -c 'XMLLINT_INDENT=\" \" ; export XMLLINT_INDENT; /usr/bin/xmllint
--format "+tmpOutputFilename+" --output "+Options.outputFilename +"'"
- if self.formatXmlFileWithXmlLint(tmpOutputFilename,
Options.outputFilename) != 0:
- abort_script("failed to validate input file %s:",
tmpOutputFilename)
- trace("delete the tmp file: %s", tmpOutputFilename)
- os.remove(tmpOutputFilename)
+ # command = "/bin/sh -c 'XMLLINT_INDENT=\" \";
+ # export XMLLINT_INDENT; /usr/bin/xmllint --format " +
+ # tmp_output_file_name + " --output " + Options.outputFilename +
+ # "'"
+ if self.format_xml_file_with_xmllint(tmp_output_file_name,
+ Options.outputFilename) != 0:
+ abort_script("Failed to validate input file: %s",
+ tmp_output_file_name)
+ trace("Delete the tmp file: %s", tmp_output_file_name)
+ os.remove(tmp_output_file_name)
else:
- # at least we should move file to its real name
- trace("shutil.move(%s, %s)", tmpOutputFilename,
Options.outputFilename)
- shutil.move(tmpOutputFilename, Options.outputFilename)
-
- trace("Number of classes parsed:%d stored:%d", self.classes_parsed,
len(self.classList))
- trace("Number of objects parsed:%d stored:%d", self.objects_parsed,
len(self.objectList))
-
- diff_classes = self.classes_parsed-len(self.classList)
- diff_objects = self.objects_parsed-len(self.objectList)
- print_info_stderr("Note! Merge ignored %d classes (parsed:%d
stored:%d)", diff_classes, self.classes_parsed, len(self.classList) )
- print_info_stderr("Note! Merge ignored %d objects (parsed:%d
stored:%d)", diff_objects, self.objects_parsed, len(self.objectList) )
-
-
- trace("Stored formatted xml document in file: %s",
Options.outputFilename)
-
- if Options.isXmlLintFound and Options.schemaFilename != None:
- self.validateXmlFileWithSchema(Options.outputFilename,
Options.schemaFilename)
-
+ # At least we should move the file to its real name
+ trace("shutil.move(%s, %s)", tmp_output_file_name,
+ Options.outputFilename)
+ shutil.move(tmp_output_file_name, Options.outputFilename)
+
+ trace("Number of classes parsed: %d stored: %d", self.classes_parsed,
+ len(self.classList))
+ trace("Number of objects parsed: %d stored: %d", self.objects_parsed,
+ len(self.objectList))
+
+ diff_classes = self.classes_parsed - len(self.classList)
+ diff_objects = self.objects_parsed - len(self.objectList)
+ print_info_stderr("Note! Merge ignored %d classes "
+ "(parsed: %d stored: %d)", diff_classes,
+ self.classes_parsed, len(self.classList))
+ print_info_stderr("Note! Merge ignored %d objects "
+ "(parsed: %d stored: %d)", diff_objects,
+ self.objects_parsed, len(self.objectList))
+
+ trace("Stored formatted xml document in file: %s",
+ Options.outputFilename)
+
+ if Options.isXmlLintFound and Options.schemaFilename is not None:
+ self.validate_xml_file_with_schema(Options.outputFilename,
+ Options.schemaFilename)
if Options.stdout:
- self.printToStdoutAndRemoveTmpFile(Options.outputFilename)
-
-#### end of class ResultImmDocument
-
-
-
-def printUsage():
- print "usage: immxml-merge [options] filename[s]"
- print """
- -o, --output specified outputfile
- (if option is omitted stdout is used)
- --grep-class PATTERN pattern match the class names in source file(s)
- (This option also sets disableParentDnValidation)
- At end of processing a summary of processed/ignored
- classes/objects is listed.
- --grep-v-class PATTERN negated pattern matching. Similar to "grep -v
PATTERN"
- --grep-dn PATTERN pattern match the object dn names in source file(s)
- (This option also sets disableParentDnValidation)
- At end of processing a summary of processed/ignored
- classes/objects is listed.
- --grep-v-dn PATTERN negated pattern matching. Similar to "grep -v
PATTERN"
- --ignore-variants when merge tool finds several definitions of same
- class or object the default behaviour is to abort the
- merge processing and print out which class/object is
- duplicated. With this option it is possible to
- continue merge, keeping the first instance of a class
- or object definition and ignore the other.
- At end of processing a summary of processed/ignored
- classes/objects is listed.
- --ignore-missing-class do not require class definitions referred by an
object
- to exist in source file(s) (Is required by default)
- --keepCommentElements keep embedded comment elements
- (experimental support: associates comment elements
- with subsequent class or object element which may be
- correct association....)
- --schema validate inputfiles and output(file) with the
supplied
- xsd schema file
- -s, --sort sort the merged class and object names
- -t, --trace print trace information to stderr
- -v, --version print version information and exit
- -h, --help display this help and exit
-
- See http://devel.opensaf.org/ for information and updates.
-"""
-
-def printVersion():
- print "immxml-merge version 0.5.1"
-
-
-
-
-def main(argv):
+ self.print_to_stdout_and_remove_tmp_file(Options.outputFilename)
+
+# End of MergedImmDocument class
+
+
+def print_usage():
+ """ Print usage of immxml-merge tool """
+ print ("usage: immxml-merge [options] filename[s]")
+ print ("""
+ -o, --output specified output file
+ (If option is omitted stdout is used)
+
+ --grep-class PATTERN pattern match the class names in source file(s)
+ (This option also sets disableParentDnValidation)
+ At end of processing a summary of processed/ignored
+ classes/objects is listed.
+
+ --grep-v-class PATTERN negated pattern matching
+ Similar to "grep -v PATTERN"
+
+ --grep-dn PATTERN pattern match the object dn names in source file(s)
+ (This option also sets disableParentDnValidation)
+ At end of processing a summary of processed/ignored
+ classes/objects is listed.
+
+ --grep-v-dn PATTERN negated pattern matching
+ Similar to "grep -v PATTERN"
+
+ --ignore-variants when merge tool finds several definitions of same
+ class or object the default behaviour is to abort
+ the merge processing and print out which
+ class/object is duplicated. With this option it is
+ possible to continue merge, keeping the first
+ instance of a class or object definition and ignore
+ the other. At end of processing a summary of
+ processed/ignored classes/objects is listed.
+
+ --ignore-missing-class do not require class definitions referred by an
+ object to exist in source file(s)
+ (Is required by default)
+
+ --keepCommentElements keep embedded comment elements
+ (experimental support: associates comment elements
+ with subsequent class or object element which may
+ be correct association....)
+
+ --schema validate input files and output(file) with the
+ supplied xsd schema file
+
+ -s, --sort sort the merged class and object names
+
+ -t, --trace print trace information to stderr
+
+ -v, --version print version information and exit
+
+ -h, --help display this help and exit
+
+ See http://devel.opensaf.org/ for information and updates.
+ """)
+
+
+def print_version():
+ """ Print version of immxml-merge tool """
+ print ("immxml-merge version 0.5.1")
+
+
+def main(argv):
+ """ Main program """
try:
- opts, args = getopt.getopt(argv, "thvso:", ["trace", "keep-comment-elements", "ignore-variants", "ignore-missing-class", "help", "version",
"sort", "grep-class=", "grep-v-class=", "grep-dn=", "grep-v-dn=", "output=", "schema="])
- except getopt.GetoptError, err:
- # print help information and exit:
+ opts, args = getopt.getopt(argv, "thvso:",
+ ["trace", "keep-comment-elements",
+ "ignore-variants", "ignore-missing-class",
+ "help", "version", "sort", "grep-class=",
+ "grep-v-class=", "grep-dn=", "grep-v-dn=",
+ "output=", "schema="])
+ except getopt.GetoptError as err:
+ # Print help information and exit:
print_info_stderr("%s", str(err))
- printUsage()
+ print_usage()
sys.exit(2)
-
- foundGrep_dn = False
- foundGrep_class = False
- for o, v in opts:
- if o in ["-t", "--trace"]:
+ found_grep_dn = False
+ found_grep_class = False
+
+ for opt, value in opts:
+ if opt in ["-t", "--trace"]:
BaseOptions.traceOn = True
- if o in ["--keep-comment-elements"]:
+ if opt == "--keep-comment-elements":
Options.keepCommentElements = True
- if o in ["--ignore-variants"]:
+ if opt == "--ignore-variants":
Options.ignoreVariants = True
- if o in ["--ignore-missing-class"]:
- Options.ignoreMissingClass = True
- if o in ["--grep-class"]:
- if foundGrep_class:
- abort_script("Only one --grep-v-class or --grep-class option may be
specified")
- foundGrep_class = True
- Options.grep_class = v
- Options.disableParentDnValidation = True
- if o in ["--grep-v-class"]:
- if foundGrep_class:
- abort_script("Only one --grep-v-class or --grep-class option may be
specified")
- foundGrep_class = True
+ if opt == "--ignore-missing-class":
+ Options.ignoreMissingClass = True
+ if opt == "--grep-class":
+ if found_grep_class:
+ abort_script("Only one --grep-v-class or --grep-class option "
+ "may be specified")
+ found_grep_class = True
+ Options.grep_class = value
+ Options.disableParentDnValidation = True
+ if opt == "--grep-v-class":
+ if found_grep_class:
+ abort_script("Only one --grep-v-class or --grep-class option "
+ "may be specified")
+ found_grep_class = True
Options.negateGrep_class = True
- Options.grep_class = v
- Options.disableParentDnValidation = True
- if o in ["--grep-v-dn"]:
- if foundGrep_dn:
- abort_script("Only one --grep-v-dn or --grep-dn option may be
specified")
- foundGrep_dn = True
+ Options.grep_class = value
+ Options.disableParentDnValidation = True
+ if opt == "--grep-v-dn":
+ if found_grep_dn:
+ abort_script("Only one --grep-v-dn or --grep-dn option may be "
+ "specified")
+ found_grep_dn = True
Options.negateGrep_dn = True
- Options.grep_dn = v
- Options.disableParentDnValidation = True
- if o in ["--grep-dn"]:
- if foundGrep_dn:
- abort_script("Only one --grep-v-dn or --grep-dn option may be
specified")
- foundGrep_dn = True
- Options.grep_dn = v
- Options.disableParentDnValidation = True
- if o in ("-o", "--output"):
+ Options.grep_dn = value
+ Options.disableParentDnValidation = True
+ if opt == "--grep-dn":
+ if found_grep_dn:
+ abort_script("Only one --grep-v-dn or --grep-dn option may be "
+ "specified")
+ found_grep_dn = True
+ Options.grep_dn = value
+ Options.disableParentDnValidation = True
+ if opt in ["-o", "--output"]:
Options.stdout = False
- Options.outputFilename = v
- if o in ("--schema"):
- Options.schemaFilename = v
- if o in ["-s", "--sort"]:
+ Options.outputFilename = value
+ if opt == "--schema":
+ Options.schemaFilename = value
+ if opt in ["-s", "--sort"]:
Options.sort = True
-
- if o in ["-v", "--version"]:
- printVersion()
+ if opt in ["-v", "--version"]:
+ print_version()
sys.exit(0)
- elif o in ["-h", "--help"]:
- printUsage()
+ elif opt in ["-h", "--help"]:
+ print_usage()
sys.exit(0)
-
- # cannot trace these until -t, Options.traceOn is effective (or not)
- trace("opts:%s", opts)
- trace("args:%s", args)
- trace("sys.path:%s", sys.path)
-
- if len(args) == 0:
- # print "Stdin processing not yet supported! (if ever!)"
- printUsage()
+
+ # Cannot trace these until -t, Options.traceOn is effective (or not)
+ trace("opts: %s", opts)
+ trace("args: %s", args)
+ trace("sys.path: %s", sys.path)
+
+ if not args:
+ # print ("stdin processing not yet supported! (if ever!)")
+ print_usage()
sys.exit(2)
-
-
- trace("Option object: \n %s", Options.printOptionSettings())
-
-
- if os.path.exists('/usr/bin/xmllint') == False:
- if (Options.schemaFilename == None ):
- # It is possible to continue without xmllint (limited w.r.t
formatting)
+
+ trace("Option object:\n %s", Options.print_option_settings())
+
+ if not os.path.exists('/usr/bin/xmllint'):
+ if Options.schemaFilename is None:
+ # It is possible to continue without xmllint
+ # (limited w.r.t formatting)
print_info_stderr("")
- print_info_stderr("Cannot find the linux command /usr/bin/xmllint which
is required for formatting!")
- print_info_stderr("Script continues but the result file may for example
lack linefeed characters.")
+ print_info_stderr("Cannot find the linux command /usr/bin/xmllint "
+ "which is required for formatting!")
+ print_info_stderr("Script continues but the result file may for "
+ "example lack linefeed characters.")
print_info_stderr("")
Options.isXmlLintFound = False
else:
- abort_script("Cannot find the required linux command /usr/bin/xmllint.
--schema option requires xmllint, Exiting!")
-
-
-
- fileList = retrieveFilenames(args)
-
- trace("starting to process files::\n")
- ## Create an Object to store classes and objects during process of input
files
- mergedDoc = MergedImmDocument()
- mergedDoc.initialize();
-
- for fileName in fileList:
- verifyInputFileReadAcess(fileName)
- mergedDoc.processInputfile(fileName)
- trace("Done with file:%s", fileName)
-
- ## store the resulting document with collected class and objects elements
- mergedDoc.saveResult()
+ abort_script("Cannot find the required linux command "
+ "/usr/bin/xmllint. --schema option requires xmllint, "
+ "Exiting!")
+
+ file_list = retrieve_file_names(args)
+ trace("Starting to process files::\n")
+ # Create an Object to store classes and objects during process of
+ # input files
+ merged_doc = MergedImmDocument()
+ merged_doc.initialize()
+
+ for file_name in file_list:
+ verify_input_file_read_access(file_name)
+ merged_doc.process_input_file(file_name)
+ trace("Done with file: %s", file_name)
+
+ # Store the resulting document with collected class and object elements
+ merged_doc.save_result()
print_info_stderr("Successfully merged input files!")
return 0
-
-
if __name__ == "__main__":
main(sys.argv[1:])
diff --git a/src/imm/tools/immxml-validate b/src/imm/tools/immxml-validate
index 89ce54e..e36ece0 100755
--- a/src/imm/tools/immxml-validate
+++ b/src/imm/tools/immxml-validate
@@ -1,50 +1,58 @@
#! /usr/bin/env python
-
-'''
- -*- OpenSAF -*-
-
- (C) Copyright 2009 The OpenSAF Foundation
-
- This program 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. This file and program are licensed
- under the GNU Lesser General Public License Version 2.1, February 1999.
- The complete license can be accessed from the following location:
- http://opensource.org/licenses/lgpl-license.php
- See the Copying file included with the OpenSAF distribution for full
- licensing terms.
-
- Author(s): Ericsson AB
-'''
-
-
-import re, os, sys, getopt, shutil
-from baseimm import * # Base class and functions for Merge and
validation utils
+# -*- OpenSAF -*-
+#
+# (C) Copyright 2009 The OpenSAF Foundation
+# (C) Copyright Ericsson AB 2017. All rights reserved.
+#
+# This program 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. This file and program are licensed
+# under the GNU Lesser General Public License Version 2.1, February 1999.
+# The complete license can be accessed from the following location:
+# http://opensource.org/licenses/lgpl-license.php
+# See the Copying file included with the OpenSAF distribution for full
+# licensing terms.
+#
+# Author(s): Ericsson AB
+#
+# pylint: disable=invalid-name,unused-argument
+""" immxml-validate tool """
+from __future__ import print_function
+import os
+import sys
+import getopt
import xml.dom.minidom
-from subprocess import call
+from baseimm import BaseOptions, BaseImmDocument, trace, retrieve_file_names, \
+ print_info_stderr, abort_script, verify_input_file_read_access
-
class Options(BaseOptions):
- #traceOn = False
+ """ immxml-validate options """
schemaFilename = None
isXmlLintFound = True
ignoreAttributeRefs = False
ignoreRdnAssociationRefs = False
-
+
@staticmethod
- def printOptionSettings():
- return BaseOptions.printOptionSettings()+' schemaFilename: %s\n' %
(Options.schemaFilename)
+ def print_option_settings():
+ return BaseOptions.print_option_settings() + ' schemaFilename: %s\n' \
+ % Options.schemaFilename
+
class AbortFileException(Exception):
+ """ Exception to raise when aborting file """
def __init__(self, value):
+ Exception.__init__(self)
self.value = value
+
def __str__(self):
- return repr(self.value)
+ return repr(self.value)
+
class ImmDocument(BaseImmDocument):
-
+ """ This class contains methods to validate an IMM XML file """
def __init__(self):
+ """ Class constructor """
self.imm_content_element = None
self.classList = []
self.classDict = {}
@@ -52,406 +60,464 @@ class ImmDocument(BaseImmDocument):
self.objectDnNameDict = {}
self.validateFailed = False
- def initialize(self):
+ @staticmethod
+ def initialize():
+ """ Initialize the validation process """
trace("initialize()")
-
- def addClass(self, classElement, otherNodes):
- className = classElement.getAttribute("name")
- trace("className: %s nodeType:%d nodeName:%s", className,
classElement.nodeType, classElement.nodeName)
-
- # check if class exist in dictionary map
- if className in self.classDict:
- # check if class clash is "acceptable"
+
+ @staticmethod
+ def check_class_clash_acceptable(class_element, class_name):
+ """ Check if class clash is acceptable. TBD """
+ pass
+
+ def add_class(self, class_element, other_nodes):
+ """ Add class to the list of classes to validate """
+ class_name = class_element.getAttribute("name")
+ trace("className: %s nodeType: %d nodeName: %s", class_name,
+ class_element.nodeType, class_element.nodeName)
+
+ # Check if class exists in dictionary map
+ if class_name in self.classDict:
+ # Check if class clash is "acceptable"
# i.e. should we bail out or not??
- if self.checkClassClashAcceptable(classElement, className):
- self.validate_failed("found duplicate class : %s", className)
+ if self.check_class_clash_acceptable(class_element, class_name):
+ self.validate_failed("Found duplicate class : %s", class_name)
else:
- attrlist = []
- attributeDict = {}
- rdnType = None
- for attribute in classElement.childNodes:
- attrname = None
- attrtype = None
+ attr_list = []
+ attribute_dict = {}
+ rdn_type = None
+ for attribute in class_element.childNodes:
+ attr_name = None
+ attr_type = None
if attribute.nodeName == "rdn":
for element in attribute.childNodes:
if element.nodeName == "type":
- rdnType = element.firstChild.nodeValue
+ rdn_type = element.firstChild.nodeValue
elif attribute.nodeName == "attr":
for element in attribute.childNodes:
if element.nodeName == "name":
- attrname = element.firstChild.nodeValue
- if attrname in attrlist:
- raise Exception("Attribute '%s' is defined more than
once in class '%s'" % (attrname, className))
- attrlist.append(attrname);
- elif element.nodeName == "type":
- attrtype = element.firstChild.nodeValue
-
- if attrname != None and attrtype != None:
- attributeDict[attrname] = attrtype
+ attr_name = element.firstChild.nodeValue
+ if attr_name in attr_list:
+ raise Exception("Attribute '%s' is defined "
+ "more than once in class '%s'"
+ % (attr_name, class_name))
+ attr_list.append(attr_name)
+ elif element.nodeName == "type":
+ attr_type = element.firstChild.nodeValue
+
+ if attr_name is not None and attr_type is not None:
+ attribute_dict[attr_name] = attr_type
break
- del attrlist
-
- classDefDict = {}
- self.classDict[className] = classDefDict
- self.classDict[className]["attributes"] = attributeDict
- self.classDict[className]["rdn"] = rdnType
- # add to ordered list
- self.classList.append((className, (otherNodes, classElement)))
-
- def addObject(self, objectElement, otherNodes):
- className = objectElement.getAttribute("class")
- trace("DUMPING Object with className: %s \n %s", className,
objectElement.toxml())
-
- attrList = []
- objectDnElement = None
- ## find "dn" childnode
- for childNode in objectElement.childNodes:
- if childNode.nodeName == "dn" and objectDnElement == None:
- objectDnElement = childNode
- elif childNode.nodeName == "attr":
- for attrChild in childNode.childNodes:
- if attrChild.nodeName == "name":
- if attrChild.firstChild.nodeValue in attrList:
- raise Exception("Attribute '%s' is defined more than
once in object" % (attrChild.firstChild.nodeValue))
- attrList.append(attrChild.firstChild.nodeValue)
-
- del attrList
-
- if objectDnElement == None or className == None or
objectDnElement.firstChild == None:
- self.validate_failed("Failed to find classname or the dn childnode in
object:%s. " ,objectElement.toxml())
-
-
-
- # objectDnName = objectDnElement.nodeValue
- ### NOTE dn name should be the nodeValue of objectDnName...
- ## however minidom probably gets confused by the equal sign in dn value
- # so it ends up adding a text node as a child......
- objectDnName = objectDnElement.firstChild.nodeValue
- trace("objectDn key: %s", objectDnName)
-
- trace("objectDnElement: %s", objectDnElement.toxml())
-
- # classname must exist in dictionary map
- if className not in self.classDict:
- self.validate_failed("failed to find class '%s' in %s", className,
objectElement.toxml())
-
-
- if objectDnName in self.objectDnNameDict:
- self.validate_failed("found duplicate object : %s",
objectElement.toxml())
-
- self.validateAndStoreDn(objectDnName, objectDnElement, className)
-
- # add to the complete object to ordered list (keyed by classname for
sorting)
- #self.objectList.append((className+objectDnName, objectElement))
- self.objectList.append((objectDnName, (otherNodes, objectElement)))
-
-
- def validateAndStoreDn(self, objectDnName, objectDnElement, className):
- commaIndex = -1
- dnLen = len(objectDnName)
- if dnLen > 256:
- self.validate_failed("length of dn is %d (max 256): %s",
len(objectDnName), objectDnName)
-
-
- # search for first unescaped comma (if any)
- for i in range(0, dnLen):
- if objectDnName[i] == ',':
- if i > 1 and objectDnName[i-1] != '\\':
- commaIndex = i
+ del attr_list
+
+ class_def_dict = {}
+ self.classDict[class_name] = class_def_dict
+ self.classDict[class_name]["attributes"] = attribute_dict
+ self.classDict[class_name]["rdn"] = rdn_type
+ # Add to ordered list
+ self.classList.append((class_name, (other_nodes, class_element)))
+
+ def add_object(self, object_element, other_nodes):
+ """ Add object to the list of objects to validate """
+ class_name = object_element.getAttribute("class")
+ trace("DUMPING Object with className: %s\n %s", class_name,
+ object_element.toxml())
+
+ attr_list = []
+ object_dn_element = None
+ # Find "dn" child node
+ for child_node in object_element.childNodes:
+ if child_node.nodeName == "dn" and object_dn_element is None:
+ object_dn_element = child_node
+ elif child_node.nodeName == "attr":
+ for attr_child in child_node.childNodes:
+ if attr_child.nodeName == "name":
+ if attr_child.firstChild.nodeValue in attr_list:
+ raise Exception("Attribute '%s' is defined more "
+ "than once in object" %
+ attr_child.firstChild.nodeValue)
+ attr_list.append(attr_child.firstChild.nodeValue)
+
+ del attr_list
+
+ if object_dn_element is None or class_name is None \
+ or object_dn_element.firstChild is None:
+ self.validate_failed("Failed to find class name or the dn child "
+ "node in object: %s. ",
+ object_element.toxml())
+
+ # object_dn_name = object_dn_element.nodeValue
+ # NOTE: dn name should be the nodeValue of object_dn_name
+ # However minidom probably gets confused by the equal sign in dn value
+ # so it ends up adding a text node as a child.
+ object_dn_name = object_dn_element.firstChild.nodeValue
+ trace("objectDn key: %s", object_dn_name)
+ trace("objectDnElement: %s", object_dn_element.toxml())
+
+ # class_name must exist in dictionary map
+ if class_name not in self.classDict:
+ self.validate_failed("Failed to find class '%s' in %s",
+ class_name, object_element.toxml())
+
+ if object_dn_name in self.objectDnNameDict:
+ self.validate_failed("Found duplicate object: %s",
+ object_element.toxml())
+
+ self.validate_and_store_dn(object_dn_name, object_dn_element,
+ class_name)
+
+ # Add the complete object to ordered list
+ # (keyed by class_name for sorting)
+ # self.objectList.append((class_name + object_dn_name, object_element))
+ self.objectList.append((object_dn_name, (other_nodes, object_element)))
+
+ def validate_and_store_dn(self, object_dn_name, object_dn_element,
+ class_name):
+ """ Validate and store object's dn """
+ comma_index = -1
+ dn_len = len(object_dn_name)
+ if dn_len > 256:
+ self.validate_failed("Length of dn is %d (max 256): %s", dn_len,
+ object_dn_name)
+
+ # Search for first unescaped comma (if any)
+ for i in range(0, dn_len):
+ if object_dn_name[i] == ',':
+ if i > 1 and object_dn_name[i - 1] != '\\':
+ comma_index = i
break
-
- if commaIndex == -1:
- trace("Found root element (no unescaped commas): %s", objectDnName)
+
+ if comma_index == -1:
+ trace("Found root element (no unescaped commas): %s",
+ object_dn_name)
# Looks alright, add element to "dn" dictionary
- self.objectDnNameDict[objectDnName] = objectDnElement
+ self.objectDnNameDict[object_dn_name] = object_dn_element
return
-
- objectOwnerPart = objectDnName[commaIndex+1:]
- objectIdPart = objectDnName[:commaIndex]
- trace("ObjectDN: %s objectOwner: %s objectIdPart:%s", objectDnName,
objectOwnerPart, objectIdPart)
-
-
- # store all dn's even if it is SA_NAME_T
- # this means even the association references is stored as objects
which could be parents
- # move length checking (64 bytes) to postValidate...
- self.objectDnNameDict[objectDnName] = objectDnElement
-
-
+
+ object_owner_part = object_dn_name[comma_index + 1:]
+ object_id_part = object_dn_name[:comma_index]
+ trace("ObjectDN: %s objectOwner: %s objectIdPart: %s", object_dn_name,
+ object_owner_part, object_id_part)
+
+ # Store all dn's even if it is SA_NAME_T
+ # This means even the association references are stored as objects
+ # which could be parents
+ # move length checking (64 bytes) to post_validate()
+ self.objectDnNameDict[object_dn_name] = object_dn_element
+
# NOTE for some imm.xml file (for example as result of immdump tool)
- # the object dn's are not ordered in a way that it is possible to
validate ownership
- # while parsing the inputfiles.
- # Instead it must be performed after the input files are completely
parsed
+ # the object dn's are not ordered in a way that it is possible to
+ # validate ownership while parsing the input files. Instead it must be
+ # performed after the input files are completely parsed.
# validate(): Do this type of IMM validation in one go afterwards
-
- return
-
+ return
+
def validate_failed(self, *args):
+ """ Print validation failed message to stderr and
+ set validateFailed flag """
printf_args = []
for i in range(1, len(args)):
printf_args.append(args[i])
-
- formatStr = "\nValidation failed: " + args[0]
- print >> sys.stderr, formatStr % tuple(printf_args)
- #sys.exit(2)
- # no more exit, set failedFlag True
+
+ format_str = "\nValidation failed: " + args[0]
+ print (format_str % tuple(printf_args), file=sys.stderr)
+ # sys.exit(2)
+ # no more exit, set failedFlag to True
self.validateFailed = True
def abort_file(self, *args):
+ """ Abort file validation and raise exception """
self.validate_failed(*args)
raise AbortFileException("Aborting current file!")
-
-
- def postValidateObjectList(self):
-
- for tupleNode in self.objectList:
- objectElement = tupleNode[1][1]
- className = objectElement.getAttribute("class")
-
- objectDnElement = None
- ## find "dn" childnode
- for childNode in objectElement.childNodes:
- if childNode.nodeName == "dn":
- objectDnElement = childNode
- if objectDnElement.firstChild == None:
- # this is really a workaround for minidom bug?: assume
dn name should be the nodeValue of objectDnName but with minidom that is not
true...
- raise Exception("Cannot find child element of dn element
(required by minidom)")
- objectDnName = objectDnElement.firstChild.nodeValue
- trace("objectDnElement: %s", objectDnElement.toxml())
- trace("objectDn key: %s", objectDnName)
- # validate dn w.r.t ownership
- self.postValidateDn(objectDnName, objectDnElement,
className)
- #break
- elif childNode.nodeName == "attr":
- nameOfAttributeToValidate = None
- for element in childNode.childNodes:
+
+ def post_validate_object_list(self):
+ """ Post-validate object list """
+ for tuple_node in self.objectList:
+ object_element = tuple_node[1][1]
+ class_name = object_element.getAttribute("class")
+ attributes = self.classDict[class_name]["attributes"]
+
+ object_dn_element = None
+ # Find "dn" child node
+ for child_node in object_element.childNodes:
+ if child_node.nodeName == "dn":
+ object_dn_element = child_node
+ if object_dn_element.firstChild is None:
+ # This is really a workaround for minidom bug?:
+ # Assume dn name should be the nodeValue of
+ # object_dn_name but with minidom that is not true.
+ raise Exception("Cannot find child element of dn "
+ "element (required by minidom)")
+ object_dn_name = object_dn_element.firstChild.nodeValue
+ trace("objectDnElement: %s", object_dn_element.toxml())
+ trace("objectDn key: %s", object_dn_name)
+ # Validate dn w.r.t ownership
+ self.post_validate_dn(object_dn_name, object_dn_element,
+ class_name)
+ # break
+ elif child_node.nodeName == "attr":
+ name_of_attribute_to_validate = None
+ for element in child_node.childNodes:
if element.nodeName == "name":
- attrname = element.firstChild.nodeValue
- if attrname in
self.classDict[className]["attributes"]:
- if self.classDict[className]["attributes"][attrname] ==
"SA_NAME_T":
- nameOfAttributeToValidate = attrname
+ attr_name = element.firstChild.nodeValue
+ if attr_name in attributes:
+ if attributes[attr_name] == "SA_NAME_T":
+ name_of_attribute_to_validate = attr_name
else:
- # attribute exist in classDict but type is
not further validated
+ # Attribute exists in classDict but type is
+ # not further validated
break
else:
- self.postValidateMissingAttribute(attrname,
className, objectDnElement)
- elif element.nodeName == "value":
- nodeValue = element.firstChild.nodeValue
-
self.postValidateAttributeSaNameT(nameOfAttributeToValidate, nodeValue,
className, objectDnElement)
- # multiple values allowed....no break
-
-
- trace("postValidateObjectList() complete!")
-
- def postValidateAttributeSaNameT(self, attributeName, attributeValue,
className, objectElement):
- if Options.ignoreAttributeRefs == True:
+ self.post_validate_missing_attribute(
+ attr_name, class_name, object_dn_element)
+ elif element.nodeName == "value":
+ node_value = element.firstChild.nodeValue
+ self.post_validate_attribute_sa_name_t(
+ name_of_attribute_to_validate, node_value,
+ class_name, object_dn_element)
+ # Multiple values allowed....no break
+
+ trace("post_validate_object_list() complete!")
+
+ def post_validate_attribute_sa_name_t(self, attribute_name,
+ attribute_value, class_name,
+ object_element):
+ """ Post-validate SaNameT attribute """
+ if Options.ignoreAttributeRefs:
return
-
- if attributeValue not in self.objectDnNameDict:
- self.validate_failed("NOTE: The object with rdn '%s' referred in
attribute %s does not exist (The attribute is element in object with class: %s dn:
%s)", attributeValue, attributeName, className, objectElement.toxml())
-
- def postValidateMissingAttribute(self, attributeName, className,
objectElement):
- self.validate_failed("NOTE: The attribute %s does not exist in class
definition (The attribute is element in object with class: %s dn: %s)",
attributeName, className, objectElement.toxml())
-
-
- def postValidateDn(self, objectDnName, objectDnElement, className):
- commaIndex = -1
- dnLen = len(objectDnName)
-
- # search for first unescaped comma (if any)
- for i in range(0, dnLen):
- if objectDnName[i] == ',':
- if i > 1 and objectDnName[i-1] != '\\':
- commaIndex = i
+
+ if attribute_value not in self.objectDnNameDict:
+ self.validate_failed("NOTE: The object with rdn '%s' referred in "
+ "attribute %s does not exist (The attribute "
+ "is element in object with class: %s dn: %s)",
+ attribute_value, attribute_name, class_name,
+ object_element.toxml())
+
+ def post_validate_missing_attribute(self, attribute_name, class_name,
+ object_element):
+ """ Post-validate missing attribute """
+ self.validate_failed("NOTE: The attribute %s does not exist in class "
+ "definition (The attribute is element in object "
+ "with class: %s dn: %s)", attribute_name,
+ class_name, object_element.toxml())
+
+ def post_validate_dn(self, object_dn_name, object_dn_element, class_name):
+ """ Post-validate dn """
+ comma_index = -1
+ dn_len = len(object_dn_name)
+
+ # Search for first unescaped comma (if any)
+ for i in range(0, dn_len):
+ if object_dn_name[i] == ',':
+ if i > 1 and object_dn_name[i - 1] != '\\':
+ comma_index = i
break
-
- if commaIndex == -1:
- trace("Found root element (no unescaped commas): %s", objectDnName)
- return
-
- objectOwnerPart = objectDnName[commaIndex+1:]
- objectPart = objectDnName[:commaIndex]
- trace("ObjectDN: %s objectOwner: %s objectPart:%s", objectDnName,
objectOwnerPart, objectPart)
-
- # owner should exist for both SA_NAME_T and SA_STRING_T
- if objectOwnerPart not in self.objectDnNameDict:
- print_info_stderr("validate Dn in %s", objectDnElement.toxml())
- self.validate_failed("Parent to %s is not found %s", objectDnName,
objectDnElement.toxml())
-
- trace("postValidateDn() OK parentPart %s found in objectDnNameDict",
objectOwnerPart)
-
- # But in case dn is a SA_NAME_T also the objectIdPart
- # should exist in dictionary....
- if self.classDict[className]["rdn"] == "SA_NAME_T":
- # find value of association (remove association name)
- equalSignIndex = objectPart.find("=")
- objectName = objectPart[:equalSignIndex]
- objectValue = objectPart[equalSignIndex+1:]
- objectValueEqualSignIndex = objectValue.find("=")
-
- # x=y vs x=y=z
- if objectValueEqualSignIndex != -1:
- if Options.ignoreRdnAssociationRefs == False:
- associationValue = objectValue
- # remove escaping
- unescapedDN = associationValue.replace('\\','')
- if unescapedDN not in self.objectDnNameDict:
- print_info_stderr("validate Dn in %s",
objectDnElement.toxml())
- self.validate_failed("The associated object %s is not found
%s", unescapedDN, objectDnElement.toxml())
- trace("postValidateDn() OK The associated object %s is found
in objectDnNameDict (Dn has type SA_NAME_T)", unescapedDN)
- else:
- if len(objectValue) > 64:
- print_info_stderr("validate Dn in %s",
objectDnElement.toxml())
- self.validate_failed("length of object value is %d (max 64):
%s", len(objectPart), objectValue)
-
- return
+ if comma_index == -1:
+ trace("Found root element (no unescaped commas): %s",
+ object_dn_name)
+ return
+ object_owner_part = object_dn_name[comma_index + 1:]
+ object_part = object_dn_name[:comma_index]
+ trace("ObjectDN: %s objectOwner: %s objectPart: %s", object_dn_name,
+ object_owner_part, object_part)
+
+ # Owner should exist for both SA_NAME_T and SA_STRING_T
+ if object_owner_part not in self.objectDnNameDict:
+ print_info_stderr("Validate dn in %s", object_dn_element.toxml())
+ self.validate_failed("Parent to %s is not found in %s",
+ object_dn_name, object_dn_element.toxml())
+
+ trace("post_validate_dn() OK parentPart %s found in objectDnNameDict",
+ object_owner_part)
+
+ # But in case dn is a SA_NAME_T also the objectIdPart should exist
+ # in dictionary
+ if self.classDict[class_name]["rdn"] == "SA_NAME_T":
+ # Find value of association (remove association name)
+ equal_sign_index = object_part.find("=")
+ # object_name = object_part[:equal_sign_index]
+ object_value = object_part[equal_sign_index + 1:]
+ object_value_equal_sign_index = object_value.find("=")
-
- def processInputfile(self, filename):
+ # x=y vs x=y=z
+ if object_value_equal_sign_index != -1:
+ if not Options.ignoreRdnAssociationRefs:
+ association_value = object_value
+ # Remove escape characters
+ unescaped_dn = association_value.replace('\\', '')
+ if unescaped_dn not in self.objectDnNameDict:
+ print_info_stderr("Validate dn in %s",
+ object_dn_element.toxml())
+ self.validate_failed("The associated object %s is not "
+ "found in %s", unescaped_dn,
+ object_dn_element.toxml())
+ trace("post_validate_dn() OK The associated object %s is "
+ "found in objectDnNameDict (dn has type SA_NAME_T)",
+ unescaped_dn)
+ else:
+ if len(object_value) > 64:
+ print_info_stderr("Validate dn in %s",
+ object_dn_element.toxml())
+ self.validate_failed("Length of object value is %d "
+ "(max 64): %s", len(object_part),
+ object_value)
+ return
+
+ def process_input_file(self, file_name):
+ """ Process IMM XML input file """
trace("")
- trace("processInputfile() :%s", filename)
-
- if Options.isXmlLintFound and Options.schemaFilename != None:
- if self.validateXmlFileWithSchema(filename,
Options.schemaFilename) != 0:
- self.abort_file("failed to validate input file %s: with xml
schema", filename)
+ trace("process_input_file(): %s", file_name)
+
+ if Options.isXmlLintFound and Options.schemaFilename is not None:
+ if self.validate_xml_file_with_schema(file_name,
+ Options.schemaFilename) != 0:
+ self.abort_file("Failed to validate input file %s with xml "
+ "schema", file_name)
else:
- self.verifyInputXmlDocumentFileIsParsable(filename)
+ self.verify_input_xml_document_file_is_parsable(file_name)
+
+ doc = xml.dom.minidom.parse(file_name)
- doc = xml.dom.minidom.parse(filename)
-
-
- ## Fast forward to imm:contents element
+ # Fast forward to imm:contents element
for element in doc.childNodes:
- otherNodes = []
- if (element.nodeName == self.imm_content_element_name):
- for childElement in element.childNodes:
- trace("imm:contents loop..... Nodename:%s NodeValue%s",
childElement.nodeName, childElement.nodeValue)
- if (childElement.nodeName == "class"):
- self.addClass(childElement, otherNodes)
- otherNodes = []
- elif (childElement.nodeName == "object"):
- self.addObject(childElement, otherNodes)
- otherNodes = []
+ other_nodes = []
+ if element.nodeName == self.imm_content_element_name:
+ for child_element in element.childNodes:
+ trace("imm:contents loop.....NodeName: %s NodeValue: %s",
+ child_element.nodeName, child_element.nodeValue)
+ if child_element.nodeName == "class":
+ self.add_class(child_element, other_nodes)
+ other_nodes = []
+ elif child_element.nodeName == "object":
+ self.add_object(child_element, other_nodes)
+ other_nodes = []
else:
- # probably text nodes....ignore if whitespace only
- childElementStr =
childElement.nodeValue.lstrip().rstrip()
- #if len(childElementStr) > 1:
- #otherNodes.append(childElement)
- otherNodes.append(childElement)
+ # Probably text nodes
+ # Ignore if whitespace only
+ # child_element_str = \
+ # child_element.nodeValue.lstrip().rstrip()
+ # if len(child_element_str) > 1:
+ # other_nodes.append(child_element)
+ other_nodes.append(child_element)
-
return 0
-
-
- def postProcessValidate(self):
- # iterate over all objects again to validate again when all objects
are parsed from inputfiles
- self.postValidateObjectList()
-
-#### end of class ImmDocument
-
-def printUsage():
- print "usage: immxml-validate [options] filename[s]"
- print """
- --schema validate inputfiles with the supplied
- xsd schema file
- -t, --trace print trace information to stderr
- --ignore-attribute-refs
- specifying this option then the tool skips to
- validate that SA_NAME_T attributes references
- existing objects
- --ignore-rdn-association-refs
- specifying this option then the tool skips to
- validate that SA_NAME_T rdn association references
- existing objects
- -v, --version print version information and exit
- -h, --help display this help and exit
-
+
+ def post_process_validate(self):
+ """ Post validation process """
+ # Iterate over all objects again to validate again when all objects are
+ # parsed from input files
+ self.post_validate_object_list()
+
+# End of ImmDocument class
+
+
+def print_usage():
+ """ Print usage of immxml-validate tool """
+ print ("usage: immxml-validate [options] filename[s]")
+ print ("""
+ --schema validate input files with the supplied xsd schema file
+
+ -t, --trace print trace information to stderr
+
+ --ignore-attribute-refs
+ if this option is specified, the tool skips to validate
+ that SA_NAME_T attributes references existing objects
+
+ --ignore-rdn-association-refs
+ if this option is specified, the tool skips to validate
+ that SA_NAME_T rdn association references existing
+ objects
+
+ -v, --version print version information and exit
+
+ -h, --help display this help and exit
+
See http://devel.opensaf.org/ for information and updates.
-"""
-
-def printVersion():
- print "immxml-validate version 0.5.1"
+ """)
+
+def print_version():
+ """ Print version of immxml-validate tool """
+ print ("immxml-validate version 0.5.1")
-def main(argv):
+def main(argv):
+ """ Main program """
try:
- opts, args = getopt.getopt(argv, "thvso", ["trace", "help", "version", "schema=",
"ignore-attribute-refs", "ignore-rdn-association-refs"])
- except getopt.GetoptError, err:
- # print help information and exit:
+ opts, args = getopt.getopt(argv, "thv",
+ ["trace", "help", "version", "schema=",
+ "ignore-attribute-refs",
+ "ignore-rdn-association-refs"])
+ except getopt.GetoptError as err:
+ # Print help information and exit
print_info_stderr("%s", str(err))
- printUsage()
+ print_usage()
sys.exit(2)
-
-
- for o, v in opts:
- if o in ["-t", "--trace"]:
+
+ for opt, value in opts:
+ if opt in ["-t", "--trace"]:
BaseOptions.traceOn = True
- if o in ("--schema"):
- Options.schemaFilename = v
- if o in ("--ignore-attribute-refs"):
+ if opt == "--schema":
+ Options.schemaFilename = value
+ if opt == "--ignore-attribute-refs":
Options.ignoreAttributeRefs = True
- if o in ("--ignore-rdn-association-refs"):
+ if opt == "--ignore-rdn-association-refs":
Options.ignoreRdnAssociationRefs = True
- if o in ["-v", "--version"]:
- printVersion()
+ if opt in ["-v", "--version"]:
+ print_version()
sys.exit(0)
- elif o in ["-h", "--help"]:
- printUsage()
+ elif opt in ["-h", "--help"]:
+ print_usage()
sys.exit(0)
-
- # cannot trace these until -t, Options.traceOn is effective (or not)
+
+ # Cannot trace these until -t, Options.traceOn is effective (or not)
trace("opts:%s", opts)
trace("args:%s", args)
trace("sys.path:%s", sys.path)
-
- if len(args) == 0:
- printUsage()
+
+ if not args:
+ print_usage()
sys.exit(2)
-
-
- trace("Option object: \n %s", Options.printOptionSettings())
-
-
- if os.path.exists('/usr/bin/xmllint') == False:
- if (Options.schemaFilename != None ):
- abort_script("Cannot find the required linux command /usr/bin/xmllint.
--schema option requires xmllint, Exiting!")
-
- fileList = retrieveFilenames(args)
-
- trace("starting to process files::\n")
- atLeastOneFileFailed = False
- for fileName in fileList:
+
+ trace("Option object:\n %s", Options.print_option_settings())
+
+ if not os.path.exists('/usr/bin/xmllint'):
+ if Options.schemaFilename is not None:
+ abort_script("Cannot find the required linux command "
+ "/usr/bin/xmllint. '--schema' option requires "
+ "xmllint, Exiting!")
+
+ file_list = retrieve_file_names(args)
+
+ trace("Starting to process files...\n")
+ at_least_one_file_failed = False
+ for file_name in file_list:
try:
doc = ImmDocument()
- verifyInputFileReadAcess(fileName)
- doc.initialize();
-
- doc.processInputfile(fileName)
- if doc.validateFailed == False:
- doc.postProcessValidate()
+ verify_input_file_read_access(file_name)
+ doc.initialize()
+ doc.process_input_file(file_name)
+ if not doc.validateFailed:
+ doc.post_process_validate()
except AbortFileException:
doc.validateFailed = True
-
-
- if doc.validateFailed == True:
- atLeastOneFileFailed = True
- print_info_stderr("Validation failed of file:%s", fileName)
+
+ if doc.validateFailed:
+ at_least_one_file_failed = True
+ print_info_stderr("Validation failed for file: %s", file_name)
else:
- print_info_stderr("Validation succeded of file:%s", fileName)
-
- trace("Done with file:%s", fileName)
-
- if atLeastOneFileFailed == True:
+ print_info_stderr("Validation succeeded for file: %s", file_name)
+
+ trace("Done with file: %s", file_name)
+
+ if at_least_one_file_failed:
sys.exit(2)
else:
return 0
-
-
-
if __name__ == "__main__":
main(sys.argv[1:])
diff --git a/tools/devel/dot/trace2dot b/tools/devel/dot/trace2dot
index dac0cf3..160617c 100755
--- a/tools/devel/dot/trace2dot
+++ b/tools/devel/dot/trace2dot
@@ -2,7 +2,7 @@
#
#
# (C) Copyright 2015 The OpenSAF Foundation
-# Copyright Ericsson AB 2015, 2016, 2017 - All Rights Reserved.
+# (C) Copyright Ericsson AB 2015, 2016, 2017. All rights reserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -15,24 +15,25 @@
#
# Author(s): Ericsson AB
#
-#
"""
- trace2dot creates a runtime call graph using an opensaf trace file as input
- and produces a dot file. The generated dot file can be viewed graphically
using e.g. dotty.
-
- Example:
- Create a dot file, amfd_trace.dot from osafamfd trace file. Start from
function saClmDispatch.
- $ trace2dot -t osafamfd -f saClmDispatch -d amfd_trace.dot
- $ dotty amfd_trace.dot
-
+trace2dot creates a runtime call graph using an opensaf trace file as input and
+produces a dot file. The generated dot file can be viewed graphically using
+tool such as dotty.
+
+Example:
+Create a dot file, amfd_trace.dot from osafamfd trace file. Start from function
+saClmDispatch.
+$ trace2dot -t osafamfd -f saClmDispatch -d amfd_trace.dot
+$ dotty amfd_trace.dot
"""
+from __future__ import print_function
import sys
import os
import argparse
def run(trace_file, from_function, dot_file):
- ''' TBD '''
+ """ TBD """
infile = open(trace_file)
if dot_file:
@@ -50,9 +51,9 @@ def run(trace_file, from_function, dot_file):
def check_infile(trace_file):
- ''' Rudimentary check for missing TRACE_ENTER/TRACE_LEAVE. Will not
- check for e.g. returns before TRACE_LEAVE.
- '''
+ """ Rudimentary check for missing TRACE_ENTER/TRACE_LEAVE.
+ Will not check for, e.g. return statements, before TRACE_LEAVE.
+ """
infile = open(trace_file)
trace_enter = set()
trace_leave = set()
@@ -79,7 +80,7 @@ def check_infile(trace_file):
def process_infile(infile, from_function, outfile):
- ''' TBD '''
+ """ TBD """
function_names = []
from_func_found = False
@@ -96,12 +97,16 @@ def process_infile(infile, from_function, outfile):
function_names.append(func_enter)
- if len(function_names) > 1:
+ if function_names:
outfile.write(
- func_enter + ' [ordering=out, color=grey, shape=box,
label="' + func_enter + '"];\n')
+ func_enter +
+ ' [ordering=out, color=grey, shape=box, label="' +
+ func_enter + '"];\n')
else:
outfile.write(
- func_enter + ' [ordering=out, color=red, shape=box,
label="' + func_enter + '"];\n')
+ func_enter +
+ ' [ordering=out, color=red, shape=box, label="' +
+ func_enter + '"];\n')
if items[5] == '<<':
func_leave = items[6].rstrip(':')
@@ -109,22 +114,24 @@ def process_infile(infile, from_function, outfile):
if from_function == func_leave:
break
- if len(function_names) > 0:
+ if function_names:
func_enter = function_names.pop()
if func_enter != func_leave:
- print('%s %s %s' % (func_enter, ' has no matching
TRACE_LEAVE, found ', func_leave))
+ print('%s %s %s' %
+ (func_enter,
+ ' has no matching TRACE_LEAVE, found ',
+ func_leave))
outfile.write(func_leave + ' -> ' + func_enter + '\n')
else:
- if len(function_names) > 0:
+ if function_names:
caller = function_names[len(function_names) - 1]
outfile.write(caller + ' -> ' + func_enter + '\n')
def file_exists(filename):
- '''Check if arg is a valid file that already exists on the file
- system.
- '''
+ """ Check if arg is a valid file that already exists on the file system.
+ """
if not os.path.exists(filename):
raise argparse.ArgumentTypeError(
"The file %s does not exist!" % filename)
@@ -133,18 +140,20 @@ def file_exists(filename):
def main():
- ''' program main '''
+ """ Main program """
parser = argparse.ArgumentParser(
- description="Create runtime callgraph from OpenSAF trace file")
+ description="Create runtime call graph from OpenSAF trace file")
parser.add_argument('-t', '--tracefile', nargs='+',
type=file_exists, help='OpenSAF trace file')
parser.add_argument('-f', '--fromfunction', nargs='+',
- help='Show runtime callgraph from function')
- parser.add_argument('-d', '--dotfile', nargs='+', help='Result file in dot
format')
- parser.add_argument('-c', '--checkfile', nargs='+',
- type=file_exists, help='Check infile for matching
trace_enter trace_leave')
+ help='Show runtime call graph from function')
+ parser.add_argument('-d', '--dotfile', nargs='+',
+ help='Result file in dot format')
+ parser.add_argument('-c', '--checkfile', nargs='+', type=file_exists,
+ help='Check infile for matching '
+ 'trace_enter trace_leave')
args = parser.parse_args()
@@ -166,5 +175,6 @@ def main():
trace_file = args.tracefile[0]
run(trace_file, from_function, dot_file)
+
if __name__ == '__main__':
main()
diff --git a/tools/devel/review/patch-tokenize.py
b/tools/devel/review/patch-tokenize.py
index 8350517..30a5188 100755
--- a/tools/devel/review/patch-tokenize.py
+++ b/tools/devel/review/patch-tokenize.py
@@ -2,6 +2,7 @@
# -*- OpenSAF -*-
#
# (C) Copyright 2010 The OpenSAF Foundation
+# (C) Copyright Ericsson AB 2015, 2016, 2017. All rights reserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -13,16 +14,19 @@
# licensing terms.
#
# Author(s): Wind River Systems
+# Ericsson AB
#
-
+# pylint: disable=invalid-name
+""" Tokenize alphanumeric words in patch file """
+from __future__ import print_function
import re
import sys
-# Validates only on lines that are patch addition (e.g. + foo)
-pattern = re.compile("\+\s.*")
+# Validate only on lines that are patch additions (e.g. + foo)
+pattern = re.compile(r"\+\s.*")
m = pattern.match(sys.argv[1])
if m:
- # Tokenize all alphanumeric words for banned word lookup
- for word in re.findall("\s*(\w+).?\(", m.group(0)):
- print word
+ # Tokenize all alphanumeric words for banned word lookup
+ for word in re.findall(r"\s*(\w+).?\(", m.group(0)):
+ print (word)