From 43b6d78d00953fa99494f12462d10470ce892920 Mon Sep 17 00:00:00 2001 From: "Ian H. Pittwood" Date: Mon, 24 Jun 2019 17:27:56 -0500 Subject: [PATCH] Combines all exceptions into a single file Spyglass has three different files that define exceptions. This change merges all of those definitions into a single file for simplicity. Before this change can be merged, spyglass-plugin-xls needs to move the exceptions needed for its functions. Related Change: https://review.opendev.org/#/c/667243/ Depends-On: I81c5ca2d9083aece3641bc8b5405dfd44baec810 Change-Id: Ibf34771653247850903e529beb17dbd60ba35fbf --- spyglass/cli.py | 6 +- spyglass/data_extractor/custom_exceptions.py | 65 ------------------- spyglass/data_extractor/models.py | 5 +- .../plugins/tugboat/check_exceptions.py | 0 spyglass/exceptions.py | 52 ++++++++++++++- spyglass/validators/exceptions.py | 32 --------- spyglass/validators/json_validator.py | 30 ++++----- tests/unit/data_extractor/test_models.py | 2 +- tests/unit/validators/test_json_validator.py | 2 +- 9 files changed, 74 insertions(+), 120 deletions(-) delete mode 100644 spyglass/data_extractor/custom_exceptions.py delete mode 100644 spyglass/data_extractor/plugins/tugboat/check_exceptions.py delete mode 100644 spyglass/validators/exceptions.py diff --git a/spyglass/cli.py b/spyglass/cli.py index e659463..c5d53d3 100644 --- a/spyglass/cli.py +++ b/spyglass/cli.py @@ -81,11 +81,13 @@ def intermediary_processor(plugin_type, **kwargs): # Load the plugin class LOG.info("Load the plugin class") + entry_point = "data_extractor_plugins" try: plugin_class = pkg_resources.load_entry_point( - "spyglass", "data_extractor_plugins", plugin_type) + "spyglass", entry_point, plugin_type) except ImportError: - raise exceptions.UnsupportedPlugin() + raise exceptions.UnsupportedPlugin( + plugin_name=plugin_type, entry_point=entry_point) # Extract data from plugin data source LOG.info("Extract data from plugin data source") diff --git a/spyglass/data_extractor/custom_exceptions.py b/spyglass/data_extractor/custom_exceptions.py deleted file mode 100644 index 5ec1304..0000000 --- a/spyglass/data_extractor/custom_exceptions.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2018 AT&T Intellectual Property. All other rights reserved. -# -# 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. - -import logging -import sys - -LOG = logging.getLogger(__name__) - - -class BaseError(Exception): - - def __init__(self, msg): - self.msg = msg - - def display_error(self): - LOG.info(self.msg) - sys.exit(1) - - -class NoSpecMatched(BaseError): - - def __init__(self, excel_specs): - self.specs = excel_specs - - def display_error(self): - # FIXME (Ian Pittwood): use log instead of print - print( - "No spec matched. Following are the available specs:\n".format( - self.specs)) - sys.exit(1) - - -class MissingAttributeError(BaseError): - pass - - -class MissingValueError(BaseError): - pass - - -class ApiClientError(BaseError): - pass - - -class TokenGenerationError(BaseError): - pass - - -class FormationConnectionError(BaseError): - pass - - -class InvalidIntermediary(BaseError): - pass diff --git a/spyglass/data_extractor/models.py b/spyglass/data_extractor/models.py index ef122e3..0e90779 100644 --- a/spyglass/data_extractor/models.py +++ b/spyglass/data_extractor/models.py @@ -16,7 +16,7 @@ from copy import deepcopy import ipaddress import logging -from spyglass.data_extractor.custom_exceptions import InvalidIntermediary +from spyglass.exceptions import InvalidIntermediary DATA_DEFAULT = "#CHANGE_ME" @@ -629,8 +629,7 @@ class SiteDocumentData(object): def _validate_key_in_intermediary_dict(key: str, dictionary: dict): if key not in dictionary: - raise InvalidIntermediary( - '%s is not defined in the given intermediary file.' % key) + raise InvalidIntermediary(key=key) def site_document_data_factory(intermediary_dict: dict) -> SiteDocumentData: diff --git a/spyglass/data_extractor/plugins/tugboat/check_exceptions.py b/spyglass/data_extractor/plugins/tugboat/check_exceptions.py deleted file mode 100644 index e69de29..0000000 diff --git a/spyglass/exceptions.py b/spyglass/exceptions.py index ab0a855..9a87a8c 100644 --- a/spyglass/exceptions.py +++ b/spyglass/exceptions.py @@ -32,7 +32,57 @@ class SpyglassBaseException(Exception): class UnsupportedPlugin(SpyglassBaseException): - """Exception that occurs when a plugin is called that does not exist""" + """Exception that occurs when a plugin is called that does not exist + + :param plugin_name: name of the specified plugin + :param entry_point: the package used to access plugin_name + """ message = ( '%(plugin_name) was not found in the package %(entry_point) ' 'entry points.') + + +# Data Extractor exceptions + + +class InvalidIntermediary(SpyglassBaseException): + """Exception that occurs when data is missing from the intermediary file + + :param key: dictionary key that Spyglass attempted to access + """ + message = '%(key) is not defined in the given intermediary file.' + + +# Validator exceptions + + +class PathDoesNotExistError(SpyglassBaseException): + """Exception that occurs when the document or schema path does not exist + + :param file_type: type of the files being accessed, documents or schemas + :param path: nonexistent path attempted to access + """ + message = '%(file_type) path: %(path) does not exist.' + + +class UnexpectedFileType(SpyglassBaseException): + """Exception that occurs when an unexpected file type is given + + :param found_ext: the extension of the file given + :param expected_ext: the extension that was expected for the file + """ + message = ( + 'Unexpected file type %(found_ext), ' + 'expected type %(expected_ext)') + + +class DirectoryEmptyError(SpyglassBaseException): + """Exception for when a directory is empty + + This exception can occur when either a directory is empty or if a directory + does not have any files with the correct file extension. + + :param ext: file extension being searched for + :param path: path being searched for files of the specified extension + """ + message = 'No files with %(ext) extension found in document path %(path)' diff --git a/spyglass/validators/exceptions.py b/spyglass/validators/exceptions.py deleted file mode 100644 index 9a69293..0000000 --- a/spyglass/validators/exceptions.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2019 AT&T Intellectual Property. All other rights reserved. -# -# 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 PathDoesNotExistError(OSError): - """Exception that occurs when the document or schema path does not exist""" - pass - - -class UnexpectedFileType(OSError): - """Exception that occurs when an unexpected file type is given""" - pass - - -class DirectoryEmptyError(OSError): - """Exception for when a directory is empty - - This exception can occur when either a directory is empty or if a directory - does not have any files with the correct file extension. - """ - pass diff --git a/spyglass/validators/json_validator.py b/spyglass/validators/json_validator.py index 592221b..48561ff 100644 --- a/spyglass/validators/json_validator.py +++ b/spyglass/validators/json_validator.py @@ -19,7 +19,7 @@ import os from jsonschema import Draft7Validator import yaml -from spyglass.validators import exceptions +from spyglass import exceptions from spyglass.validators.validator import BaseDocumentValidator LOG = logging.getLogger(__name__) @@ -43,11 +43,11 @@ class JSONSchemaValidator(BaseDocumentValidator): # Check that given paths are valid if not os.path.exists(document_path): - LOG.error('Document path: %s does not exist.', document_path) - raise exceptions.PathDoesNotExistError() + raise exceptions.PathDoesNotExistError( + file_type='Document', path=document_path) if not os.path.exists(schema_path): - LOG.error('Schema path: %s does not exist.', document_path) - raise exceptions.PathDoesNotExistError() + raise exceptions.PathDoesNotExistError( + file_type='Schema', path=schema_path) # Extract list of document file paths from path if os.path.isdir(document_path): @@ -57,17 +57,17 @@ class JSONSchemaValidator(BaseDocumentValidator): # Directory should not be empty if not self.documents: - LOG.error( - 'No files with %s extension found in document path ' - '%s', document_extension, document_path) - raise exceptions.DirectoryEmptyError() + raise exceptions.DirectoryEmptyError( + ext=document_extension, path=document_path) elif os.path.splitext(document_path) == document_extension: # Single files can just be appended to the list to process the same # so long as the extension matches self.documents.append(document_path) else: # Throw error if unexpected file type given - raise exceptions.UnexpectedFileType() + raise exceptions.UnexpectedFileType( + found_ext=os.path.splitext(document_path), + expected_ext=document_extension) # Extract list of schema file paths from path if os.path.isdir(schema_path): @@ -77,16 +77,16 @@ class JSONSchemaValidator(BaseDocumentValidator): # Directory should not be empty if not self.schemas: - LOG.error( - 'No files with %s extension found in document path ' - '%s', document_extension, document_path) - raise exceptions.DirectoryEmptyError() + raise exceptions.DirectoryEmptyError( + ext=schema_extension, path=schema_path) elif os.path.splitext(schema_path) == schema_extension: # Single files can just be appended to the list to process the same self.schemas.append(schema_path) else: # Throw error if unexpected file type given - raise exceptions.UnexpectedFileType() + raise exceptions.UnexpectedFileType( + found_ext=os.path.splitext(schema_path), + expected_ext=schema_extension) # Initialize pairs list for next step self.document_schema_pairs = [] diff --git a/tests/unit/data_extractor/test_models.py b/tests/unit/data_extractor/test_models.py index 296698f..49d0f72 100644 --- a/tests/unit/data_extractor/test_models.py +++ b/tests/unit/data_extractor/test_models.py @@ -19,8 +19,8 @@ from unittest import mock import yaml -from spyglass.data_extractor.custom_exceptions import InvalidIntermediary from spyglass.data_extractor import models +from spyglass.exceptions import InvalidIntermediary FIXTURE_DIR = os.path.join( os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'shared') diff --git a/tests/unit/validators/test_json_validator.py b/tests/unit/validators/test_json_validator.py index 9299e80..be056e1 100644 --- a/tests/unit/validators/test_json_validator.py +++ b/tests/unit/validators/test_json_validator.py @@ -16,7 +16,7 @@ import os import pytest -from spyglass.validators.exceptions import PathDoesNotExistError +from spyglass.exceptions import PathDoesNotExistError from spyglass.validators.json_validator import JSONSchemaValidator FIXTURE_DIR = os.path.join(