code: def test_immutability(self):
      # Top level immutable
      a = AttrDict()
      a.foo = 0
      a.immutable(True)
      with self.assertRaises(AttributeError):
          a.foo = 1
          a.bar = 1
      assert a.is_immutable()
      assert a.foo == 0
      a.immutable(False)
      assert not a.is_immutable()
      a.foo = 1
      assert a.foo == 1
  
      # Recursively immutable
      a.level1 = AttrDict()
      a.level1.foo = 0
      a.level1.level2 = AttrDict()
      a.level1.level2.foo = 0
      a.immutable(True)
      assert a.is_immutable()
      with self.assertRaises(AttributeError):
          a.level1.level2.foo = 1
          a.level1.bar = 1
      assert a.level1.level2.foo == 0
  
      # Serialize immutability state
      a.immutable(True)
      a2 = core_config.load_cfg(yaml.dump(a))
      assert a.is_immutable()
      assert a2.is_immutable()
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from __future__ import unicode_literals
  import copy
  import tempfile
  import unittest
  import yaml
  from detectron.core.config import cfg
  from detectron.utils.collections import AttrDict
  import detectron.core.config
  import detectron.utils.logging
label_desc: Use image node_id 1 for calling the TestAttrDict obj's underlying member method code with example usage: obj.test_immutability() without return types