Skip to content

Commit

Permalink
Merge pull request #115 from paulsengroup/feat/better-errors
Browse files Browse the repository at this point in the history
Improve error message generated when invalid params are passed to hictkpy.File()
  • Loading branch information
robomics authored Nov 10, 2024
2 parents d222d37 + 9e8dcf6 commit d1bfb66
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 3 deletions.
31 changes: 28 additions & 3 deletions src/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,34 @@ namespace hictkpy::file {
static void ctor(hictk::File *fp, const std::filesystem::path &path,
std::optional<std::int32_t> resolution, std::string_view matrix_type,
std::string_view matrix_unit) {
new (fp) hictk::File{path.string(), static_cast<std::uint32_t>(resolution.value_or(0)),
hictk::hic::ParseMatrixTypeStr(std::string{matrix_type}),
hictk::hic::ParseUnitStr(std::string{matrix_unit})};
const auto resolution_ = static_cast<std::uint32_t>(resolution.value_or(0));
try {
new (fp) hictk::File{path.string(), resolution_,
hictk::hic::ParseMatrixTypeStr(std::string{matrix_type}),
hictk::hic::ParseUnitStr(std::string{matrix_unit})};
// TODO all the exceptions should ideally be handled on the hictk side
// but this will have to do until the next release of hictk
} catch (const HighFive::Exception &e) {
std::string_view msg{e.what()};
if (msg.find("Unable to open the group \"/resolutions/0\"") != std::string_view::npos) {
throw std::runtime_error(
"resolution is required and cannot be None when opening .mcool files");
}
throw;
} catch (const std::runtime_error &e) {
std::string_view msg{e.what()};
if (msg.find("resolution cannot be 0 when opening .hic files") != std::string_view::npos) {
throw std::runtime_error("resolution is required and cannot be None when opening .hic files");
}
throw;
}

if (resolution.has_value() && fp->resolution() != resolution_) {
// TODO this should also be handled by hictk
throw std::runtime_error(
fmt::format(FMT_STRING("resolution mismatch for file \"{}\": expected {}, found {}"),
fp->uri(), resolution_, fp->resolution()));
}
}

static std::string repr(const hictk::File &f) {
Expand Down
42 changes: 42 additions & 0 deletions test/test_file_ctors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright (C) 2024 Roberto Rossini <[email protected]>
#
# SPDX-License-Identifier: MIT

import pathlib

import pytest

import hictkpy

testdir = pathlib.Path(__file__).resolve().parent

pytestmark = pytest.mark.parametrize(
"file,resolution",
[
(testdir / "data" / "cooler_test_file.mcool", 100_000),
(testdir / "data" / "hic_test_file.hic", 100_000),
],
)


class TestClass:
def test_resolution_mismatch(self, file, resolution):
f = hictkpy.MultiResFile(file)

if not f[resolution].is_cooler():
pytest.skip(f'File "{file}" is not in .mcool format')

assert 1_000_000 in f.resolutions()
with pytest.raises(RuntimeError, match="resolution mismatch"):
hictkpy.File(f"{file}::/resolutions/{resolution}", 1_000_000)

def test_missing_resolution_param(self, file, resolution):
f = hictkpy.MultiResFile(file)

if f[resolution].is_cooler():
ext = ".mcool"
else:
ext = ".hic"

with pytest.raises(RuntimeError, match=f"resolution is required and cannot be None when opening {ext} files"):
hictkpy.File(file)

0 comments on commit d1bfb66

Please sign in to comment.