From a96a508d906c5c31de06573583ec8c5fd7a2de9b Mon Sep 17 00:00:00 2001 From: Derek Jones Date: Tue, 15 Oct 2024 10:06:30 -0700 Subject: [PATCH] Make helper classes private, address code coverage issues. Some of the dict-like overloads were an overachievement. --- src/nested_pandas/nestedframe/core.py | 15 ++++----------- .../nested_pandas/nestedframe/test_nestedframe.py | 4 ++++ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/nested_pandas/nestedframe/core.py b/src/nested_pandas/nestedframe/core.py index d772b1c..bf2ea6f 100644 --- a/src/nested_pandas/nestedframe/core.py +++ b/src/nested_pandas/nestedframe/core.py @@ -69,7 +69,7 @@ def _constructor_expanddim(self) -> Self: # type: ignore[name-defined] # noqa: __pandas_priority__ = 3500 -class NestResolver(dict): +class _NestResolver(dict): """ Used by NestedFrame.eval to resolve the names of nests at the top level. While the resolver is normally a dictionary, with values that are fixed @@ -83,22 +83,15 @@ def __init__(self, outer: NestedFrame): super().__init__() def __contains__(self, item): - if not isinstance(item, str): - return False top_nest = item if "." not in item else item.split(".")[0].strip() return top_nest in self._outer.nested_columns - def __len__(self): - return len(self._outer.nested_columns) - def __getitem__(self, item): - if not isinstance(item, str): - raise KeyError(f"Unknown nest {item}") top_nest = item if "." not in item else item.split(".")[0].strip() if not super().__contains__(top_nest): if top_nest not in self._outer.nested_columns: raise KeyError(f"Unknown nest {top_nest}") - super().__setitem__(top_nest, NestedFieldResolver(top_nest, self._outer)) + super().__setitem__(top_nest, _NestedFieldResolver(top_nest, self._outer)) return super().__getitem__(top_nest) def __setitem__(self, key, value): @@ -110,7 +103,7 @@ def __setitem__(self, key, value): pass -class NestedFieldResolver: +class _NestedFieldResolver: """ Used by NestedFrame.eval to resolve the names of fields in nested columns when encountered in expressions, interpreting __getattr__ in terms of a @@ -448,7 +441,7 @@ def eval(self, expr: str, *, inplace: bool = False, **kwargs) -> Any | None: -------- https://pandas.pydata.org/docs/reference/api/pandas.eval.html """ - kwargs["resolvers"] = tuple(kwargs.get("resolvers", ())) + (NestResolver(self),) + kwargs["resolvers"] = tuple(kwargs.get("resolvers", ())) + (_NestResolver(self),) kwargs["inplace"] = inplace kwargs["parser"] = "nested-pandas" return super().eval(expr, **kwargs) diff --git a/tests/nested_pandas/nestedframe/test_nestedframe.py b/tests/nested_pandas/nestedframe/test_nestedframe.py index 1590529..eb7c3f3 100644 --- a/tests/nested_pandas/nestedframe/test_nestedframe.py +++ b/tests/nested_pandas/nestedframe/test_nestedframe.py @@ -860,6 +860,10 @@ def test_eval_assignment(): assert (nf_nx["packed.f"] == nf["a"] + nf["packed.c"]).all() assert (nf_nx["packed.f"] == pd.Series([1, 3, 5, 12, 6, 5, 4, 7, 4], index=to_pack.index)).all() + # Only supporting one level of nesting at present. + with pytest.raises(ValueError): + nf.eval("packed.c.inner = packed.c * 2 + packed.d") + # Assigning to new base columns from nested columns. This can't be done because # it would attempt to create base column values that were "between indexes", or as # Pandas puts, duplicate index labels.