@@ -137,23 +137,37 @@ def __getattr__(self, key):
137
137
raise AttributeError (key )
138
138
139
139
def set_read_only (self , names , msg = "Attribute is read-only" ):
140
- object .__setattr__ (self , "_read_only" , names )
141
- object .__setattr__ (self , "_read_only_msg" , msg )
140
+ """
141
+ Designate named attributes as read-only with the corresponding msg
142
+
143
+ Method is additive. Making additional calls to this method will update
144
+ existing messages and add to the current set of _read_only names.
145
+ """
146
+ new_read_only = {name : msg for name in names }
147
+ if getattr (self , "_read_only" , False ):
148
+ self ._read_only .update (new_read_only )
149
+ else :
150
+ object .__setattr__ (self , "_read_only" , new_read_only )
142
151
143
152
def finalize (self , msg = "Object is final: No new keys may be added." ):
144
153
"""Prevent any new keys being set."""
145
154
object .__setattr__ (self , "_final" , msg )
146
155
147
156
def __setitem__ (self , key , val ):
148
- if key in self .__dict__ .get ("_read_only" , [] ):
149
- raise AttributeError (self ._read_only_msg , key )
157
+ if key in self .__dict__ .get ("_read_only" , {} ):
158
+ raise AttributeError (self ._read_only [ key ] , key )
150
159
151
160
final_msg = self .__dict__ .get ("_final" )
152
161
if final_msg and key not in self :
153
162
raise AttributeError (final_msg , key )
154
163
155
164
return super ().__setitem__ (key , val )
156
165
166
+ def update (self , other ):
167
+ # Overrides dict.update() to use __setitem__ above
168
+ for k , v in other .items ():
169
+ self [k ] = v
170
+
157
171
# pylint: disable=inconsistent-return-statements
158
172
def first (self , * names ):
159
173
for name in names :
0 commit comments