Source code for swimlane.exceptions

"""Custom exceptions and errors"""

from difflib import get_close_matches

from requests import HTTPError


[docs]class SwimlaneException(Exception): """Base exception for Swimlane errors"""
[docs]class UnknownField(SwimlaneException, KeyError): """Raised anytime access is attempted to a field that does not exist on an App or Record Attributes: app (App): App with the unknown field requested field_name (str): Name of the field that was requested similar_field_names (list(str)): List of strings of fields on app that are potentially similar to field_name """ def __init__(self, app, field_name, field_pool): self.app = app self.field_name = field_name self.similar_field_names = get_close_matches(self.field_name, field_pool, 3) message = "{!r} has no field '{}'".format(self.app, self.field_name) if self.similar_field_names: message += '. Similar fields: ' + ', '.join([repr(f) for f in self.similar_field_names]) super(UnknownField, self).__init__(message)
[docs]class ValidationError(SwimlaneException, ValueError): """Raised when record's field data is invalid Attributes: record (Record): Record in context of validation failure failure (str): Reason for record failure """ def __init__(self, record, failure): self.record = record self.failure = failure super(ValidationError, self).__init__( 'Validation failed for {!r}. Reason: {}'.format(self.record, self.failure) )
class _InvalidSwimlaneVersion(SwimlaneException, NotImplementedError): """Base class raised when connecting to unsupported versions of Swimlane Attributes: swimlane (Swimlane): Swimlane client failing the version check min_version (str): Minimum version specified on version range max_version (str): Maximum version specified on version range """ def __init__(self, swimlane, min_version, max_version): self.swimlane = swimlane self.min_version = min_version self.max_version = max_version super(_InvalidSwimlaneVersion, self).__init__(self._get_message()) def _get_range_string(self): if self.min_version and self.max_version: range_string = '>= {}, < {}'.format(self.min_version, self.max_version) elif self.min_version: range_string = '>= {}'.format(self.min_version) else: range_string = '<= {}'.format(self.max_version) return range_string def _get_message(self): return 'Swimlane version {}, must be {}'.format( self.swimlane.version, self._get_range_string() )
[docs]class InvalidSwimlaneBuildVersion(_InvalidSwimlaneVersion): """Raised when method connected to Swimlane with build version outside a required range""" def _get_message(self): return 'Swimlane build version {}, must be {}'.format( self.swimlane.build_version, self._get_range_string() )
[docs]class InvalidSwimlaneProductVersion(_InvalidSwimlaneVersion): """Raised when method connected to Swimlane with product version outside a required range""" def _get_message(self): return 'Swimlane product version {}, must be {}'.format( self.swimlane.product_version, self._get_range_string() )
[docs]class SwimlaneHTTP400Error(SwimlaneException, HTTPError): """Exception raised when receiving a 400 response with additional context Attributes: code (int): Swimlane error code name (str): Human-readable Swimlane error name argument (str): Optional argument included with error or None http_error (HTTPError): Source requests.HTTPError caught and used to generate this exception """ codes = { -1: 'Unknown', 1000: 'PasswordExpired', 1001: 'DuplicateUserName', 1002: 'InvalidUserNameOrPassword', 1003: 'ConfirmPasswordDoesNotMatch', 1004: 'PasswordDoesNotMeetComplexityRequirements', 1005: 'PasswordResetRequired', 1006: 'NewPasswordCannotMatchCurrent', 1007: 'InvalidUser', 1051: 'DuplicateGroupName', 1061: 'DuplicateRoleName', 2000: 'DuplicateFieldName', 2001: 'FieldNameEmpty', 2002: 'InvalidApplicationExportFile', 2003: 'ApplicationNotFound', 2004: 'InvalidCalculation', 2005: 'DuplicateApplicationName', 2006: 'DuplicateAppletName', 2007: 'DuplicateAppletAcronym', 2008: 'DuplicateApplicationAcronym', 2011: 'SectionNameTooLong', 3000: 'DuplicateFieldValue', 3001: 'InvalidDateField', 3002: 'RecordNotFound', 3003: 'FieldNotFound', 3006: 'MaxAttachmentSize', 4000: 'BadStatsGroup', 4001: 'BadFilter', 5000: 'AppLimitExceeded', 5001: 'UserLimitExceeded', 5002: 'NewServerInstall', 5003: 'UnableToConnectToActiveDirectory', 5004: 'UnableToRetrieveStoredValue', 5005: 'UnableToConnectToMongoDb', 5006: 'UnableToConnectToSmtp', 5007: 'SwimlaneAlreadyInitialized', 5008: 'ModelValidationError', 5009: 'UpgradeInProcess', 5010: 'RequiredFieldMissing', 5011: 'UnableToRetrieveEncryptionKey', 5012: 'PathNotFound', 5013: 'WrongType', 5014: 'ModificationError', 5015: 'DatabaseError', 5016: 'NetworkError', 5017: 'InvalidOnThisOS', 6000: 'ConnectionDataNotProvided', 7000: 'RegexNotDefined', 7001: 'AssetNotFound', 9000: 'BadThreatIntelConnector', 9001: 'NoThreatIntel', 9002: 'ThreatIntelTypeNotSupportedByThisProvider', 10000: 'DuplicateTaskName', 10001: 'TaskNotFound', 17001: 'DuplicateAssetName', 19001: 'HangfireError' } def __init__(self, http_error): self.http_error = http_error try: error_content = self.http_error.response.json() except ValueError: error_content = {'Argument': None, 'ErrorCode': '-1'} self.code = int(error_content.get('ErrorCode', -1)) self.argument = error_content.get('Argument') self.name = self.codes.get(self.code, self.codes[-1]) message = '{}:{}'.format(self.name, self.code) if self.argument is not None: message = '{message} ({argument})'.format(message=message, argument=self.argument) super(SwimlaneHTTP400Error, self).__init__( '{message}: Bad Request for url: {url}'.format(message=message, url=self.http_error.response.url) )