Skip to content

Commit

Permalink
Implement safeguard against problematic meta keys (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielhuppmann authored Nov 22, 2024
1 parent 65ce305 commit 362d503
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
8 changes: 8 additions & 0 deletions ixmp4/data/db/meta/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from ixmp4 import db
from ixmp4.core.decorators import check_types
from ixmp4.core.exceptions import InvalidRunMeta
from ixmp4.data import abstract
from ixmp4.data.auth.decorators import guard
from ixmp4.data.db.model import Model
Expand All @@ -16,6 +17,8 @@
from .. import base
from .model import RunMetaEntry

ILLEGAL_META_KEYS = {"model", "scenario", "id", "version", "is_default"}


class RemoveRunMetaEntryFrameSchema(pa.DataFrameModel):
key: Series[pa.String] = pa.Field(coerce=True)
Expand Down Expand Up @@ -60,6 +63,8 @@ def add(
default_only=False,
)

if key in ILLEGAL_META_KEYS:
raise InvalidRunMeta("Illegal meta key: " + key)
entry = RunMetaEntry(run__id=run__id, key=key, value=value)
self.session.add(entry)
return entry
Expand Down Expand Up @@ -205,6 +210,9 @@ def map_value_column(df: pd.DataFrame):
@check_types
@guard("edit")
def bulk_upsert(self, df: DataFrame[AddRunMetaEntryFrameSchema]) -> None:
if illegal_keys := (set(df.key.values) & ILLEGAL_META_KEYS):
raise InvalidRunMeta("Illegal meta key(s): " + ", ".join(illegal_keys))

self.check_df_access(df)
df["type"] = df["value"].map(type).map(RunMetaEntry.Type.from_pytype)

Expand Down
16 changes: 15 additions & 1 deletion tests/data/test_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pytest

import ixmp4
from ixmp4.core.exceptions import SchemaError
from ixmp4.core.exceptions import InvalidRunMeta, SchemaError
from ixmp4.data.abstract.meta import RunMetaEntry

from ..utils import assert_unordered_equality
Expand All @@ -19,6 +19,8 @@
columns=["id", "key", "type", "value"],
)

TEST_ILLEGAL_META_KEYS = {"model", "scenario", "id", "version", "is_default"}


class TestDataMeta:
def test_create_get_entry(self, platform: ixmp4.Platform):
Expand All @@ -37,6 +39,18 @@ def test_create_get_entry(self, platform: ixmp4.Platform):
assert entry.value == value
assert entry.type == type

def test_illegal_key(self, platform: ixmp4.Platform):
run = platform.runs.create("Model", "Scenario")
for key in TEST_ILLEGAL_META_KEYS:
with pytest.raises(InvalidRunMeta, match="Illegal meta key: " + key):
platform.backend.meta.create(run.id, key, "foo")

df = pd.DataFrame(
{"run__id": [run.id] * 2, "key": [key, "foo"], "value": ["bar", "baz"]},
)
with pytest.raises(InvalidRunMeta, match=r"Illegal meta key\(s\): " + key):
platform.backend.meta.bulk_upsert(df)

def test_entry_unique(self, platform: ixmp4.Platform):
run = platform.runs.create("Model", "Scenario")
platform.backend.meta.create(run.id, "Key", "Value")
Expand Down

0 comments on commit 362d503

Please sign in to comment.