Skip to content

Commit c33afaf

Browse files
committed
Adding skip_unsettable flag to load method
1 parent e61aaa1 commit c33afaf

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

tap/tap.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,12 +487,17 @@ def save(self, path: str) -> None:
487487
with open(path, 'w') as f:
488488
json.dump(self._log_all(), f, indent=4, sort_keys=True, cls=PythonObjectEncoder)
489489

490-
def load(self, path: str, check_reproducibility: bool = False) -> None:
490+
def load(self,
491+
path: str,
492+
check_reproducibility: bool = False,
493+
skip_unsettable: bool = False) -> None:
491494
"""Loads the arguments in JSON format. Note: Due to JSON, tuples are loaded as lists.
492495
493496
:param path: Path to the JSON file where the arguments will be loaded from.
494497
:param check_reproducibility: When True, raises an error if the loaded reproducibility
495498
information doesn't match the current reproducibility information.
499+
:param skip_unsettable: When True, skips attributes that cannot be set in the Tap object,
500+
e.g. properties without setters.
496501
"""
497502
with open(path) as f:
498503
args_dict = json.load(f, object_hook=as_python_object)
@@ -528,7 +533,7 @@ def load(self, path: str, check_reproducibility: bool = False) -> None:
528533
raise ValueError(f'{no_reproducibility_message}: Uncommitted changes '
529534
f'in current args.')
530535

531-
self.from_dict(args_dict)
536+
self.from_dict(args_dict, skip_unsettable=skip_unsettable)
532537

533538
def __str__(self) -> str:
534539
"""Returns a string representation of self.

tests/test_integration.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,45 @@ def add_arguments(self) -> None:
955955
output = {'e': 7, 'f': {1}, 'd': ('a', 'b'), 'c': True, 'a': 'hi', 'b': 1, 'g': Person('tapper')}
956956
self.assertEqual(output, new_args.as_dict())
957957

958+
def test_save_load_property(self):
959+
class PropertySaveLoadTap(Tap):
960+
a: str = 'hello'
961+
962+
def __init__(self):
963+
super(PropertySaveLoadTap, self).__init__()
964+
self._prop1 = 1
965+
self._prop2 = 'hi'
966+
967+
@property
968+
def prop1(self):
969+
return self._prop1
970+
971+
@property
972+
def prop2(self):
973+
return self._prop2
974+
975+
@prop2.setter
976+
def prop2(self, prop2):
977+
self._prop2 = prop2
978+
979+
def process_args(self) -> None:
980+
self._prop1 = 2
981+
self.prop2 = 'bye'
982+
983+
args = PropertySaveLoadTap().parse_args([])
984+
985+
with NamedTemporaryFile() as f:
986+
args.save(f.name)
987+
new_args = PropertySaveLoadTap()
988+
989+
with self.assertRaises(AttributeError):
990+
new_args.load(f.name) # because trying to set unsettable prop1
991+
992+
new_args.load(f.name, skip_unsettable=True)
993+
994+
output = {'a': 'hello', 'prop1': 1, 'prop2': 'bye'}
995+
self.assertEqual(output, new_args.as_dict())
996+
958997

959998
class TestDeepCopy(TestCase):
960999
def test_deep_copy(self):

0 commit comments

Comments
 (0)