Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/+add-pulp-exceptions.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add more Pulp Exceptions.
90 changes: 90 additions & 0 deletions pulp_gem/app/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from gettext import gettext as _

from pulpcore.plugin.exceptions import PulpException


class RemoteURLRequiredError(PulpException):
"""
Raised when a sync is attempted without a URL on the remote.
"""

error_code = "GEM0001"

def __str__(self):
return f"[{self.error_code}] " + _("A remote must have a url specified to synchronize.")


class RemoteConnectionError(PulpException):
"""
Raised when a connection to the remote host fails.
"""

error_code = "GEM0002"

def __init__(self, host):
self.host = host

def __str__(self):
return f"[{self.error_code}] " + _("Could not connect to host {host}").format(
host=self.host
)


class InvalidGemNameError(PulpException):
"""
Raised when a gem name does not match the expected format.
"""

error_code = "GEM0003"

def __init__(self, name):
self.name = name

def __str__(self):
return f"[{self.error_code}] " + _("Invalid gem name: {name}").format(name=self.name)


class InvalidRequirementError(PulpException):
"""
Raised when a gem info file contains an unrecognized requirement key.
"""

error_code = "GEM0004"

def __init__(self, stmt):
self.stmt = stmt

def __str__(self):
return f"[{self.error_code}] " + _("Invalid requirement: {stmt}").format(stmt=self.stmt)


class InvalidVersionStringError(PulpException):
"""
Raised when a gem version string does not match the expected format.
"""

error_code = "GEM0005"

def __init__(self, version):
self.version = version

def __str__(self):
return f"[{self.error_code}] " + _("Invalid version string: {version}").format(
version=self.version
)


class UnknownRubyClassError(PulpException):
"""
Raised when YAML parsing encounters an unknown Ruby class.
"""

error_code = "GEM0006"

def __init__(self, suffix):
self.suffix = suffix

def __str__(self):
return f"[{self.error_code}] " + _("Unknown ruby class {suffix}.").format(
suffix=self.suffix
)
5 changes: 3 additions & 2 deletions pulp_gem/app/tasks/synchronizing.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
Stage,
)

from pulp_gem.app.exceptions import RemoteConnectionError, RemoteURLRequiredError
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two look rather generic. Can they live in pulpcore.plugin?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably ok to do that later...

from pulp_gem.app.models import GemContent, GemRemote
from pulp_gem.specs import (
NAME_REGEX,
Expand Down Expand Up @@ -44,7 +45,7 @@ def synchronize(remote_pk, repository_pk, mirror=False):
repository = Repository.objects.get(pk=repository_pk)

if not remote.url:
raise ValueError(_("A remote must have a url specified to synchronize."))
raise RemoteURLRequiredError()

first_stage = GemFirstStage(remote)
dv = DeclarativeVersion(first_stage, repository, mirror=mirror)
Expand Down Expand Up @@ -87,7 +88,7 @@ async def run(self):
try:
versions_result = await versions_downloader.run()
except ClientConnectionError as e:
raise Exception(f"Could not connect to host {e.host}")
raise RemoteConnectionError(host=e.host)
await pr_download_versions.aincrement()

async with ProgressReport(message="Parsing versions list") as pr_parse_versions:
Expand Down
17 changes: 12 additions & 5 deletions pulp_gem/specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
import rubymarshal.writer
import rubymarshal.reader

from pulp_gem.app.exceptions import (
InvalidGemNameError,
InvalidRequirementError,
InvalidVersionStringError,
UnknownRubyClassError,
)

log = getLogger(__name__)

NAME_REGEX = re.compile(r"[\w\.-]+")
Expand Down Expand Up @@ -118,7 +125,7 @@ async def read_versions(relative_path):
for name, (ext_versions, md5_sum) in results.items():
# Sanitize name
if not NAME_REGEX.fullmatch(name):
raise ValueError(f"Invalid gem name: {name}")
raise InvalidGemNameError(name=name)
yield name, ext_versions, md5_sum


Expand Down Expand Up @@ -159,7 +166,7 @@ async def read_info(relative_path, versions_info):
elif key == "rubygems":
gem_info["required_rubygems_version"] = value
else:
raise ValueError(f"Invalid requirement: {stmt}")
raise InvalidRequirementError(stmt=stmt)
yield gem_info


Expand Down Expand Up @@ -348,7 +355,7 @@ def _yaml_ruby_constructor(loader, suffix, node):
try:
return rubymarshal.classes.registry[suffix].yaml_constructor(loader, node)
except KeyError:
raise NotImplementedError(f"Unknown ruby class {suffix}.")
raise UnknownRubyClassError(suffix=suffix)


yaml.add_multi_constructor("!ruby/object:", _yaml_ruby_constructor, Loader=RubyMarshalYamlLoader)
Expand Down Expand Up @@ -380,14 +387,14 @@ def analyse_gem(file_obj):
}
# Sanitize name
if not NAME_REGEX.fullmatch(gem_info["name"]):
raise ValueError(f"Invalid gem name: {gem_info['name']}")
raise InvalidGemNameError(name=gem_info["name"])
# Sanitize version
if VERSION_REGEX.fullmatch(gem_info["version"]):
gem_info["prerelease"] = False
elif PRERELEASE_VERSION_REGEX.fullmatch(gem_info["version"]):
gem_info["prerelease"] = True
else:
raise ValueError(f"Invalid version string: {gem_info['version']}")
raise InvalidVersionStringError(version=gem_info["version"])
for key in ("required_ruby_version", "required_rubygems_version"):
if (requirement := data._private_data.get(key)) is not None:
gem_info[key] = requirement.to_s()
Expand Down
Loading