Skip to content

Commit

Permalink
many: use exceptions based on SnapcraftError
Browse files Browse the repository at this point in the history
Signed-off-by: Kyle Fazzari <kyle@canonical.com>
  • Loading branch information
kyrofa authored and sergiusens committed Aug 14, 2017
1 parent 6a15792 commit e68d25a
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 53 deletions.
8 changes: 6 additions & 2 deletions integration_tests/store/test_store_close.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

from testtools.matchers import FileExists

from testtools.matchers import (
Equals,
)

import integration_tests


Expand All @@ -24,7 +28,7 @@ class ChannelClosingTestCase(integration_tests.StoreTestCase):
def test_missing_login(self):
expected = 'run "snapcraft login"'
status = self.close('basic', 'beta', expected=expected)
self.assertEqual(1, status)
self.assertThat(status, Equals(2))

def test_missing_permission(self):
self.addCleanup(self.logout)
Expand All @@ -33,7 +37,7 @@ def test_missing_permission(self):
'Make sure the logged in account has upload permissions on '
"'missing' in series '16'.")
status = self.close('missing', 'beta', expected=expected)
self.assertEqual(1, status)
self.assertThat(status, Equals(2))

def test_close_channel(self):
self.addCleanup(self.logout)
Expand Down
5 changes: 3 additions & 2 deletions integration_tests/store/test_store_sign_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import shutil

from testtools.matchers import (
Equals,
Contains,
FileContains,
FileExists,
Expand Down Expand Up @@ -47,7 +48,7 @@ def test_unsuccessful_sign_build_no_login(self):

status = self.sign_build(
self.snap_path, local=True, expect_success=False)
self.assertEqual(1, status)
self.assertThat(status, Equals(2))
self.assertThat(self.snap_build_path, Not(FileExists()))

def test_successful_sign_build_local(self):
Expand Down Expand Up @@ -77,7 +78,7 @@ def test_unsuccessful_sign_build_push_no_login(self):
self.assertThat(self.snap_path, FileExists())

status = self.sign_build(self.snap_path, expect_success=False)
self.assertEqual(1, status)
self.assertThat(status, Equals(2))
self.assertThat(self.snap_build_path, Not(FileExists()))

def test_successful_sign_build_push(self):
Expand Down
7 changes: 5 additions & 2 deletions integration_tests/test_after.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import os
import subprocess

from testtools.matchers import Contains
from testtools.matchers import (
Equals,
Contains,
)

import integration_tests

Expand Down Expand Up @@ -51,7 +54,7 @@ def test_build_with_circular_dependencies(self):
subprocess.CalledProcessError,
self.run_snapcraft, 'build')

self.assertEqual(1, exception.returncode)
self.assertThat(exception.returncode, Equals(2))
expected = (
'Issue detected while analyzing snapcraft.yaml: '
'circular dependency chain found in parts definition\n')
Expand Down
31 changes: 29 additions & 2 deletions snapcraft/internal/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,14 @@ def exit_code(self):
return 2


class MissingState(Exception):
pass
class MissingStateCleanError(SnapcraftError):
fmt = (
"Failed to clean step {step!r}: Missing necessary state. This won't "
"work until a complete clean has occurred."
)

def __init__(self, step):
super().__init__(step=step)


class SnapcraftEnvironmentError(SnapcraftError):
Expand Down Expand Up @@ -77,6 +83,27 @@ def __str__(self):
return super().__str__()


class InvalidAppCommandError(SnapcraftError):

fmt = (
'The specified command {command!r} defined in the app {app!r} does '
'not exist or is not executable'
)

def __init__(self, command, app):
super().__init__(command=command, app=app)


class InvalidDesktopFileError(SnapcraftError):

fmt = (
'Invalid desktop file {filename!r}: {message}'
)

def __init__(self, filename, message):
super().__init__(filename=filename, message=message)


class SnapcraftPartMissingError(SnapcraftError):

