Skip to content

Commit

Permalink
[cmd:add] Support specific error codes on Add command
Browse files Browse the repository at this point in the history
This commit also adds a new exception that wraps ValueError.

Closes chaoss#19
  • Loading branch information
andygrunwald authored and sduenas committed Nov 10, 2015
1 parent ac6a282 commit 96c3936
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 17 deletions.
8 changes: 4 additions & 4 deletions sortinghat/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from sortinghat.db.model import MIN_PERIOD_DATE, MAX_PERIOD_DATE,\
UniqueIdentity, Identity, Profile, Organization, Domain, Country, Enrollment,\
MatchingBlacklist
from sortinghat.exceptions import AlreadyExistsError, NotFoundError
from sortinghat.exceptions import AlreadyExistsError, NotFoundError, WrappedValueError


def add_unique_identity(db, uuid):
Expand Down Expand Up @@ -110,11 +110,11 @@ def _find_unique_identity(session, uuid):
return uidentity

if source is None:
raise ValueError('source cannot be None')
raise WrappedValueError('source cannot be None')
if source == '':
raise ValueError('source cannot be an empty string')
raise WrappedValueError('source cannot be an empty string')
if not (email or name or username):
raise ValueError('identity data cannot be None or empty')
raise WrappedValueError('identity data cannot be None or empty')

with db.connect() as session:
identity = session.query(Identity).\
Expand Down
10 changes: 5 additions & 5 deletions sortinghat/cmd/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import argparse

from sortinghat import api
from sortinghat.command import Command, CMD_SUCCESS, CMD_FAILURE
from sortinghat.exceptions import AlreadyExistsError, MatcherNotSupportedError, NotFoundError
from sortinghat.command import Command, CMD_SUCCESS
from sortinghat.exceptions import AlreadyExistsError, MatcherNotSupportedError, NotFoundError, WrappedValueError
from sortinghat.matcher import create_identity_matcher
from sortinghat.matching import SORTINGHAT_IDENTITIES_MATCHERS

