nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: pyg-team/pytorch_geometric
Pull request #10067 (2025-02-24 14:00:07)

Support `HashTensor.numpy()`/`HashTensor.tolist()`


Patch:
diff --git a/torch_geometric/hash_tensor.py b/torch_geometric/hash_tensor.py
index db894e99e..41782deea 100644
--- a/torch_geometric/hash_tensor.py
+++ b/torch_geometric/hash_tensor.py
@@ -12,6 +12,7 @@ from typing import (
     Union,
 )
 
+import numpy as np
 import torch
 import torch.utils._pytree as pytree
 import xxhash
@@ -303,6 +304,10 @@ class HashTensor(Tensor):
         """"""  # noqa: D419
         return self.as_tensor().tolist()
 
+    def numpy(self, *, force: bool = False) -> np.ndarray:
+        """"""  # noqa: D419
+        return self.as_tensor().numpy(force=force)
+
     def index_select(  # type: ignore
         self,
         dim: int,


Test patch:
diff --git a/test/test_edge_index.py b/test/test_edge_index.py
index ed06d24d4..eb78b3246 100644
--- a/test/test_edge_index.py
+++ b/test/test_edge_index.py
@@ -1212,7 +1212,7 @@ def test_sparse_resize(dtype, device):
     assert out._T_indptr is None
 
 
-def test_to_list():
+def test_tolist():
     adj = EdgeIndex([[0, 1, 1, 2], [1, 0, 2, 1]])
     with pytest.raises(RuntimeError, match="supported for tensor subclasses"):
         adj.tolist()
diff --git a/test/test_hash_tensor.py b/test/test_hash_tensor.py
index fbaaf7cf9..b77662eae 100644
--- a/test/test_hash_tensor.py
+++ b/test/test_hash_tensor.py
@@ -1,6 +1,7 @@
 import os.path as osp
 from typing import List
 
+import numpy as np
 import pytest
 import torch
 
@@ -440,6 +441,18 @@ def test_select(device):
     assert out.as_tensor().equal(value[:, 0])
 
 
+def test_tolist():
+    key = torch.tensor([2, 1, 0])
+    value = torch.randn(key.size(0), 2)
+    assert HashTensor(key, value).tolist() == value.tolist()
+
+
+def test_numpy():
+    key = torch.tensor([2, 1, 0])
+    value = torch.randn(key.size(0), 2)
+    assert np.allclose(HashTensor(key, value).numpy(), value.numpy())
+
+
 def _collate_fn(hash_tensors: List[HashTensor]) -> List[HashTensor]:
     return hash_tensors
Repository: pyg-team/pytorch_geometric
Pull request #10209 (2025-04-18 09:48:37)

Don't warn `Using CPU-based processing within 'map_index'` repeatedly


Patch:
diff --git a/torch_geometric/utils/map.py b/torch_geometric/utils/map.py
index bf4c2167d..4a2c8a63e 100644
--- a/torch_geometric/utils/map.py
+++ b/torch_geometric/utils/map.py
@@ -1,4 +1,3 @@
-import warnings
 from typing import Optional, Tuple, Union
 
 import numpy as np
@@ -6,6 +5,10 @@ import torch
 from torch import Tensor
 from torch.utils.dlpack import from_dlpack
 
+from torch_geometric.warnings import WarningCache
+
+_warning_cache = WarningCache()
+
 
 def map_index(
     src: Tensor,
@@ -93,10 +96,10 @@ def map_index(
             WITH_CUDF = True
         except ImportError:
             import pandas as pd
-            warnings.warn("Using CPU-based processing within 'map_index' "
-                          "which may cause slowdowns and device "
-                          "synchronization. Consider installing 'cudf' to "
-                          "accelerate computation")
+            _warning_cache.warn("Using CPU-based processing within "
+                                "'map_index' which may cause slowdowns and "
+                                "device synchronization. Consider installing "
+                                "'cudf' to accelerate computation")
     else:
         import pandas as pd
 
diff --git a/torch_geometric/warnings.py b/torch_geometric/warnings.py
index 771e74c31..4a32b026d 100644
--- a/torch_geometric/warnings.py
+++ b/torch_geometric/warnings.py
@@ -4,11 +4,11 @@ from typing import Literal
 import torch_geometric
 
 
-def warn(message: str) -> None:
+def warn(message: str, stacklevel: int = 5) -> None:
     if torch_geometric.is_compiling():
         return
 
-    warnings.warn(message)
+    warnings.warn(message, stacklevel=stacklevel)
 
 
 def filterwarnings(
@@ -19,3 +19,12 @@ def filterwarnings(
         return
 
     warnings.filterwarnings(action, message)
+
+
+class WarningCache(set):
+    """Cache for warnings."""
+    def warn(self, message: str, stacklevel: int = 5) -> None:
+        """Trigger warning message."""
+        if message not in self:
+            self.add(message)
+            warn(message, stacklevel=stacklevel)


Test patch:
diff --git a/test/test_warnings.py b/test/test_warnings.py
index 9f57277a1..1a6260294 100644
--- a/test/test_warnings.py
+++ b/test/test_warnings.py
@@ -3,7 +3,7 @@ from unittest.mock import patch
 
 import pytest
 
-from torch_geometric.warnings import warn
+from torch_geometric.warnings import WarningCache, warn
 
 
 def test_warn():
@@ -17,3 +17,19 @@ def test_no_warn_if_compiling(_):
     with warnings.catch_warnings():
         warnings.simplefilter('error')
         warn('test')
+
+
+def test_warning_cache():
+    cache = WarningCache()
+    assert len(cache) == 0
+
+    cache.warn('test')
+    assert len(cache) == 1
+    assert 'test' in cache
+
+    cache.warn('test')
+    assert len(cache) == 1
+
+    cache.warn('test2')
+    assert len(cache) == 2
+    assert 'test2' in cache