From 1aa720bc40c1e97240738fe26e0dc6cd024efd6d Mon Sep 17 00:00:00 2001 From: Riccardo De Maria Date: Sun, 1 Dec 2024 15:07:22 +0100 Subject: [PATCH 1/8] support setitem on col row --- tests/test_table.py | 36 ++++++++++++++++++++++++++++++++++++ xdeps/table.py | 40 ++++++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/tests/test_table.py b/tests/test_table.py index 8b62be1..7aab455 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -117,6 +117,42 @@ def test_table_getitem_edge_cases(): assert t[("betx",)][2] == t["betx"][2] +def test_table_setitem_col(): + t["2betx"] = t["betx"] * 2 + assert np.array_equal(t["2betx"], data["betx"] * 2) + t["betx"] = 1 + assert np.array_equal(t["betx"], np.ones(len(data["betx"]))) + +def test_table_setitem_col_row(): + t["betx", 1] = 10 + assert t["betx", 1] == 10 + t["betx", "ip2"] = 20 + assert t["betx", "ip2"] == 20 + t["betx", "ip2::1"] = 30 + assert t["betx", "ip2::1"] == 30 + t["betx", "ip2<<1"] = 40 + assert t["betx", "ip2<<1"] == 40 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + t["betx", "ip2::1>>1"] = 50 + assert t["betx", "ip2::1>>1"] == 50 + def test_table_numpy_string(): tab = Table(dict(name=np.array(["a", "b$b"]), val=np.array([1, 2]))) assert tab["val", tab.name[1]] == 2 diff --git a/xdeps/table.py b/xdeps/table.py index 4d2dc3a..68277ec 100644 --- a/xdeps/table.py +++ b/xdeps/table.py @@ -543,7 +543,7 @@ def __getitem__(self, args): return self._data[args] except KeyError: return eval(args, gblmath, self._data) - if type(args) is tuple: # multiple args + if isinstance(args,tuple): # multiple args if len(args) == 0: col = None row = None @@ -824,14 +824,38 @@ def __setitem__(self, key, val): object.__setattr__(self, "_index_cache", None) object.__setattr__(self, "_count_cache", None) object.__setattr__(self, "_name_cache", None) - if key in self.__dict__: - object.__setattr__(self, key, val) - elif key in self._col_names: - self._data[key][:] = val + elif isinstance(key, str): + if key in self.__dict__: + object.__setattr__(self, key, val) + elif key in self._col_names: + self._data[key][:] = val + else: + self._data[key] = val + if hasattr(val, "__iter__") and len(val) == len(self): + self._col_names.append(key) + elif isinstance(key,tuple): + col,row = key + col = self._data[col] + if isinstance(row, str): + cache, count = self._get_cache() + idx = cache.get((row, 0)) + if idx is None: + name, count, offset = self._split_name_count_offset(row) + idx = self._get_row_cache_raise(name, count, offset) + elif isinstance(row, tuple): + cache, count = self._get_cache() + idx = cache.get(row) + if idx is None: + idx = self._get_row_cache_raise(*row) + elif isinstance(row, slice): + idx = self._get_row_indices(row) + elif isinstance(row, list): + idx = self._get_row_indices(row) + else: + idx = row + col[idx]=val else: - self._data[key] = val - if hasattr(val, "__iter__") and len(val) == len(self): - self._col_names.append(key) + raise ValueError(f"Invalid key {key}") __setattr__ = __setitem__ From 53498caef06c1c50ba0a1f80ee31050c75348620 Mon Sep 17 00:00:00 2001 From: Riccardo De Maria Date: Mon, 2 Dec 2024 14:23:00 +0100 Subject: [PATCH 2/8] fix bug --- xdeps/table.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xdeps/table.py b/xdeps/table.py index 68277ec..2d63114 100644 --- a/xdeps/table.py +++ b/xdeps/table.py @@ -477,7 +477,10 @@ def _select(self, rows, cols): col_list.insert(0, self._index) data = {} for cc in col_list: - data[cc] = eval(cc, gblmath, view) + try: + data[cc] = view[cc] + except KeyError: + data[cc] = eval(cc, gblmath, view) for kk in self.keys(exclude_columns=True): data[kk] = self._data[kk] return self.__class__( From 8dfcce8ea6cc2723c7ccd2d532c8bbda7372d30f Mon Sep 17 00:00:00 2001 From: Riccardo De Maria Date: Mon, 2 Dec 2024 15:03:23 +0100 Subject: [PATCH 3/8] fix show --- tests/test_table.py | 47 +++++++++++++++++++++++++++++++++++---------- xdeps/table.py | 2 ++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/tests/test_table.py b/tests/test_table.py index 7aab455..3b8bf26 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -3,18 +3,18 @@ from xdeps import Table -data = { - "name": np.array(["ip1", "ip2", "ip2", "ip3", "tab$end"]), - "s": np.array([1.0, 2.0, 2.1, 3.0, 4.0]), - "betx": np.array([4.0, 5.0, 5.1, 6.0, 7.0]), - "bety": np.array([2.0, 3.0, 3.1, 4.0, 9.0]), -} +def get_a_table(): + data = { + "name": np.array(["ip1", "ip2", "ip2", "ip3", "tab$end"]), + "s": np.array([1.0, 2.0, 2.1, 3.0, 4.0]), + "betx": np.array([4.0, 5.0, 5.1, 6.0, 7.0]), + "bety": np.array([2.0, 3.0, 3.1, 4.0, 9.0]), + } + t = Table(data) + return t, data -## Table tests - -t = Table(data) - +t, data = get_a_table() def test_table_initialization(): # Valid initialization @@ -118,12 +118,15 @@ def test_table_getitem_edge_cases(): def test_table_setitem_col(): + t, data = get_a_table() t["2betx"] = t["betx"] * 2 assert np.array_equal(t["2betx"], data["betx"] * 2) t["betx"] = 1 assert np.array_equal(t["betx"], np.ones(len(data["betx"]))) + def test_table_setitem_col_row(): + t, data = get_a_table() t["betx", 1] = 10 assert t["betx", 1] == 10 t["betx", "ip2"] = 20 @@ -153,6 +156,7 @@ def test_table_setitem_col_row(): t["betx", "ip2::1>>1"] = 50 assert t["betx", "ip2::1>>1"] == 50 + def test_table_numpy_string(): tab = Table(dict(name=np.array(["a", "b$b"]), val=np.array([1, 2]))) assert tab["val", tab.name[1]] == 2 @@ -278,6 +282,29 @@ def test_table_show(): assert table.show(output=str) == "name value\na 1\nb 2\nc 3" +def test_table_show_rows(): + data = {"name": np.array(["a", "b", "c"]), "value": np.array([1, 2, 3])} + table = Table(data) + assert table.show(rows=1, output=str) == "name value\nb 2" + + +def test_table_show_cols(): + data = {"name": np.array(["a", "b", "c"]), "value": np.array([1, 2, 3])} + table = Table(data) + assert ( + table.show(cols="value", output=str) + == "name value\na 1\nb 2\nc 3" + ) + + +def test_table_show_rows_cols(): + t, data = get_a_table() + assert ( + t.show(rows="ip2.*", cols="betx", output=str) + == "name betx\nip1 5\nip2::0 5.1" + ) + + ## Table cols tests diff --git a/xdeps/table.py b/xdeps/table.py index 2d63114..af13349 100644 --- a/xdeps/table.py +++ b/xdeps/table.py @@ -443,6 +443,8 @@ def _get_row_indices(self, row): return np.array(out, dtype=int) else: raise ValueError(f"Invalid row selector {row}") + elif row is None: + return slice(None) else: return [self._get_row_index(row)] From 3a361b43b12c039a76bce4d31cc464e43edefa3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20=C5=81opaciuk?= Date: Mon, 9 Dec 2024 10:56:19 +0100 Subject: [PATCH 4/8] Build wheels for Python 3.8 or higher --- .github/workflows/deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 939da5f..bf48ebc 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -24,7 +24,7 @@ jobs: - name: Build wheels run: python -m cibuildwheel --output-dir wheelhouse env: - CIBW_PROJECT_REQUIRES_PYTHON: ">=3.7" + CIBW_PROJECT_REQUIRES_PYTHON: ">=3.8" - uses: actions/upload-artifact@v4 with: From b00102da62a5341ea1ea12c8154c0fff614db0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20=C5=81opaciuk?= Date: Mon, 9 Dec 2024 10:59:21 +0100 Subject: [PATCH 5/8] Bump Python version in pyproject.toml to >=3.8 --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index bc2be67..e23a17a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,5 @@ [build-system] requires = ["setuptools", "wheel", "Cython"] + +[project] +requires-python = ">= 3.8" From dbca11bc770ffd7ae8d9e3c35ba6c4cf6754282b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20=C5=81opaciuk?= Date: Tue, 10 Dec 2024 12:11:14 +0100 Subject: [PATCH 6/8] Revert "Bump Python version in pyproject.toml to >=3.8" This reverts commit b00102da62a5341ea1ea12c8154c0fff614db0e4. --- pyproject.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e23a17a..bc2be67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,2 @@ [build-system] requires = ["setuptools", "wheel", "Cython"] - -[project] -requires-python = ">= 3.8" From e3de3d09359b7773376bf516aeef3d50299f341f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20=C5=81opaciuk?= Date: Tue, 10 Dec 2024 17:55:16 +0100 Subject: [PATCH 7/8] Fix bug in Table.__setattr__: don't terminate on cache invalidation --- tests/test_table.py | 2 ++ xdeps/table.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_table.py b/tests/test_table.py index 3b8bf26..079665d 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -123,6 +123,8 @@ def test_table_setitem_col(): assert np.array_equal(t["2betx"], data["betx"] * 2) t["betx"] = 1 assert np.array_equal(t["betx"], np.ones(len(data["betx"]))) + t["name"] = t["name"] * 2 + assert np.all(t['name'] == [x * 2 for x in data['name']]) def test_table_setitem_col_row(): diff --git a/xdeps/table.py b/xdeps/table.py index af13349..77ec07b 100644 --- a/xdeps/table.py +++ b/xdeps/table.py @@ -829,7 +829,8 @@ def __setitem__(self, key, val): object.__setattr__(self, "_index_cache", None) object.__setattr__(self, "_count_cache", None) object.__setattr__(self, "_name_cache", None) - elif isinstance(key, str): + + if isinstance(key, str): if key in self.__dict__: object.__setattr__(self, key, val) elif key in self._col_names: From 73c9d3d7a68a240809cfc283ddc9005e2422603e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20=C5=81opaciuk?= Date: Tue, 17 Dec 2024 09:29:13 +0100 Subject: [PATCH 8/8] Change version number --- xdeps/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xdeps/_version.py b/xdeps/_version.py index 4ca39e7..b4e3540 100644 --- a/xdeps/_version.py +++ b/xdeps/_version.py @@ -1 +1 @@ -__version__ = '0.8.2' +__version__ = '0.8.3'