From 1998953880fcdb4b3987dbbe49c98c6a72552090 Mon Sep 17 00:00:00 2001
From: Claude Paroz <claude@2xlibre.net>
Date: Thu, 17 Feb 2022 23:40:44 +0100
Subject: [PATCH 1/2] Remove recursiveGet/Set/DelAttr

---
 src/reportlab/lib/utils.py |  31 --------
 tests/test_lib_utils.py    | 153 +------------------------------------
 2 files changed, 2 insertions(+), 182 deletions(-)

diff --git a/src/reportlab/lib/utils.py b/src/reportlab/lib/utils.py
index 811d6906..251cfce1 100644
--- a/src/reportlab/lib/utils.py
+++ b/src/reportlab/lib/utils.py
@@ -1329,37 +1329,6 @@ class TimeStamp:
     def asctime(self):
         return time.asctime(self.lt)
 
-def recursiveGetAttr(obj, name, g=None):
-    "Can call down into e.g. object1.object2[4].attr"
-    if not isStr(name): raise TypeError('invalid reursive acess using %r' % name)
-    name = asNative(name)
-    name = name.strip()
-    if not name: raise ValueError('empty recursive access')
-    dot = '.' if name and name[0] not in '[.(' else ''
-    return rl_safe_eval('obj%s%s'%(dot,name), g={}, l=dict(obj=obj))
-
-def recursiveSetAttr(obj, name, value):
-    "Can call down into e.g. object1.object2[4].attr = value"
-    #get the thing above last.
-    tokens = name.split('.')
-    if len(tokens) == 1:
-        setattr(obj, name, value)
-    else:
-        most = '.'.join(tokens[:-1])
-        last = tokens[-1]
-        parent = recursiveGetAttr(obj, most)
-        setattr(parent, last, value)
-
-def recursiveDelAttr(obj, name):
-    tokens = name.split('.')
-    if len(tokens) == 1:
-        delattr(obj, name)
-    else:
-        most = '.'.join(tokens[:-1])
-        last = tokens[-1]
-        parent = recursiveGetAttr(obj, most)
-        delattr(parent, last)
-
 def yieldNoneSplits(L):
     '''yield sublists of L separated by None; the Nones disappear'''
     i = 0
diff --git a/tests/test_lib_utils.py b/tests/test_lib_utils.py
index fe3e4370..e9ff8208 100644
--- a/tests/test_lib_utils.py
+++ b/tests/test_lib_utils.py
@@ -11,9 +11,8 @@ import reportlab
 from reportlab import rl_config
 import unittest
 from reportlab.lib import colors
-from reportlab.lib.utils import recursiveImport, recursiveGetAttr, recursiveSetAttr, rl_isfile, \
+from reportlab.lib.utils import recursiveImport, rl_isfile, \
                                 isCompactDistro, isPyPy, TimeStamp, rl_get_module, \
-                                recursiveGetAttr, recursiveSetAttr, recursiveDelAttr, \
                                 asUnicode, asUnicodeEx, asBytes
 
 def _rel_open_and_read(fn):
@@ -92,24 +91,6 @@ class ImporterTestCase(unittest.TestCase):
         finally:
             os.chdir(cwd)
 
-    def test5(self):
-        "recursive attribute setting/getting on modules"
-        import reportlab.lib.units
-        inch = recursiveGetAttr(reportlab, 'lib.units.inch')
-        assert inch == 72
-
-        recursiveSetAttr(reportlab, 'lib.units.cubit', 18*inch)
-        cubit = recursiveGetAttr(reportlab, 'lib.units.cubit')
-        assert cubit == 18*inch
-
-    def test6(self):
-        "recursive attribute setting/getting on drawings"
-        from reportlab.graphics.charts.barcharts import sampleH1
-        drawing = sampleH1()
-        recursiveSetAttr(drawing, 'barchart.valueAxis.valueMax', 72)
-        theMax = recursiveGetAttr(drawing, 'barchart.valueAxis.valueMax')
-        assert theMax == 72
-
     def test7(self):
         "test open and read of a simple relative file"
         b = _rel_open_and_read('../docs/images/Edit_Prefs.gif')
@@ -226,138 +207,8 @@ class ImporterTestCase(unittest.TestCase):
         self.assertRaises(AttributeError,asBytes,['abc'])
         self.myAssertRaisesRegex(AttributeError,"asBytes\(.*'list' object has no attribute 'encode'", asBytes,['abc'])
 
