Skip to content

Commit

Permalink
add tests for load_graph, document behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
ytausch committed Feb 13, 2024
1 parent 62ee2eb commit b7627ef
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 14 deletions.
1 change: 0 additions & 1 deletion conda_forge_tick/auto_tick.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@
frozen_to_json_friendly,
get_keys_default,
load_existing_graph,
load_graph,
parse_meta_yaml,
parse_munged_run_export,
pluck,
Expand Down
2 changes: 1 addition & 1 deletion conda_forge_tick/pypi_name_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from packaging.utils import canonicalize_name as canonicalize_pypi_name

from .lazy_json_backends import LazyJson, dump, get_all_keys_for_hashmap, loads
from .utils import as_iterable, load_existing_graph, load_graph
from .utils import as_iterable, load_existing_graph


class Mapping(TypedDict):
Expand Down
14 changes: 9 additions & 5 deletions conda_forge_tick/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,23 +451,27 @@ def dump_graph(
def load_existing_graph(filename: str = DEFAULT_GRAPH_FILENAME) -> nx.DiGraph:
"""
Load the graph from a file using the lazy json backend.
If a non-existing or empty file is encountered, a FileNotFoundError is raised.
If you expect the graph to possibly not exist, use load_graph.
If the file does not exist, it is initialized with empty JSON before performing any reads.
If empty JSON is encountered, a ValueError is raised.
If you expect the graph to be possibly empty JSON (i.e. not initialized), use load_graph.
:return: the graph
:raises ValueError if the file contains empty JSON (or did not exist before)
"""
gx = load_graph(filename)
if gx is None:
raise FileNotFoundError(f"Graph file {filename} does not exist or is empty")
raise ValueError(f"Graph file {filename} contains empty JSON")
return gx


def load_graph(filename: str = DEFAULT_GRAPH_FILENAME) -> Optional[nx.DiGraph]:
"""
Load the graph from a file using the lazy json backend.
If you expect the graph to exist, use load_existing_graph.
If the file does not exist, it is initialized with empty JSON.
If you expect the graph to be non-empty JSON, use load_existing_graph.
:return: the graph, or None if the file does not exist or is empty JSON
:return: the graph, or None if the file is empty JSON (or
:raises FileNotFoundError if the file does not exist
"""
dta = copy.deepcopy(LazyJson(filename).data)
if dta:
Expand Down
129 changes: 122 additions & 7 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,52 @@
from conda_forge_tick.utils import get_keys_default
from unittest import mock
from unittest.mock import MagicMock, mock_open

import pytest

from conda_forge_tick.utils import (
DEFAULT_GRAPH_FILENAME,
get_keys_default,
load_existing_graph,
load_graph,
)

EMPTY_JSON = "{}"
DEMO_GRAPH = """
{
"directed": true,
"graph": {
"outputs_lut": {
"package1": {
"__set__": true,
"elements": [
"package1"
]
},
"package2": {
"__set__": true,
"elements": [
"package2"
]
}
}
},
"links": [
{
"source": "package1",
"target": "package2"
}
],
"multigraph": false,
"nodes": [
{
"id": "package1",
"payload": {
"__lazy_json__": "node_attrs/package1.json"
}
}
]
}
"""


def test_get_keys_default():
Expand All @@ -25,9 +73,76 @@ def test_get_keys_default_none():
"bot": None,
},
}
get_keys_default(
attrs,
["conda-forge.yml", "bot", "check_solvable"],
{},
False,
) is False
assert (
get_keys_default(
attrs,
["conda-forge.yml", "bot", "check_solvable"],
{},
False,
)
is False
)


def test_load_graph():
with mock.patch("builtins.open", mock_open(read_data=DEMO_GRAPH)) as mock_file:
gx = load_graph()

assert gx is not None

assert gx.nodes.keys() == {"package1", "package2"}

mock_file: MagicMock
mock_file.assert_has_calls([mock.call(DEFAULT_GRAPH_FILENAME)])


def test_load_graph_empty_graph():
with mock.patch("builtins.open", mock_open(read_data=EMPTY_JSON)) as mock_file:
gx = load_graph()

assert gx is None

mock_file: MagicMock
mock_file.assert_has_calls([mock.call(DEFAULT_GRAPH_FILENAME)])


@mock.patch("os.path.exists")
def test_load_graph_file_does_not_exist(exists_mock: MagicMock):
exists_mock.return_value = False

with mock.patch("builtins.open", mock_open(read_data=EMPTY_JSON)) as mock_file:
load_graph()

mock_file: MagicMock
mock_file.assert_has_calls([mock.call(DEFAULT_GRAPH_FILENAME, "w")])


def test_load_existing_graph():
with mock.patch("builtins.open", mock_open(read_data=DEMO_GRAPH)) as mock_file:
gx = load_existing_graph()

assert gx.nodes.keys() == {"package1", "package2"}

mock_file: MagicMock
mock_file.assert_has_calls([mock.call(DEFAULT_GRAPH_FILENAME)])


def test_load_existing_graph_empty_graph():
with mock.patch("builtins.open", mock_open(read_data=EMPTY_JSON)) as mock_file:
with pytest.raises(ValueError, match="empty JSON"):
load_existing_graph()

mock_file: MagicMock
mock_file.assert_has_calls([mock.call(DEFAULT_GRAPH_FILENAME)])


@mock.patch("os.path.exists")
def test_load_existing_graph_file_does_not_exist(exists_mock: MagicMock):
exists_mock.return_value = False

with mock.patch("builtins.open", mock_open(read_data=EMPTY_JSON)) as mock_file:
with pytest.raises(ValueError, match="empty JSON"):
load_existing_graph()

mock_file: MagicMock
mock_file.assert_has_calls([mock.call(DEFAULT_GRAPH_FILENAME, "w")])

0 comments on commit b7627ef

Please sign in to comment.