def test_refcounts(self) -> None: # create the model x_field = StructuredModel.define_field("x", StructuredModel.INT) y_field = StructuredModel.define_field("y", StructuredModel.INT) record = StructuredModel.define_record("R", [x_field, y_field]) array = StructuredModel.define_array(record) schema = StructuredModel.define_record( "A", [StructuredModel.define_field("a", array)]) model = StructuredModel.build_model( schema, value={"a": [{ "x": 1, "y": 2 }, { "x": 3, "y": 4 }]}) # change the model model.a[1].x = 33 del model.a[0] model.a.insert( 1, StructuredModel.build_model(record, value={ "x": -1, "y": -2 })) # check ref counts model_ref = weakref.ref(model) del model self.assertIsNone(model_ref())
def test_change_array_records_value_generates_model_changed(self) -> None: x_field = StructuredModel.define_field("x", StructuredModel.INT) y_field = StructuredModel.define_field("y", StructuredModel.INT) record = StructuredModel.define_record("A", [x_field, y_field]) schema = StructuredModel.define_array(record) model = StructuredModel.build_model(schema, value=[{ "x": 1, "y": 2 }, { "x": 3, "y": 4 }]) changed_ref = [0] def property_changed() -> None: changed_ref[0] += 1 with contextlib.closing( model.model_changed_event.listen(property_changed)): self.assertEqual(0, changed_ref[0]) model.insert_item( 1, StructuredModel.build_model(record, value={ "x": 5, "y": 6 })) self.assertEqual(1, changed_ref[0]) model.items[1].x = 55 self.assertEqual(2, changed_ref[0])
def test_refcounts_after_record_and_apply(self) -> None: # create the model x_field = StructuredModel.define_field("x", StructuredModel.INT) y_field = StructuredModel.define_field("y", StructuredModel.INT) record = StructuredModel.define_record("R", [x_field, y_field]) array = StructuredModel.define_array(record) schema = StructuredModel.define_record("A", [StructuredModel.define_field("a", array)]) model = StructuredModel.build_model(schema, value={"a": [{"x": 1, "y": 2}, {"x": 3, "y": 4}]}) # create recorder r = Recorder.Recorder(model) # change the model model_copy = copy.deepcopy(model) model.a[1].x = 33 del model.a[0] model.a.insert(1, StructuredModel.build_model(record, value={"x": -1, "y": -2})) # confirm changes self.assertEqual(33, model.a[0].x) self.assertEqual(-2, model.a[1].y) # confirm copy self.assertEqual(1, model_copy.a[0].x) self.assertEqual(4, model_copy.a[1].y) r.apply(model_copy) self.assertEqual(33, model_copy.a[0].x) self.assertEqual(-2, model_copy.a[1].y) # check recorder refcount r_ref = weakref.ref(r) del r self.assertIsNone(r_ref())
def get_settings_model(self, hardware_source): for instance in self.__instances: if instance.video_device == hardware_source.video_device: fields = [ StructuredModel.define_field("driver", StructuredModel.STRING), StructuredModel.define_field("device_id", StructuredModel.STRING), StructuredModel.define_field("name", StructuredModel.STRING), ] values = { "driver": instance.settings.get("driver", None), "device_id": instance.video_device.camera_id, "name": instance.video_device.camera_name, } for setting_description in instance.video_device_factory.describe_settings( ): setting_name = setting_description["name"] fields.append( StructuredModel.define_field( setting_name, setting_description["type"])) setting_value = instance.settings.get(setting_name, None) if setting_value is not None: values[setting_name] = setting_value schema = StructuredModel.define_record("settings", fields) model = StructuredModel.build_model(schema, value=values) return model return None
def __init__(self): self._event_loop = None # this will be injected by declarative UI engine # create a structured model by building a schema and then using the schema to create a structured model object. mode_title_field = StructuredModel.define_field( "title", StructuredModel.STRING) mode_balance_field = StructuredModel.define_field("balance", StructuredModel.INT, default=0) mode_schema = StructuredModel.define_record( "Mode", [mode_title_field, mode_balance_field]) mode_index_field = StructuredModel.define_field("mode_index", StructuredModel.INT, default=1) modes_field = StructuredModel.define_field( "modes", StructuredModel.define_array(mode_schema)) schema = StructuredModel.define_record("Configuration", [mode_index_field, modes_field]) # import pprint # print(pprint.pformat(schema)) self.model = StructuredModel.build_model(schema) # the title model is used for adding new modes. it is not part of the structured model. self.title_model = Model.PropertyModel() # the mode titles model is a property containing a list of mode titles. it is not part of the structured # model, but needs to be rebuilt when the list of modes in the model changes. add a listener for items # inserted/removed events and rebuild the mode titles model when those events are fired. self.mode_titles_model = Model.PropertyModel( [mode.title for mode in self.model.modes]) def modes_changed(k, v, i): if k == "modes": self.mode_titles_model.value = [ mode.title for mode in self.model.modes ] self.__modes_item_inserted_listener = self.model.item_inserted_event.listen( modes_changed) self.__modes_item_removed_listener = self.model.item_removed_event.listen( modes_changed) # add some initial modes self.model.modes.append( StructuredModel.build_model(mode_schema, value={"title": "One"})) self.model.modes.append( StructuredModel.build_model(mode_schema, value={"title": "Two"}))
def test_array_of_records_defaults_for_new_records(self) -> None: # test that building a model with defaults properly populates the defaults x_field = StructuredModel.define_field("x", StructuredModel.INT, default=1) y_field = StructuredModel.define_field("y", StructuredModel.INT, default=2) record = StructuredModel.define_record("A", [x_field, y_field]) model = StructuredModel.build_model(record) self.assertEqual(1, model.x) self.assertEqual(2, model.y)
def test_record_with_array_defaults(self) -> None: # test that a record with an array field can be initialized with default values array_field = StructuredModel.define_field( "a", StructuredModel.define_array(StructuredModel.INT)) record = StructuredModel.define_record("R", [array_field]) record_field = StructuredModel.define_field("r", record, default={"a": [3, 4, 5]}) schema = StructuredModel.define_record("Z", [record_field]) model = StructuredModel.build_model(schema) self.assertEqual(3, len(model.r.a)) self.assertEqual(4, model.r.a[1]) self.assertEqual(5, model.r.a[2])
def test_copy_record_produces_copy(self) -> None: x_field = StructuredModel.define_field("x", StructuredModel.INT) y_field = StructuredModel.define_field("y", StructuredModel.INT) schema = StructuredModel.define_record("A", [x_field, y_field]) model = StructuredModel.build_model(schema, value={"x": 1, "y": 2}) model_copy = copy.deepcopy(model) self.assertEqual(model.x, model_copy.x) self.assertEqual(model.y, model_copy.y) model.x = 4 self.assertNotEqual(model.x, model_copy.x) self.assertEqual(model.y, model_copy.y) model.copy_from(model_copy) self.assertEqual(model.x, model_copy.x) self.assertEqual(model.y, model_copy.y)
def test_refcounts(self) -> None: # create the model x_field = StructuredModel.define_field("x", StructuredModel.INT) y_field = StructuredModel.define_field("y", StructuredModel.INT) record = StructuredModel.define_record("R", [x_field, y_field]) array = StructuredModel.define_array(record) schema = StructuredModel.define_record("A", [StructuredModel.define_field("a", array)]) model = StructuredModel.build_model(schema, value={"a": [{"x": 1, "y": 2}, {"x": 3, "y": 4}]}) # create recorder r = Recorder.Recorder(model) # check recorder refcount r_ref = weakref.ref(r) del r self.assertIsNone(r_ref())
def test_observer_item_sequence_filter(self): # configure the model array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) # build the observer oo = Observer.ObserverBuilder() predicate = lambda x: not x.startswith("a") oo.source(model).ordered_sequence_from_array("a").filter(predicate) with contextlib.closing( typing.cast(Observer.AbstractItemSequenceSource, oo.make_observable())) as o: # check the observer functionality self.assertEqual(["b", "c"], o.items) # a, b, c model.a.insert(1, "a-b") self.assertEqual(["b", "c"], o.items) # a, a-b, b, c model.a.insert(0, "b-a") self.assertEqual(["b-a", "b", "c"], o.items) # b-a, a, a-b, b, c del model.a[1] self.assertEqual(["b-a", "b", "c"], o.items) # b-a, a-b, b, c del model.a[2] self.assertEqual(["b-a", "c"], o.items) # b-a, a-b, c
def test_observer_item_tuple(self): # configure the model str_field = StructuredModel.define_field("s", StructuredModel.STRING, default="ss") number_field = StructuredModel.define_field("n", StructuredModel.INT, default=10) schema = StructuredModel.define_record("R", [str_field, number_field]) model = StructuredModel.build_model(schema) # build the observer oo = Observer.ObserverBuilder() oo.source(model).tuple(oo.x.prop("s"), oo.x.prop("n")) with contextlib.closing(oo.make_observable()) as o: # check the observer functionality self.assertEqual(("ss", 10), o.item) model.s = "tt" self.assertEqual(("tt", 10), o.item) model.n = 4 self.assertEqual(("tt", 4), o.item)
def test_get_record_array_property(self) -> None: # test that a record gives access to a array value directly through a property on the record array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) self.assertIsInstance(model.a, collections.abc.Sequence)
def test_observer_item_ordered_sequence_len(self): # configure the model array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) # build the observer length = 0 def len_changed(new_length: Observer.ItemValue) -> None: nonlocal length length = new_length oo = Observer.ObserverBuilder() oo.source(model).ordered_sequence_from_array("a").map( oo.x.transform(lambda x: x.upper())).len().action_fn(len_changed) with contextlib.closing(oo.make_observable()) as o: # check the observer functionality # items will be ordered self.assertEqual(3, length) model.a.insert(1, "a-b") self.assertEqual(4, length) del model.a[0] self.assertEqual(3, length)
def test_observer_action(self): # configure the model str_field = StructuredModel.define_field("s", StructuredModel.STRING, default="ss") schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) # build the observer value = "" class Action(Observer.AbstractAction): def __init__(self, item_value): nonlocal value value = item_value def close(self): pass oo = Observer.ObserverBuilder() oo.source(model).prop("s").action(Action) with contextlib.closing(oo.make_observable()) as o: # check the observer functionality self.assertEqual("ss", value) model.s = "tt" self.assertEqual("tt", value)
def test_observer_item_sequence_for_each(self): # configure the model array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) # build the observer values = list() class Action(Observer.AbstractAction): def __init__(self, item_value): nonlocal values values.append(item_value) def close(self): pass oo = Observer.ObserverBuilder() oo.source(model).sequence_from_array("a").for_each(oo.x.action(Action)) with contextlib.closing( typing.cast(Observer.AbstractItemSequenceSource, oo.make_observable())) as o: # check the observer functionality # items will be unordered self.assertEqual(["a", "b", "c"], values) model.a.insert(1, "a-b") self.assertEqual(["a", "b", "c", "a-b"], values)
def test_get_record_property(self) -> None: # test that a record gives access to a field value directly through a property on the record str_field = StructuredModel.define_field("s", StructuredModel.STRING, default="ss") schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) self.assertEqual("ss", model.s)
def test_setting_value_in_array_raises_exception(self) -> None: array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) with self.assertRaises(IndexError): model.a[0] = "A"
def test_get_record_array_model(self) -> None: # test that a record gives access to a array model through a property on the record with _model suffix array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) self.assertIsInstance(model.a_model, StructuredModel.ArrayModel)
def test_str_array_defaults(self) -> None: # test that an array of simple fields (str) can be initialized with default values array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) self.assertSequenceEqual(["a", "b", "c"], model.a)
def test_array_of_records_defaults(self) -> None: # test that an array of record fields can be initialized with default values x_field = StructuredModel.define_field("x", StructuredModel.INT) y_field = StructuredModel.define_field("y", StructuredModel.INT) record = StructuredModel.define_record("A", [x_field, y_field]) array_field = StructuredModel.define_array(record) str_field = StructuredModel.define_field("a", array_field, default=[{ "x": 1, "y": 2 }, { "x": 3, "y": 4 }]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) self.assertEqual(2, len(model.a)) self.assertEqual(1, model.a[0].x) self.assertEqual(4, model.a[1].y)
def test_change_record_record_value_generates_model_changed(self) -> None: x_field = StructuredModel.define_field("x", StructuredModel.INT) y_field = StructuredModel.define_field("y", StructuredModel.INT) sub_record = StructuredModel.define_record("A", [x_field, y_field]) sub_field = StructuredModel.define_field("a", sub_record) schema = StructuredModel.define_record("B", [sub_field]) model = StructuredModel.build_model(schema, value={"a": { "x": 1, "y": 2 }}) changed_ref = [0] def property_changed() -> None: changed_ref[0] += 1 with contextlib.closing( model.model_changed_event.listen(property_changed)): self.assertEqual(0, changed_ref[0]) model.a.x = 11 self.assertEqual(1, changed_ref[0])
def __init__(self) -> None: site_field = StructuredModel.define_field("site", StructuredModel.STRING) instrument_field = StructuredModel.define_field( "instrument", StructuredModel.STRING) task_field = StructuredModel.define_field("task", StructuredModel.STRING) microscopist_field = StructuredModel.define_field( "microscopist", StructuredModel.STRING) sample_field = StructuredModel.define_field("sample", StructuredModel.STRING) sample_area_field = StructuredModel.define_field( "sample_area", StructuredModel.STRING) schema = StructuredModel.define_record("SessionMetadata", [ site_field, instrument_field, task_field, microscopist_field, sample_field, sample_area_field ]) self.__model = StructuredModel.build_model(schema, value=get_data().get( "session_metadata", dict())) def model_changed() -> None: data = get_data() data["session_metadata"] = self.__model.to_dict_value() set_data(data) self.__model_changed_listener = self.__model.model_changed_event.listen( model_changed)
def test_observer_item_constant(self): # configure the model str_field = StructuredModel.define_field("s", StructuredModel.STRING, default="ss") schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) # build the observer oo = Observer.ObserverBuilder() oo.source(model).prop("s").constant("N/A") with contextlib.closing(oo.make_observable()) as o: # check the observer functionality self.assertEqual("N/A", o.item) model.s = "tt" self.assertEqual("N/A", o.item)
def test_copy_array_produces_copy(self) -> None: x_field = StructuredModel.define_field("x", StructuredModel.INT) y_field = StructuredModel.define_field("y", StructuredModel.INT) record = StructuredModel.define_record("A", [x_field, y_field]) schema = StructuredModel.define_array(record) model = StructuredModel.build_model(schema, value=[{ "x": 1, "y": 2 }, { "x": 3, "y": 4 }]) model_copy = copy.deepcopy(model) self.assertEqual(len(model.items), len(model_copy.items)) self.assertEqual(model.items[1].x, model_copy.items[1].x) self.assertEqual(model.items[1].y, model_copy.items[1].y) model.items[1].x = 5 self.assertNotEqual(model.items[1].x, model_copy.items[1].x) self.assertEqual(model.items[1].y, model_copy.items[1].y) model.copy_from(model_copy) self.assertEqual(len(model.items), len(model_copy.items)) self.assertEqual(model.items[1].x, model_copy.items[1].x) self.assertEqual(model.items[1].y, model_copy.items[1].y)
def test_observer_item_array(self): # configure the model array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) # build the observer oo = Observer.ObserverBuilder() oo.source(model).array("a") with contextlib.closing(oo.make_observable()) as o: # check the observer functionality self.assertEqual(["a", "b", "c"], o.item) model.a.insert(1, "a-b") self.assertEqual(["a", "a-b", "b", "c"], o.item) del model.a[2] self.assertEqual(["a", "a-b", "c"], o.item)
def test_observer_item_array_sequence(self): # configure the model array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) # build the observer oo = Observer.ObserverBuilder() oo.source(model).sequence_from_array("a") with contextlib.closing(typing.cast(Observer.AbstractItemSequenceSource, oo.make_observable())) as o: # check the observer functionality # items will be unordered self.assertEqual(["a", "b", "c"], o.items) model.a.insert(1, "a-b") self.assertEqual(["a", "b", "c", "a-b"], o.items) del model.a[0] self.assertEqual(["b", "c", "a-b"], o.items)
def test_observer_item_sequence_index(self): # configure the model array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) # build the observer oo = Observer.ObserverBuilder() oo.source(model).ordered_sequence_from_array("a").map(oo.x.transform(lambda x: x.upper())).index(0) with contextlib.closing(oo.make_observable()) as o: # check the observer functionality # items will be ordered self.assertEqual("A", o.item) model.a.insert(1, "a-b") self.assertEqual("A", o.item) del model.a[0] self.assertEqual("A-B", o.item)
def test_set_record_property_fires_property_changed_event(self) -> None: str_field = StructuredModel.define_field("s", StructuredModel.STRING, default="ss") schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) was_property_changed_ref = [False] def handle_property_changed(name: str) -> None: self.assertEqual("s", name) was_property_changed_ref[0] = True with contextlib.closing( model.property_changed_event.listen(handle_property_changed)): self.assertFalse(was_property_changed_ref[0]) model.s = "tt" self.assertTrue(was_property_changed_ref[0])
def test_removing_item_in_array_field_of_record_using_del_fires_item_removed_event( self): array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) was_item_removed_ref = [False] def handle_item_removed(key, value, before_index): self.assertEqual("a", key) self.assertEqual("b", value) self.assertEqual(1, before_index) was_item_removed_ref[0] = True with contextlib.closing( model.item_removed_event.listen(handle_item_removed)): self.assertFalse(was_item_removed_ref[0]) del model.a[1] self.assertTrue(was_item_removed_ref[0])
def test_inserting_item_in_array_field_of_record_using_insert_fires_item_inserted_event( self) -> None: array_field = StructuredModel.define_array(StructuredModel.STRING) str_field = StructuredModel.define_field("a", array_field, default=["a", "b", "c"]) schema = StructuredModel.define_record("R", [str_field]) model = StructuredModel.build_model(schema) was_item_inserted_ref = [False] def handle_item_inserted(key: str, value: typing.Any, before_index: int) -> None: self.assertEqual("a", key) self.assertEqual("bb", value) self.assertEqual(1, before_index) was_item_inserted_ref[0] = True with contextlib.closing( model.item_inserted_event.listen(handle_item_inserted)): self.assertFalse(was_item_inserted_ref[0]) model.a.insert(1, "bb") self.assertTrue(was_item_inserted_ref[0])