def test_persistent_object_proxy_calls_listeners_once_during_lifecycle(self): r_count = 0 u_count = 0 def r(x): nonlocal r_count; r_count += 1 def u(x): nonlocal u_count; u_count += 1 persistent_object_context = Persistence.PersistentObjectContext() object0 = Persistence.PersistentObject() object1 = Persistence.PersistentObject() object1_proxy = object0.create_item_proxy(item_specifier=Persistence.PersistentObjectSpecifier.read(object1.uuid)) with contextlib.closing(object0), contextlib.closing(object1), contextlib.closing(object1_proxy): object1_proxy.on_item_registered = r object1_proxy.on_item_unregistered = u # register parent, but not child object0.persistent_object_context = persistent_object_context self.assertEqual(0, r_count) self.assertEqual(0, u_count) # now register child and ensure register was called object1.persistent_object_context = persistent_object_context self.assertEqual(object1, object1_proxy.item) self.assertEqual(1, r_count) self.assertEqual(0, u_count) # unregister child and ensure unregistered was called object1.persistent_object_context = None self.assertEqual(1, r_count) self.assertEqual(1, u_count)
def test_persistent_object_proxy_updates_when_registered(self): persistent_object_context = Persistence.PersistentObjectContext() object0 = Persistence.PersistentObject() object1 = Persistence.PersistentObject() object1_proxy = object0.create_item_proxy(item_specifier=Persistence.read_persistent_specifier(object1.uuid)) with contextlib.closing(object0), contextlib.closing(object1), contextlib.closing(object1_proxy): object0.persistent_object_context = persistent_object_context self.assertIsNone(object1_proxy.item) object1.persistent_object_context = persistent_object_context self.assertEqual(object1, object1_proxy.item)
def mime_data_get_data_source(mime_data: UserInterface.MimeData, document_model: DocumentModel.DocumentModel) -> typing.Tuple[typing.Optional[DisplayItem.DisplayItem], typing.Optional[Graphics.Graphic]]: display_item = None graphic = None if mime_data.has_format(DATA_SOURCE_MIME_TYPE): data_source_mime_data = json.loads(mime_data.data_as_string(DATA_SOURCE_MIME_TYPE)) display_item_specifier = Persistence.read_persistent_specifier(data_source_mime_data["display_item_specifier"]) display_item = typing.cast(typing.Optional[DisplayItem.DisplayItem], document_model.resolve_item_specifier(display_item_specifier)) if display_item_specifier else None if "graphic_specifier" in data_source_mime_data: graphic_specifier = Persistence.read_persistent_specifier(data_source_mime_data["graphic_specifier"]) graphic = typing.cast(typing.Optional[Graphics.Graphic], document_model.resolve_item_specifier(graphic_specifier)) if graphic_specifier else None return display_item, graphic
def create_specifier( self, item: Persistence.PersistentObject, *, allow_partial: bool = True ) -> Persistence.PersistentObjectSpecifier: if item.project == self and allow_partial: return Persistence.PersistentObjectSpecifier(item=item) else: return Persistence.PersistentObjectSpecifier(item=item, context=item.project)
def test_persistent_object_context_calls_register_when_object_becomes_registered(self): persistent_object_context = Persistence.PersistentObjectContext() object1 = Persistence.PersistentObject() with contextlib.closing(object1): was_registered = False def registered(registered_item, unregistered_item) -> None: nonlocal was_registered if registered_item == object1: was_registered = True with persistent_object_context.registration_event.listen(registered): persistent_object_context.register(object1) self.assertTrue(was_registered)
def test_persistent_object_context_does_not_trigger_event_on_already_registered_object(self): persistent_object_context = Persistence.PersistentObjectContext() object1 = Persistence.PersistentObject() with contextlib.closing(object1): persistent_object_context.register(object1) was_registered = False def registered(registered_item, unregistered_item) -> None: nonlocal was_registered if registered_item: was_registered = True with persistent_object_context.registration_event.listen(registered): self.assertFalse(was_registered)
def __init__( self, *, structure_type: typing.Optional[str] = None, source: typing.Optional[Persistence.PersistentObject] = None ) -> None: super().__init__() self.__properties: typing.Dict[str, typing.Any] = dict() self.__referenced_object_proxies: typing.Dict[ str, Persistence.PersistentObjectProxy[Persistence. PersistentObject]] = dict() self.define_type("data_structure") self.define_property("structure_type", structure_type, changed=self.__structure_type_changed, hidden=True) self.define_property("source_specifier", changed=self.__source_specifier_changed, key="source_uuid", hidden=True) # properties is handled explicitly self.data_structure_changed_event = Event.Event() self.data_structure_objects_changed_event = Event.Event() self.__source_reference = self.create_item_reference(item=source) self.source_specifier = Persistence.write_persistent_specifier( source.uuid) if source else None self.__entity: typing.Optional[Schema.Entity] = None self.__entity_property_changed_event_listener: typing.Optional[ Event.EventListener] = None self.__create_entity()
def mime_data_get_display_items(mime_data: UserInterface.MimeData, document_model: DocumentModel.DocumentModel) -> typing.List[DisplayItem.DisplayItem]: display_items : typing.List[DisplayItem.DisplayItem] = list() if mime_data.has_format(DISPLAY_ITEMS_MIME_TYPE): data_sources_mime_data = json.loads(mime_data.data_as_string(DISPLAY_ITEMS_MIME_TYPE)) for data_source_mime_data in data_sources_mime_data: display_item_specifier = Persistence.read_persistent_specifier(data_source_mime_data["display_item_specifier"]) display_item = typing.cast(typing.Optional[DisplayItem.DisplayItem], document_model.resolve_item_specifier(display_item_specifier)) if display_item_specifier else None if display_item: display_items.append(display_item) if mime_data.has_format(DISPLAY_ITEM_MIME_TYPE): data_source_mime_data = json.loads(mime_data.data_as_string(DISPLAY_ITEM_MIME_TYPE)) display_item_specifier = Persistence.read_persistent_specifier(data_source_mime_data["display_item_specifier"]) display_item = typing.cast(typing.Optional[DisplayItem.DisplayItem], document_model.resolve_item_specifier(display_item_specifier)) if display_item_specifier else None if display_item: display_items.append(display_item) return display_items
def mime_data_get_panel(mime_data: UserInterface.MimeData, document_model: DocumentModel.DocumentModel) -> typing.Tuple[typing.Optional[DisplayItem.DisplayItem], Persistence.PersistentDictType]: display_item = None d: Persistence.PersistentDictType = dict() if mime_data.has_format(DISPLAY_PANEL_MIME_TYPE): d = json.loads(mime_data.data_as_string(DISPLAY_PANEL_MIME_TYPE)) if "display_item_specifier" in d: display_item_specifier = Persistence.read_persistent_specifier(d["display_item_specifier"]) display_item = typing.cast(typing.Optional[DisplayItem.DisplayItem], document_model.resolve_item_specifier(display_item_specifier)) if display_item_specifier else None return display_item, d
def test_persistent_object_context_calls_unregister_when_object_becomes_unregistered( self): persistent_object_context = Persistence.PersistentObjectContext() object1 = Persistence.PersistentObject() was_registered = False def registered(registered_item, unregistered_item) -> None: nonlocal was_registered if registered_item == object1: was_registered = True if unregistered_item == object1: was_registered = False with persistent_object_context.registration_event.listen(registered): item_specifier1 = object1.item_specifier persistent_object_context.register(object1, item_specifier1) self.assertTrue(was_registered) persistent_object_context.unregister(object1, item_specifier1) self.assertFalse(was_registered)
def insert_display_item(self, before_index: int, display_item: DisplayItem.DisplayItem) -> None: assert display_item not in self.__display_items self.__display_items.insert(before_index, display_item) self.notify_insert_item("display_items", display_item, before_index) self.update_counted_display_items(collections.Counter([display_item])) display_item_specifiers = self.display_item_specifiers display_item_specifier = Persistence.write_persistent_specifier(display_item.uuid) assert display_item_specifier is not None display_item_specifiers.insert(before_index, display_item_specifier) self.display_item_specifiers = display_item_specifiers self.notify_property_changed("display_item_specifiers")
def __configure_reference_proxy( self, property_name: str, value: typing.Any, item: typing.Optional[Persistence.PersistentObject]) -> None: if isinstance(value, dict) and value.get("type") in { "data_item", "display_item", "data_source", "graphic", "structure" } and "uuid" in value: self.__referenced_object_proxies[ property_name] = self.create_item_proxy( item_specifier=Persistence.read_persistent_specifier( value["uuid"]), item=item)
def test_persistent_object_proxy_does_not_call_listener_when_removed_from_unregistered_parent( self): r_count = 0 u_count = 0 def r(x): nonlocal r_count r_count += 1 def u(x): nonlocal u_count u_count += 1 persistent_object_context = Persistence.PersistentObjectContext() object0 = Persistence.PersistentObject() object1 = Persistence.PersistentObject() object1_proxy = object0.create_item_proxy( item_specifier=Persistence.PersistentObjectSpecifier.read( object1.uuid)) with contextlib.closing(object1_proxy): object1_proxy.on_item_registered = r object1_proxy.on_item_unregistered = u object0.persistent_object_context = persistent_object_context # only parent has been registered self.assertEqual(0, r_count) self.assertEqual(0, u_count) object1.persistent_object_context = persistent_object_context # now object has been registered self.assertEqual(object1, object1_proxy.item) self.assertEqual(1, r_count) self.assertEqual(0, u_count) # unregistered parent first, then object object0.persistent_object_context = None object1.persistent_object_context = None self.assertEqual(1, r_count) self.assertEqual(0, u_count) # parent was already unregistered
def test_persistent_object_proxy_calls_listeners_when_initialized_with_object( self): r_count = 0 u_count = 0 def r(x): nonlocal r_count r_count += 1 def u(x): nonlocal u_count u_count += 1 persistent_object_context = Persistence.PersistentObjectContext() object0 = Persistence.PersistentObject() object1 = Persistence.PersistentObject() object1_proxy = object0.create_item_proxy(item=object1) object1_proxy.on_item_registered = r object1_proxy.on_item_unregistered = u with contextlib.closing(object1_proxy): # register parent and check initial conditions object0.persistent_object_context = persistent_object_context self.assertEqual(object1, object1_proxy.item) self.assertEqual(0, r_count) self.assertEqual(0, u_count) # register child which was already registered; confirm registered not called object1.persistent_object_context = persistent_object_context self.assertEqual( 0, r_count) # item never becomes registered; it starts registered self.assertEqual(0, u_count) # unregister works normal object1.persistent_object_context = None self.assertEqual(0, r_count) self.assertEqual(1, u_count)
def __init__( self, type: str, *, parent: typing.Optional[Persistence.PersistentObject] = None ) -> None: super().__init__() self.define_type(type) self.define_property("parent_specifier", changed=self.__parent_specifier_changed, key="parent_uuid", hidden=True) self.__parent_reference = self.create_item_reference(item=parent) self.parent_specifier = Persistence.write_persistent_specifier( parent.uuid) if parent else None
def mime_data_put_layer(mime_data: UserInterface.MimeData, index: int, display_item: DisplayItem.DisplayItem, label: typing.Optional[str], fill_color: typing.Optional[str], stroke_color: typing.Optional[str]) -> None: legend_data: Persistence.PersistentDictType = { "index": index, } if label: legend_data["label"] = label if fill_color: legend_data["fill_color"] = fill_color if stroke_color: legend_data["stroke_color"] = stroke_color mime_dict = { "legend_data": legend_data, "display_item_specifier": Persistence.write_persistent_specifier(display_item.uuid) } mime_data.set_data_as_string(LAYER_MIME_TYPE, json.dumps(mime_dict))
def test_deep_copy_should_not_deep_copy_data_items(self): with TestContext.create_memory_context() as test_context: document_model = test_context.create_document_model() data_group = DataGroup.DataGroup() document_model.append_data_group(data_group) data_item = DataItem.DataItem(numpy.zeros((8, 8), numpy.uint32)) document_model.append_data_item(data_item) display_item = document_model.get_display_item_for_data_item( data_item) data_group.append_display_item(display_item) data_group_copy = copy.deepcopy(data_group) document_model.append_data_group(data_group_copy) display_item_specifier = Persistence.read_persistent_specifier( data_group_copy.display_item_specifiers[0]) self.assertEqual( display_item, document_model.resolve_item_specifier(display_item_specifier))
def __init__(self, file_path): file_path = pathlib.Path(file_path) if file_path.suffix == ".nsproj": r = Profile.IndexProjectReference() r.project_path = file_path else: r = Profile.FolderProjectReference() r.project_folder_path = file_path r.persistent_object_context = Persistence.PersistentObjectContext() r.load_project(None) #r.project._raw_properties["version"] = 3 r.project.read_project() r.project.read_project() self.project = r.project self._data_items_properties = [ di.properties for di in self.project.data_items ]
def get_object_specifier( object: typing.Optional[Persistence.PersistentObject], object_type: typing.Optional[str] = None, project: typing.Optional[Project.Project] = None ) -> typing.Optional[Persistence.PersistentDictType]: # project is passed for testing only if isinstance(object, DataItem.DataItem): specifier = Persistence.PersistentObjectSpecifier(object.uuid) specifier_uuid = specifier.item_uuid if specifier else object.uuid d = { "version": 1, "type": object_type or "data_item", "uuid": str(specifier_uuid) } return d if object and object_type in ("xdata", "display_xdata", "cropped_xdata", "cropped_display_xdata", "filter_xdata", "filtered_xdata"): assert isinstance(object, DisplayItem.DisplayDataChannel) specifier = Persistence.PersistentObjectSpecifier(object.uuid) specifier_uuid = specifier.item_uuid if specifier else object.uuid d = {"version": 1, "type": object_type, "uuid": str(specifier_uuid)} return d if isinstance(object, DisplayItem.DisplayDataChannel): # should be "data_source" but requires file format change specifier = Persistence.PersistentObjectSpecifier(object.uuid) specifier_uuid = specifier.item_uuid if specifier else object.uuid d = {"version": 1, "type": "data_source", "uuid": str(specifier_uuid)} return d elif isinstance(object, Graphics.Graphic): specifier = Persistence.PersistentObjectSpecifier(object.uuid) specifier_uuid = specifier.item_uuid if specifier else object.uuid d = {"version": 1, "type": "graphic", "uuid": str(specifier_uuid)} return d elif isinstance(object, DataStructure): specifier = Persistence.PersistentObjectSpecifier(object.uuid) specifier_uuid = specifier.item_uuid if specifier else object.uuid d = {"version": 1, "type": "structure", "uuid": str(specifier_uuid)} return d elif isinstance(object, DisplayItem.DisplayItem): specifier = Persistence.PersistentObjectSpecifier(object.uuid) specifier_uuid = specifier.item_uuid if specifier else object.uuid d = {"version": 1, "type": "display_item", "uuid": str(specifier_uuid)} return d return None
def create_specifier( self, item: Persistence.PersistentObject ) -> Persistence.PersistentObjectSpecifier: return Persistence.PersistentObjectSpecifier(item=item)
def item_specifier(self) -> Persistence.PersistentObjectSpecifier: return Persistence.PersistentObjectSpecifier(item_uuid=self.uuid)
def __init__( self, source: typing.Optional[Persistence.PersistentObject] = None, source_property: typing.Optional[str] = None, target: typing.Optional[Persistence.PersistentObject] = None, target_property: typing.Optional[str] = None, *, parent: typing.Optional[Persistence.PersistentObject] = None ) -> None: super().__init__("property-connection", parent=parent) self.define_property("source_specifier", Persistence.write_persistent_specifier( source.uuid) if source else None, changed=self.__source_specifier_changed, key="source_uuid", hidden=True) self.define_property("source_property", hidden=True) self.define_property("target_specifier", Persistence.write_persistent_specifier( target.uuid) if target else None, changed=self.__target_specifier_changed, key="target_uuid", hidden=True) self.define_property("target_property", hidden=True) # these are only set in persistent object context changed self.__binding: typing.Optional[Binding.Binding] = None self.__target_property_changed_listener: typing.Optional[ Event.EventListener] = None self.__source_reference = self.create_item_reference(item=source) self.__target_reference = self.create_item_reference(item=target) # suppress messages while we're setting source or target self.__suppress = False # set up the proxies def configure_binding() -> None: if self._source and self._target: assert not self.__binding self.__binding = Binding.PropertyBinding( self._source, self.source_property) self.__binding.target_setter = self.__set_target_from_source # while reading, the data item in the display data channel will not be connected; # we still set its value here. when the data item becomes valid, it will update. self.__binding.update_target_direct( self.__binding.get_target_value()) def release_binding() -> None: if self.__binding: self.__binding.close() self.__binding = None if self.__target_property_changed_listener: self.__target_property_changed_listener.close() self.__target_property_changed_listener = None self.__source_reference.on_item_registered = lambda x: configure_binding( ) self.__source_reference.on_item_unregistered = lambda x: release_binding( ) def configure_target() -> None: def property_changed(target: typing.Optional[ Persistence.PersistentObject], property_name: str) -> None: if property_name == self.target_property: self.__set_source_from_target( getattr(target, property_name)) assert self.__target_property_changed_listener is None if self._target: self.__target_property_changed_listener = self._target.property_changed_event.listen( functools.partial(property_changed, self._target)) configure_binding() self.__target_reference.on_item_registered = lambda x: configure_target( ) self.__target_reference.on_item_unregistered = lambda x: release_binding( ) # but set up if we were passed objects if source is not None: self.__source_reference.item = source if source_property: self.source_property = source_property if target is not None: self.__target_reference.item = target if target_property: self.target_property = target_property if self._target: configure_target()
def mime_data_put_display_items(mime_data: UserInterface.MimeData, display_items: typing.Sequence[DisplayItem.DisplayItem]) -> None: mime_data_content = [{"display_item_specifier": Persistence.write_persistent_specifier(display_item.uuid)} for display_item in display_items] mime_data.set_data_as_string(DISPLAY_ITEMS_MIME_TYPE, json.dumps(mime_data_content))
def mime_data_put_display_item(mime_data: UserInterface.MimeData, display_item: DisplayItem.DisplayItem) -> None: mime_data_content = {"display_item_specifier": Persistence.write_persistent_specifier(display_item.uuid)} mime_data.set_data_as_string(DISPLAY_ITEM_MIME_TYPE, json.dumps(mime_data_content))
def source(self, source: typing.Optional[Persistence.PersistentObject]) -> None: self.__source_reference.item = source self.source_specifier = Persistence.write_persistent_specifier( source.uuid) if source else None
def mime_data_put_data_source(mime_data: UserInterface.MimeData, display_item: DisplayItem.DisplayItem, graphic: typing.Optional[Graphics.Graphic]) -> None: mime_data_content = dict() mime_data_content["display_item_specifier"] = Persistence.write_persistent_specifier(display_item.uuid) if graphic and graphic.project: mime_data_content["graphic_specifier"] = Persistence.write_persistent_specifier(graphic.uuid) mime_data.set_data_as_string(DATA_SOURCE_MIME_TYPE, json.dumps(mime_data_content))
def __source_specifier_changed(self, name: str, d: Persistence._SpecifierType) -> None: self.__source_reference.item_specifier = Persistence.read_persistent_specifier( d)
def mime_data_put_panel(mime_data: UserInterface.MimeData, display_item: typing.Optional[DisplayItem.DisplayItem], d: Persistence.PersistentDictType) -> None: if display_item: d = dict(d) d["display_item_specifier"] = Persistence.write_persistent_specifier(display_item.uuid) mime_data.set_data_as_string(DISPLAY_PANEL_MIME_TYPE, json.dumps(d))
def item_specifier(self) -> Persistence.PersistentObjectSpecifier: return Persistence.PersistentObjectSpecifier( item_uuid=self.uuid, context_uuid=self.profile.uuid)
def mime_data_get_layer(mime_data: UserInterface.MimeData, document_model: DocumentModel.DocumentModel) -> typing.Tuple[Persistence.PersistentDictType, typing.Optional[DisplayItem.DisplayItem]]: mime_dict = json.loads(mime_data.data_as_string(LAYER_MIME_TYPE)) legend_data = mime_dict["legend_data"] display_item_specifier = Persistence.read_persistent_specifier(mime_dict["display_item_specifier"]) display_item = typing.cast(typing.Optional[DisplayItem.DisplayItem], document_model.resolve_item_specifier(display_item_specifier)) if display_item_specifier else None return legend_data, display_item