parser: Improve exception handling
Multiple improvements for exception handling and raising the correct exceptions. The following changes make the output nicer for readability although, it still has some bits missing. - Renaming exceptions.py to parsererr.py due to H237. - Changing the custom exception prefix from Exception to Error. - Parser deliberately raises custom exceptions pointing out the error. - Changes to custom exception classes to match the error type better. - Printing the rst_file name with a nicer error output. - Exact location in the rst file needs find or grep method as the location (LOC) is not yet provided. - Errors are still easy to trace with find or grep. Change-Id: I008563d7caaf4d059b30d7b687faf823b2e6a913
This commit is contained in:
parent
c6d99ea667
commit
d23f101054
|
@ -1,41 +0,0 @@
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
|
|
||||||
class Rst2BashException(Exception):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MissingTagsException(Rst2BashException):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class NestedDistroBlocksException(Rst2BashException):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class PathNotFoundException(Rst2BashException):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class NoCodeBlocksException(Rst2BashException):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidOperatorException(Rst2BashException):
|
|
||||||
|
|
||||||
pass
|
|
|
@ -17,6 +17,9 @@ import re
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
import parsererr as ParserErr
|
||||||
|
|
||||||
|
|
||||||
class BlockIndex(object):
|
class BlockIndex(object):
|
||||||
"""Creates indices which describes the location of blocks in rst file.
|
"""Creates indices which describes the location of blocks in rst file.
|
||||||
|
|
||||||
|
@ -228,7 +231,8 @@ class ParseBlocks(object):
|
||||||
action = 'config'
|
action = 'config'
|
||||||
codeBlock = self._parse_config(codeBlock)
|
codeBlock = self._parse_config(codeBlock)
|
||||||
else:
|
else:
|
||||||
raise # TODO(dbite): Raise custom exception here.
|
msg = "Invalid command type: %s" % cmdType
|
||||||
|
raise ParserErr.InvalidCodeBlockError(msg)
|
||||||
|
|
||||||
command.append(action=action, command=codeBlock)
|
command.append(action=action, command=codeBlock)
|
||||||
|
|
||||||
|
@ -289,7 +293,8 @@ class ParseBlocks(object):
|
||||||
elif ">" in operator:
|
elif ">" in operator:
|
||||||
operator = "mysql_exec "
|
operator = "mysql_exec "
|
||||||
else:
|
else:
|
||||||
raise # TODO(dbite): Create custom exceptions!
|
msg = "Invalid operator: %s" % operator
|
||||||
|
raise ParserErr.InvalidOperatorError(msg)
|
||||||
|
|
||||||
return operator
|
return operator
|
||||||
|
|
||||||
|
@ -408,7 +413,10 @@ class ExtractBlocks(object):
|
||||||
self.allBlocksIterator = \
|
self.allBlocksIterator = \
|
||||||
self.blocks['allBlock'].get_startindex_generator()
|
self.blocks['allBlock'].get_startindex_generator()
|
||||||
|
|
||||||
self._extractblocks()
|
try:
|
||||||
|
self._extractblocks()
|
||||||
|
except IndexError as err:
|
||||||
|
raise ParserErr.MissingTagsError(err)
|
||||||
|
|
||||||
# Helper function for quick lookup from the blocks lookup table.
|
# Helper function for quick lookup from the blocks lookup table.
|
||||||
def _block_lookup(self, allblock):
|
def _block_lookup(self, allblock):
|
||||||
|
@ -423,8 +431,8 @@ class ExtractBlocks(object):
|
||||||
if blockIndex is not False:
|
if blockIndex is not False:
|
||||||
return blockName, blockIndex
|
return blockName, blockIndex
|
||||||
else:
|
else:
|
||||||
# TODO(dbite): Raise custom exception.
|
msg = "Invalid block name: %s" % blockName
|
||||||
raise
|
raise ParserErr.InvalidBlockError(msg)
|
||||||
|
|
||||||
# Helper function for recursive-generator pattern.
|
# Helper function for recursive-generator pattern.
|
||||||
def _extractblocks(self, distro=None, path=None, distroEnd=None):
|
def _extractblocks(self, distro=None, path=None, distroEnd=None):
|
||||||
|
@ -456,6 +464,11 @@ class ExtractBlocks(object):
|
||||||
|
|
||||||
block = self.blocks[blockName]
|
block = self.blocks[blockName]
|
||||||
|
|
||||||
|
# TODO(dbite): Implement a mechanism for locating the exact location in
|
||||||
|
# the rst file at the current recursive depth. This
|
||||||
|
# information should then be logged and passed via. the
|
||||||
|
# exception traceback. Save required vars. in a global
|
||||||
|
# variable.
|
||||||
if distroEnd < block.get_start_block(blockIndex)[0]:
|
if distroEnd < block.get_start_block(blockIndex)[0]:
|
||||||
distro = None
|
distro = None
|
||||||
|
|
||||||
|
@ -536,14 +549,27 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
for rst_file in rst_files:
|
for rst_file in rst_files:
|
||||||
|
|
||||||
rst_file_path = os.path.join(rst_path, rst_file)
|
parser_message = "\nError: XXX: Failed to parse %s to bash.\n\t - "
|
||||||
print("Parsing: %s\n") % (rst_file)
|
|
||||||
code_blocks = ExtractBlocks(rst_file_path, bash_path)
|
|
||||||
code_blocks.get_indice_blocks()
|
|
||||||
try:
|
try:
|
||||||
|
rst_file_path = os.path.join(rst_path, rst_file)
|
||||||
|
code_blocks = ExtractBlocks(rst_file_path, bash_path)
|
||||||
|
code_blocks.get_indice_blocks()
|
||||||
code_blocks.extract_codeblocks()
|
code_blocks.extract_codeblocks()
|
||||||
except Exception:
|
bashCode = code_blocks.get_bash_code()
|
||||||
|
|
||||||
|
if not code_blocks.write_bash_code():
|
||||||
|
msg = "Could not write to bash: %s" % rst_file_path
|
||||||
|
raise ParserErr.Rst2BashError(msg)
|
||||||
|
|
||||||
|
except (ParserErr.InvalidCodeBlockError,
|
||||||
|
ParserErr.InvalidOperatorError,
|
||||||
|
ParserErr.InvalidBlockError,
|
||||||
|
ParserErr.MissingTagsError) as ex:
|
||||||
|
parser_message = parser_message + repr(ex) + "\n"
|
||||||
|
except ParserErr.Rst2BashError as ex:
|
||||||
pass
|
pass
|
||||||
bashCode = code_blocks.get_bash_code()
|
else:
|
||||||
if not code_blocks.write_bash_code():
|
parser_message = "Success :): parsed %s to bash. :D"
|
||||||
raise Exception("Could not write to bash")
|
finally:
|
||||||
|
print(parser_message % rst_file)
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
|
class Rst2BashError(Exception):
|
||||||
|
"""Base class for exceptions for Rst2Bash module."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidBlockError(Rst2BashError):
|
||||||
|
"""Error describing possible sphinx blocks but invalid for rst2bash."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MissingTagsError(Rst2BashError):
|
||||||
|
"""Error describing missing tags, especially rst2bash specific end tags."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NestedDistroBlocksError(Rst2BashError):
|
||||||
|
"""Error describing nested distribution blocks."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
Rst2BashError.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class PathNotFoundError(Rst2BashError):
|
||||||
|
"""Error describing missing path for certain commands (ex: config)."""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
Rst2BashError.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidCodeBlockError(Rst2BashError):
|
||||||
|
"""Error describing unspported code blocks for rst2bash."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidOperatorError(Rst2BashError):
|
||||||
|
"""Error describing bash/db operators which are not supported."""
|
||||||
|
|
||||||
|
pass
|
Loading…
Reference in New Issue