-class RaccessTest:
-    l = [1, 2]
-    a = [0, [1, 2, [3,4]]]
-    b = {'x': {'y': 'y'}, 'z': [1, 2]}
-    z = 'z'
-
-class RaccessPerson:
-    settings = {
-        'autosave': True,
-        'style': {
-            'height': 30,
-            'width': 200
-        },
-        'themes': ['light', 'dark']
-    }
-    def __init__(self, name, age, friends):
-        self.name = name
-        self.age = age
-        self.friends = friends
-
-class RaccessTestCase(unittest.TestCase):
-    "Test recursive access functions"
-    def test1(self):
-        def innerTest(k,v):
-            obj = RaccessTest()
-            obj.t = obj
-            obj.a.append(obj)
-            obj.b['w'] = obj
-            self.assertEqual(recursiveGetAttr(obj,k),v,"error getattr(obj,%r)==%r" % (k,v))
-        for k,v in [
-            ('l', RaccessTest.l),
-            ('t.t.t.t.z', 'z'),
-            ('a[0]', 0),
-            ('a[1][0]', 1),
-            ('a[1][2]', [3,4]),
-            ('b["x"]', {'y': 'y'}),
-            ('b["x"]["y"]', 'y'),
-            ('b["z"]', [1,2]),
-            ('b["z"][1]', 2),
-            ('b["w"].z', 'z'),
-            ('b["w"].t.l', [1, 2]),
-            ('a[-1].z', 'z'),
-            ('l[-1]', 2),
-            ('a[2].t.a[-1].z', 'z'),
-            ('a[2].t.b["z"][0]', 1),
-            ('a[-1].t.z', 'z'),
-            ]:
-            innerTest(k,v)
-
-    def test_person_example(self):
-        bob = RaccessPerson(name="Bob", age=31, friends=[])
-        jill = RaccessPerson(name="Jill", age=29, friends=[bob])
-        jack = RaccessPerson(name="Jack", age=28, friends=[bob, jill])
-
-        # Nothing new
-        self.assertEqual(recursiveGetAttr(bob, 'age') ,31)
-
-        # Lists
-        self.assertEqual(recursiveGetAttr(jill, 'friends[0].name') ,'Bob')
-        self.assertEqual(recursiveGetAttr(jack, 'friends[-1].age') ,29)
-
-        # Dict lookups
-        self.assertEqual(recursiveGetAttr(jack, 'settings["style"]["width"]') ,200)
-
-        # Combination of lookups
-        self.assertEqual(recursiveGetAttr(jack, 'settings["themes"][-2]') ,'light')
-        self.assertEqual(recursiveGetAttr(jack, 'friends[-1].settings["themes"][1]') ,'dark')
-
-        # Setattr
-        #recursiveSetAttr(bob, 'settings["style"]["width"]', 400)
-        #self.assertEqual(recursiveGetAttr(bob, 'settings["style"]["width"]') ,400)
-
-        # Nested objects
-        recursiveSetAttr(bob, 'friends', [jack, jill])
-        self.assertEqual(recursiveGetAttr(jack, 'friends[0].friends[0]') ,jack)
-
-        recursiveSetAttr(jill, 'friends[0].age', 32)
-        self.assertEqual(bob.age ,32)
-
-        # Deletion
-        #recursiveDelAttr(jill, 'friends[0]')
-        #self.assertEqual(len(jill.friends) ,0)
-
-        recursiveDelAttr(jill, 'age')
-        assert not hasattr(jill, 'age')
-
-        recursiveDelAttr(bob, 'friends[0].age')
-        assert not hasattr(jack, 'age')
-
-        # Unsupported
-        #with self.assertRaises(NotImplementedError) as e:
-        #   recursiveGetAttr(bob, 'friends[0+1]')
-
-        # Nice try, function calls are not allowed
-        #with self.assertRaises(ValueError):
-        #   recursiveGetAttr(bob, 'friends.pop(0)')
-
-        # Must be an expression
-        with self.assertRaises(SyntaxError):
-            recursiveGetAttr(bob, 'friends = []')
-
-        # Must be an expression
-        with self.assertRaises(SyntaxError):
-            recursiveGetAttr(bob, 'friends..')
-
-        # Must be an expression
-        with self.assertRaises(KeyError):
-            recursiveGetAttr(bob, 'settings["DoesNotExist"]')
-
-        # Must be an expression
-        with self.assertRaises(IndexError):
-            recursiveGetAttr(bob, 'friends[100]')
-
-    def test_empty(self):
-        obj = RaccessTest()
-        with self.assertRaises(ValueError):
-           recursiveGetAttr(obj,"  ")
-
-        with self.assertRaises(ValueError):
-            recursiveGetAttr(obj,"")
-
-        with self.assertRaises(TypeError):
-            recursiveGetAttr(obj, 0)
-
-        with self.assertRaises(TypeError):
-            recursiveGetAttr(obj, None)
-
-        with self.assertRaises(TypeError):
-            recursiveGetAttr(obj, obj)
-
 def makeSuite():
-    return makeSuiteForClasses(ImporterTestCase,RaccessTestCase)
+    return makeSuiteForClasses(ImporterTestCase)
 
 if __name__ == "__main__": #noruntests
     unittest.TextTestRunner().run(makeSuite())
-- 
2.30.2