Expand Down Expand Up @@ -139,7 +139,7 @@ def add(self, source, email=None, name=None, username=None, uuid=None,
matcher = create_identity_matcher(matching, blacklist)
except MatcherNotSupportedError, e:
self.error(str(e))
return CMD_FAILURE
return e.code

try:
new_uuid = api.add_identity(self.db, source, email, name, username, uuid)
Expand All @@ -148,9 +148,9 @@ def add(self, source, email=None, name=None, username=None, uuid=None,

if matcher:
self.__merge_on_matching(uuid, matcher, interactive)
except (AlreadyExistsError, NotFoundError, ValueError), e:
except (AlreadyExistsError, NotFoundError, WrappedValueError), e:
self.error(str(e))
return CMD_FAILURE
return e.code

return CMD_SUCCESS

Expand Down
2 changes: 1 addition & 1 deletion sortinghat/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

import jinja2

from sortinghat.exceptions import DatabaseError
from sortinghat.exceptions import DatabaseError, CODE_VALUE_ERROR
from sortinghat.db.database import Database

CMD_SUCCESS = 0
Expand Down
32 changes: 32 additions & 0 deletions sortinghat/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,26 @@
reload(sys)
sys.setdefaultencoding('utf8')


CODE_BASE_ERROR = 1
CODE_ALREADY_EXISTS_ERROR = 2
CODE_BAD_FILE_FORMAT_ERROR = 3
CODE_DATABASE_ERROR = 4
CODE_INVALID_DATE_ERROR = 5
CODE_INVALID_FORMAT_ERROR = 6
CODE_LOAD_ERROR = 7
CODE_MATCHER_NOT_SUPPORTED_ERROR = 8
CODE_NOT_FOUND_ERROR = 9
CODE_VALUE_ERROR = 10


class BaseError(Exception):
"""Base class error.
Derived classes can overwrite error message declaring 'message' property.
"""
message = 'Unknown error'
code = CODE_BASE_ERROR

def __init__(self, **kwargs):
super(BaseError, self).__init__(kwargs)
Expand All @@ -40,6 +54,9 @@ def __init__(self, **kwargs):
def __str__(self):
return self.msg

def __int__(self):
return self.code

def __unicode__(self):
return unicode(self.msg)

Expand All @@ -48,6 +65,7 @@ class AlreadyExistsError(BaseError):
"""Exception raised when an entity already exists in the registry"""

message = "%(entity)s already exists in the registry"
code = CODE_ALREADY_EXISTS_ERROR

def __init__(self, **kwargs):
self.uuid = kwargs.pop('uuid', None)
Expand All @@ -58,39 +76,53 @@ class BadFileFormatError(BaseError):
"""Exception raised when an input file does not have the expected format"""

message = "%(cause)s"
code = CODE_BAD_FILE_FORMAT_ERROR


class DatabaseError(BaseError):
"""Exception raised when a database error occurs"""

message = "%(error)s (err: %(code)s)"
code = CODE_DATABASE_ERROR


class InvalidDateError(BaseError):
"""Exception raised when a date is invalid"""

message = "%(date)s is not a valid date"
code = CODE_INVALID_DATE_ERROR


class InvalidFormatError(BaseError):
"""Exception raised when a format is invalid"""

message = "%(cause)s"
code = CODE_INVALID_FORMAT_ERROR


class LoadError(BaseError):
"""Exception raised when an error occurs loading data"""

message = "%(cause)s"
code = CODE_LOAD_ERROR


class MatcherNotSupportedError(BaseError):
"""Exception raised when an identity matcher is not supported"""

message = "%(matcher)s identity matcher is not supported"
code = CODE_MATCHER_NOT_SUPPORTED_ERROR


class NotFoundError(BaseError):
"""Exception raised when an entity is not found in the registry"""

message = "%(entity)s not found in the registry"
code = CODE_NOT_FOUND_ERROR


class WrappedValueError(ValueError):
"""Exception WrappedValueError is a normal ValueError with code support"""

code = CODE_VALUE_ERROR

15 changes: 8 additions & 7 deletions tests/test_cmd_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from sortinghat.command import CMD_SUCCESS, CMD_FAILURE
from sortinghat.cmd.add import Add
from sortinghat.db.database import Database
from sortinghat.exceptions import CODE_ALREADY_EXISTS_ERROR, CODE_MATCHER_NOT_SUPPORTED_ERROR, CODE_NOT_FOUND_ERROR, CODE_VALUE_ERROR

from tests.config import DB_USER, DB_PASSWORD, DB_NAME, DB_HOST, DB_PORT

Expand Down Expand Up @@ -180,7 +181,7 @@ def test_non_existing_uuid(self):
"""Check if it fails adding identities to unique identities that do not exist"""

code = self.cmd.add('scm', email='[email protected]', uuid='FFFFFFFFFFFFFFF')
self.assertEqual(code, CMD_FAILURE)
self.assertEqual(code, CODE_NOT_FOUND_ERROR)

output = sys.stderr.getvalue().strip()
self.assertEqual(output, ADD_UUID_NOT_FOUND_ERROR)
Expand All @@ -189,41 +190,41 @@ def test_existing_identity(self):
"""Check if it fails adding an identity that already exists"""

code = self.cmd.add('scm', '[email protected]', 'John Smith', 'jsmith')
self.assertEqual(code, CMD_FAILURE)
self.assertEqual(code, CODE_ALREADY_EXISTS_ERROR)
output = sys.stderr.getvalue().strip()
self.assertEqual(output, ADD_EXISTING_ERROR)

def test_none_or_empty_source(self):
"""Check whether new identities cannot be added when giving a None or empty source"""

code = self.cmd.add(None)
self.assertEqual(code, CMD_FAILURE)
self.assertEqual(code, CODE_VALUE_ERROR)
output = sys.stderr.getvalue().strip().split('\n')[0]
self.assertEqual(output, ADD_SOURCE_NONE_ERROR)

code = self.cmd.add('')
self.assertEqual(code, CMD_FAILURE)
self.assertEqual(code, CODE_VALUE_ERROR)
output = sys.stderr.getvalue().strip().split('\n')[1]
self.assertEqual(output, ADD_SOURCE_EMPTY_ERROR)

def test_none_or_empty_data(self):
"""Check whether new identities cannot be added when identity data is None or empty"""

code = self.cmd.add('scm', None, '', None)
self.assertEqual(code, CMD_FAILURE)
self.assertEqual(code, CODE_VALUE_ERROR)
output = sys.stderr.getvalue().strip().split('\n')[0]
self.assertEqual(output, ADD_IDENTITY_NONE_OR_EMPTY_ERROR)

code = self.cmd.add('scm', '', '', '')
self.assertEqual(code, CMD_FAILURE)
self.assertEqual(code, CODE_VALUE_ERROR)
output = sys.stderr.getvalue().strip().split('\n')[1]
self.assertEqual(output, ADD_IDENTITY_NONE_OR_EMPTY_ERROR)

def test_invalid_matching_method(self):
"""Check if it fails when an invalid matching method is given"""

code = self.cmd.add('scm', '[email protected]', matching='mock')
self.assertEqual(code, CMD_FAILURE)
self.assertEqual(code, CODE_MATCHER_NOT_SUPPORTED_ERROR)
output = sys.stderr.getvalue().strip()
self.assertEqual(output, ADD_MATCHING_ERROR)

Expand Down

0 comments on commit 96c3936

Please sign in to comment.