From 0778c11a4c1f6e58d8d92ee9a9a5ad3db7660820 Mon Sep 17 00:00:00 2001
From: Enric Tejedor Saavedra <enric.tejedor.saavedra@cern.ch>
Date: Wed, 27 Feb 2019 16:57:23 +0100
Subject: [PATCH] [Exp PyROOT] TVectorT: add __getitem__ pythonisation with
 checked bounds

Throws IndexError if index is out of bounds and also makes it possible
to iterate over a TVectorT.
---
 .../python/ROOT/pythonization/_generic.py     | 26 +++++++++++++++++--
 .../python/ROOT/pythonization/_tvectort.py    |  7 +++++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_generic.py b/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_generic.py
index e12f27f43c8..83c20a000b7 100644
--- a/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_generic.py
+++ b/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_generic.py
@@ -1,7 +1,7 @@
-# Author: Stefan Wunsch CERN  06/2018
+# Author: Stefan Wunsch, Enric Tejedor CERN  06/2018
 
 ################################################################################
-# Copyright (C) 1995-2018, Rene Brun and Fons Rademakers.                      #
+# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.                      #
 # All rights reserved.                                                         #
 #                                                                              #
 # For the licensing terms see $ROOTSYS/LICENSE.                                #
@@ -11,6 +11,28 @@
 from libROOTPython import AddPrettyPrintingPyz
 from ROOT import pythonization
 
+def _add_getitem_checked(klass):
+    # Parameters:
+    # - klass: class where to add a __getitem__ method that raises
+    # IndexError if index is out of range
+
+    def getitem_checked(o, i):
+        # Get item of `o` at `i` or raise IndexError if index is
+        # out of range.
+        # Assumes `o` has `__len__`.
+        # Parameters:
+        # - o: object
+        # - i: index to be checked in object
+        # Returns:
+        # - o[i]
+        if i >= 0 and i < len(o):
+            return o._getitem__unchecked(i)
+        else:
+            raise IndexError('index out of range')
+    
+    klass._getitem__unchecked = klass.__getitem__
+    klass.__getitem__ = getitem_checked
+
 
 @pythonization()
 def pythonizegeneric(klass, name):
diff --git a/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_tvectort.py b/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_tvectort.py
index c1d0aa4ea36..b35a9d4abae 100644
--- a/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_tvectort.py
+++ b/bindings/pyroot_experimental/PyROOT/python/ROOT/pythonization/_tvectort.py
@@ -10,6 +10,8 @@
 
 from ROOT import pythonization
 
+from ._generic import _add_getitem_checked
+
 
 @pythonization()
 def pythonize_tvectort(klass, name):
@@ -21,4 +23,9 @@ def pythonize_tvectort(klass, name):
         # Support `len(v)` as `v.GetNoElements()`
         klass.__len__ = klass.GetNoElements
 
+        # Add checked __getitem__.
+        # Allows to throw pythonic IndexError when index is out of range
+        # and to iterate over the vector.
+        _add_getitem_checked(klass)
+
     return True
-- 
GitLab