fmt = (
Expand Down
2 changes: 1 addition & 1 deletion snapcraft/internal/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
my-part:
# See 'snapcraft plugins'
plugin: nil
""" # noqa, lines too long.
""" # noqa, lines too long.

_STEPS_TO_AUTOMATICALLY_CLEAN_IF_DIRTY = {'stage', 'prime'}

Expand Down
32 changes: 14 additions & 18 deletions snapcraft/internal/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@

from snapcraft import file_utils
from snapcraft import shell_utils
from snapcraft.internal import common
from snapcraft.internal.errors import (
MissingGadgetError,
SnapcraftPathEntryError)
from snapcraft.internal import (
common,
errors
)
from snapcraft.internal.deprecations import handle_deprecation_notice
from snapcraft.internal.sources import get_source_handler_from_type
from snapcraft.internal.states import (
Expand Down Expand Up @@ -132,7 +132,7 @@ def setup_assets(self):

if self._config_data.get('type', '') == 'gadget':
if not os.path.exists('gadget.yaml'):
raise MissingGadgetError()
raise errors.MissingGadgetError()
file_utils.link_or_copy(
'gadget.yaml', os.path.join(self.meta_dir, 'gadget.yaml'))

Expand Down Expand Up @@ -388,9 +388,7 @@ def _wrap_app(self, name, app):
try:
app[k] = self._wrap_exe(app[k], '{}-{}'.format(k, name))
except CommandError as e:
raise EnvironmentError(
'The specified command {!r} defined in the app {!r} '
'does not exist or is not executable'.format(str(e), name))
raise errors.InvalidAppCommandError(str(e), name)
desktop_file_name = app.pop('desktop', '')
if desktop_file_name:
desktop_file = _DesktopFile(
Expand All @@ -409,23 +407,21 @@ def __init__(self, *, name, filename, snap_name, prime_dir):
self._prime_dir = prime_dir
self._path = os.path.join(prime_dir, filename)
if not os.path.exists(self._path):
raise EnvironmentError(
'The specified desktop file {!r} defined in the app '
'{!r} does not exist'.format(filename, name))
raise errors.InvalidDesktopFileError(
filename, 'does not exist (defined in the app {!r})'.format(
name))

def parse_and_reformat(self):
self._parser = configparser.ConfigParser(interpolation=None)
self._parser.optionxform = str
self._parser.read(self._path, encoding='utf-8')
section = 'Desktop Entry'
if section not in self._parser.sections():
raise EnvironmentError(
'The specified desktop file {!r} is not a valid '
'desktop file'.format(self._filename))
raise errors.InvalidDesktopFileError(
self._filename, "missing 'Desktop Entry' section")
if 'Exec' not in self._parser[section]:
raise EnvironmentError(
'The specified desktop file {!r} is missing the '
'"Exec" key'.format(self._filename))
raise errors.InvalidDesktopFileError(
self._filename, "missing 'Exec' key")
# XXX: do we want to allow more parameters for Exec?
if self._name == self._snap_name:
exec_value = '{} %U'.format(self._name)
Expand Down Expand Up @@ -478,5 +474,5 @@ def _verify_app_paths(basedir, apps):
for path_entry in path_entries:
file_path = os.path.join(basedir, apps[app][path_entry])
if not os.path.exists(file_path):
raise SnapcraftPathEntryError(
raise errors.SnapcraftPathEntryError(
app=app, key=path_entry, value=file_path)
14 changes: 5 additions & 9 deletions snapcraft/internal/pluginhandler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,9 +494,7 @@ def clean_stage(self, project_staged_state, hint=''):
self._clean_shared_area(self.stagedir, state,
project_staged_state)
except AttributeError:
raise errors.MissingState(
"Failed to clean step 'stage': Missing necessary state. "
"This won't work until a complete clean has occurred.")
raise errors.MissingStateCleanError('stage')

self.mark_cleaned('stage')

Expand Down Expand Up @@ -554,9 +552,7 @@ def clean_prime(self, project_primed_state, hint=''):
self._clean_shared_area(self.primedir, state,
project_primed_state)
except AttributeError:
raise errors.MissingState(
"Failed to clean step 'prime': Missing necessary state. "
"This won't work until a complete clean has occurred.")
raise errors.MissingStateCleanError('prime')

self.mark_cleaned('prime')

Expand Down Expand Up @@ -602,7 +598,7 @@ def clean(self, project_staged_state=None, project_primed_state=None,
try:
self._clean_steps(project_staged_state, project_primed_state,
step, hint)
except errors.MissingState:
except errors.MissingStateCleanError:
# If one of the step cleaning rules is missing state, it must be
# running on the output of an old Snapcraft. In that case, if we
# were specifically asked to clean that step we need to fail.
Expand Down Expand Up @@ -923,7 +919,7 @@ def _organize_filesets(fileset, base_dir):
# deletions.
shutil.rmtree(src)
elif os.path.isfile(dst):
raise EnvironmentError(
raise errors.SnapcraftEnvironmentError(
'Trying to organize file {key!r} to {dst!r}, '
'but {dst!r} already exists'.format(
key=key, dst=os.path.relpath(dst, base_dir)))
Expand Down Expand Up @@ -1073,7 +1069,7 @@ def _file_collides(file_this, file_other):


def check_for_collisions(parts):
"""Raises an EnvironmentError if conflicts are found between two parts."""
"""Raises a SnapcraftPartConflictError if conflicts are found."""
parts_files = {}
for part in parts:
# Gather our own files up
Expand Down
2 changes: 1 addition & 1 deletion snapcraft/internal/project_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ def _build_env(root, snap_name, confinement, arch_triplet,

if confinement == 'classic':
if not core_dynamic_linker:
raise EnvironmentError(
raise errors.SnapcraftEnvironmentError(
'classic confinement requires the core snap to be installed. '
'Install it by running `snap install core`.')

Expand Down
8 changes: 6 additions & 2 deletions snapcraft/storeapi/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,12 @@ def __init__(self, response, snap_id, series, arch):
series=series or 'any', error=error)


class StoreDeltaApplicationError(Exception):
pass
class StoreDeltaApplicationError(StoreError):

fmt = '{message}'

def __init__(self, message):
super().__init__(message=message)


class StoreSnapStatusError(StoreSnapRevisionsError):
Expand Down
12 changes: 6 additions & 6 deletions snapcraft/tests/pluginhandler/test_pluginhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ class OrganizeTestCase(tests.TestCase):
setup_dirs=[],
setup_files=['foo', 'bar'],
organize_set={'foo': 'bar'},
expected=EnvironmentError,
expected=errors.SnapcraftEnvironmentError,
)),
('*_for_files', dict(
setup_dirs=[],
Expand All @@ -735,7 +735,7 @@ class OrganizeTestCase(tests.TestCase):
setup_dirs=[],
setup_files=['foo.conf', 'bar.conf'],
organize_set={'*.conf': 'dir'},
expected=EnvironmentError,
expected=errors.SnapcraftEnvironmentError,
)),
('*_for_directories', dict(
setup_dirs=['dir1', 'dir2'],
Expand Down Expand Up @@ -1218,7 +1218,7 @@ def test_clean_stage_state_common_files(self):
def test_clean_stage_old_state(self):
self.handler.mark_done('stage', None)
raised = self.assertRaises(
errors.MissingState,
errors.MissingStateCleanError,
self.handler.clean_stage, {})

self.assertEqual(
Expand Down Expand Up @@ -1549,7 +1549,7 @@ def test_clean_prime_state_common_files(self):
def test_clean_prime_old_state(self):
self.handler.mark_done('prime', None)
raised = self.assertRaises(
errors.MissingState,
errors.MissingStateCleanError,
self.handler.clean_prime, {})

self.assertEqual(
Expand Down Expand Up @@ -1905,7 +1905,7 @@ def test_clean_prime_old_prime_state(self):
handler.mark_done('prime', None)

raised = self.assertRaises(
errors.MissingState,
errors.MissingStateCleanError,
handler.clean, step='prime')

self.assertEqual(
Expand Down Expand Up @@ -2019,7 +2019,7 @@ def test_clean_stage_old_stage_state(self):
handler.mark_done('stage', None)

raised = self.assertRaises(
errors.MissingState,
errors.MissingStateCleanError,
handler.clean, step='stage')

self.assertEqual(
Expand Down
14 changes: 6 additions & 8 deletions snapcraft/tests/test_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@
_SnapPackaging
)
from snapcraft.internal import common
from snapcraft.internal.errors import (
MissingGadgetError,
SnapcraftPathEntryError,
)
from snapcraft.internal import errors
from snapcraft import ProjectOptions, tests


Expand Down Expand Up @@ -136,7 +133,7 @@ def test_create_gadget_meta_with_missing_gadget_yaml_raises_error(self):
self.config_data['type'] = 'gadget'

self.assertRaises(
MissingGadgetError,
errors.MissingGadgetError,
create_snap_packaging,
self.config_data,
self.project_options,
Expand Down Expand Up @@ -562,7 +559,8 @@ class EnsureFilePathsTestCaseFails(CreateBaseTestCase):
def test_file_path_entry(self):
self.config_data['apps'] = {'app': {self.key: self.filepath}}

self.assertRaises(SnapcraftPathEntryError, self.generate_meta_yaml)
self.assertRaises(
errors.SnapcraftPathEntryError, self.generate_meta_yaml)


class CreateWithGradeTestCase(CreateBaseTestCase):
Expand Down Expand Up @@ -733,7 +731,7 @@ def test_command_does_not_exist(self):
apps = {'app1': {'command': 'command-does-not-exist'}}

raised = self.assertRaises(
EnvironmentError,
errors.InvalidAppCommandError,
self.packager._wrap_apps, apps)
self.assertEqual(
"The specified command 'command-does-not-exist' defined in the "
Expand All @@ -749,7 +747,7 @@ def test_command_is_not_executable(self):
_create_file(cmd_path)

raised = self.assertRaises(
EnvironmentError,
errors.InvalidAppCommandError,
self.packager._wrap_apps, apps)
self.assertEqual(
"The specified command 'command-not-executable' defined in the "
Expand Down

0 comments on commit e68d25a

Please sign in to comment.