Refactor error wrappers in CLI.

Replaced EGroup with BaseGroup which has default error_wrapper method.
Added BaseGroup to all click groups using proxy empty classes.
Added inheritance from SolarError to several custom exception classes.

Change-Id: I4afa2f23ef4486c3a1565c04419f4b8dff21705a
This commit is contained in:
Maciej Kwiek 2016-04-29 14:55:14 +02:00
parent 0a29d63404
commit 71900a69cb
10 changed files with 67 additions and 50 deletions

View File

@ -12,8 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
from functools import wraps
import click
from solar.dblayer.model import DBLayerException
from solar.errors import SolarError
class AliasedGroup(click.Group):
"""This class introduces iproute2-like behaviour,
@ -40,13 +45,27 @@ class AliasedGroup(click.Group):
ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))
class EGroup(click.Group):
class BaseGroup(click.Group):
error_wrapper_enabled = False
error_wrapper = None
def add_command(self, cmd, name=None):
if self.error_wrapper:
cmd.callback = self.error_wrapper(cmd.callback)
return super(EGroup, self).add_command(cmd, name)
cmd.callback = self.error_wrapper(cmd.callback)
return super(BaseGroup, self).add_command(cmd, name)
def error_wrapper(self, f):
@wraps(f)
def _in(*args, **kwargs):
try:
return f(*args, **kwargs)
except (SolarError, DBLayerException) as e:
self.handle_exception(e)
if self.error_wrapper_enabled:
raise click.ClickException(str(e))
raise
except Exception as e:
self.handle_exception(e)
raise
return _in
def handle_exception(self, e):
pass

View File

@ -17,10 +17,15 @@ import subprocess
import click
import networkx as nx
from solar.cli.base import BaseGroup
from solar.events import api as evapi
@click.group()
class EventsGroup(BaseGroup):
pass
@click.group(cls=EventsGroup)
def events():
pass

View File

@ -15,11 +15,16 @@
import click
import yaml
from solar.cli.base import BaseGroup
from solar.core import resource as sresource
from solar.dblayer.model import NONE
@click.group(help="Manages raw resource inputs")
class InputsGroup(BaseGroup):
pass
@click.group(help="Manages raw resource inputs", cls=InputsGroup)
def inputs():
pass

View File

@ -63,7 +63,7 @@ def show_emitter_connections(res):
def main(debug):
debug = debug or os.getenv("SOLAR_CLI_DEBUG")
if not debug:
base.EGroup.error_wrapper_enabled = True
base.BaseGroup.error_wrapper_enabled = True
def init_actions():

View File

@ -18,6 +18,7 @@ import time
import click
from solar.cli.base import BaseGroup
from solar.cli.uids_history import remember_uid
from solar.cli.uids_history import SOLARUID
from solar.dblayer.locking import DBLock
@ -29,7 +30,11 @@ from solar.orchestration.traversal import states
from solar.orchestration import utils
@click.group(name='orch')
class OrchGroup(BaseGroup):
pass
@click.group(name='orch', cls=OrchGroup)
def orchestration():
pass
@ -58,7 +63,7 @@ def wait_report(uid, timeout, interval=3):
except errors.SolarError:
click.echo('')
click_report(uid)
sys.exit(1)
raise
else:
click.echo('')
click_report(uid)

View File

@ -13,32 +13,17 @@
# under the License.
import click
from functools import wraps
import os
import yaml
from solar.cli.base import BaseGroup
from solar.core.resource.repository import Repository
from solar.core.resource.repository import RepositoryException
from solar.cli.base import EGroup
class RepoGroup(EGroup):
def error_wrapper(self, f):
@wraps(f)
def _in(*args, **kwargs):
try:
return f(*args, **kwargs)
except OSError as e:
if self.error_wrapper_enabled:
raise click.ClickException(str(e))
raise
except RepositoryException as e:
if self.error_wrapper_enabled:
raise click.ClickException(str(e))
raise
return _in
class RepoGroup(BaseGroup):
def handle_exception(self, e):
if e is OSError:
raise click.ClickException(str(e))
@click.group(help="Manages Solar repositories", cls=RepoGroup)

View File

@ -16,29 +16,17 @@ import json
import os
import click
from functools import wraps
import yaml
from solar.cli.base import EGroup
from solar.cli.base import BaseGroup
from solar.cli import executors
from solar.core import actions
from solar.core import resource as sresource
from solar.core.resource import composer as cr
from solar import errors
class ResourceGroup(EGroup):
def error_wrapper(self, f):
@wraps(f)
def _in(*args, **kwargs):
try:
return f(*args, **kwargs)
except errors.SolarError as e:
if self.error_wrapper_enabled:
raise click.ClickException(str(e))
raise
return _in
class ResourceGroup(BaseGroup):
pass
@click.group(cls=ResourceGroup)

View File

@ -16,6 +16,7 @@ import sys
import click
from solar.cli.base import BaseGroup
from solar.cli.uids_history import remember_uid
from solar.core import resource
from solar.core import testing
@ -24,7 +25,11 @@ from solar.system_log import change
from solar.system_log import data
@click.group()
class SystemLogGroup(BaseGroup):
pass
@click.group(cls=SystemLogGroup)
def changes():
pass

View File

@ -23,13 +23,14 @@ import semantic_version
import shutil
import yaml
from solar import errors
from solar import utils
RES_TYPE = Enum("Resource Types", 'Normal Composer')
class RepositoryException(Exception):
class RepositoryException(errors.SolarError):
pass

View File

@ -33,7 +33,11 @@ class DBLayerException(Exception):
class DBLayerNotFound(DBLayerException):
pass
def __init__(self, spec):
self.message = 'Object {} not found in db layer'.format(spec)
def __str__(self):
return str(self.message)
class DBLayerNoRiakObj(DBLayerException):