hydrus/hydrus/client/db/ClientDBTagDisplay.py

665 lines
30 KiB
Python

import collections
import itertools
import sqlite3
import time
import typing
from hydrus.core import HydrusConstants as HC
from hydrus.core import HydrusData
from hydrus.core import HydrusDBBase
from hydrus.core import HydrusExceptions
from hydrus.core import HydrusGlobals as HG
from hydrus.client import ClientConstants as CC
from hydrus.client import ClientSearch
from hydrus.client.db import ClientDBDefinitionsCache
from hydrus.client.db import ClientDBMaster
from hydrus.client.db import ClientDBModule
from hydrus.client.db import ClientDBServices
from hydrus.client.db import ClientDBTagParents
from hydrus.client.db import ClientDBTagSiblings
from hydrus.client.metadata import ClientTags
class ClientDBTagDisplay( ClientDBModule.ClientDBModule ):
def __init__(
self,
cursor: sqlite3.Cursor,
cursor_transaction_wrapper: HydrusDBBase.DBCursorTransactionWrapper,
modules_services: ClientDBServices.ClientDBMasterServices,
modules_tags: ClientDBMaster.ClientDBMasterTags,
modules_tags_local_cache: ClientDBDefinitionsCache.ClientDBCacheLocalTags,
modules_tag_siblings: ClientDBTagSiblings.ClientDBTagSiblings,
modules_tag_parents: ClientDBTagParents.ClientDBTagParents
):
self._cursor_transaction_wrapper = cursor_transaction_wrapper
self.modules_services = modules_services
self.modules_tags = modules_tags
self.modules_tags_local_cache = modules_tags_local_cache
self.modules_tag_parents = modules_tag_parents
self.modules_tag_siblings = modules_tag_siblings
ClientDBModule.ClientDBModule.__init__( self, 'client tag display', cursor )
def FilterChained( self, display_type, tag_service_id, tag_ids ) -> typing.Set[ int ]:
# we are not passing ideal_tag_ids here, but that's ok, we are testing sibling chains in one second
parents_chained_tag_ids = self.modules_tag_parents.FilterChained( display_type, tag_service_id, tag_ids )
unknown_tag_ids = set( tag_ids ).difference( parents_chained_tag_ids )
sibling_chained_tag_ids = self.modules_tag_siblings.FilterChained( display_type, tag_service_id, unknown_tag_ids )
chained_tag_ids = set( parents_chained_tag_ids ).union( sibling_chained_tag_ids )
return chained_tag_ids
def GeneratePredicatesFromTagIdsAndCounts( self, tag_display_type: int, display_tag_service_id: int, tag_ids_to_full_counts, inclusive, job_key = None ):
tag_ids = set( tag_ids_to_full_counts.keys() )
predicates = []
if tag_display_type == ClientTags.TAG_DISPLAY_STORAGE:
if display_tag_service_id != self.modules_services.combined_tag_service_id:
tag_ids_to_ideal_tag_ids = self.modules_tag_siblings.GetTagIdsToIdealTagIds( ClientTags.TAG_DISPLAY_ACTUAL, display_tag_service_id, tag_ids )
tag_ids_that_are_sibling_chained = self.modules_tag_siblings.FilterChained( ClientTags.TAG_DISPLAY_ACTUAL, display_tag_service_id, tag_ids )
tag_ids_to_ideal_tag_ids_for_siblings = { tag_id : ideal_tag_id for ( tag_id, ideal_tag_id ) in tag_ids_to_ideal_tag_ids.items() if tag_id in tag_ids_that_are_sibling_chained }
ideal_tag_ids_to_sibling_chain_tag_ids = self.modules_tag_siblings.GetIdealTagIdsToChains( ClientTags.TAG_DISPLAY_ACTUAL, display_tag_service_id, set( tag_ids_to_ideal_tag_ids_for_siblings.values() ) )
#
ideal_tag_ids = set( tag_ids_to_ideal_tag_ids.values() )
ideal_tag_ids_that_are_parent_chained = self.modules_tag_parents.FilterChained( ClientTags.TAG_DISPLAY_ACTUAL, display_tag_service_id, ideal_tag_ids )
tag_ids_to_ideal_tag_ids_for_parents = { tag_id : ideal_tag_id for ( tag_id, ideal_tag_id ) in tag_ids_to_ideal_tag_ids.items() if ideal_tag_id in ideal_tag_ids_that_are_parent_chained }
ideal_tag_ids_to_ancestor_tag_ids = self.modules_tag_parents.GetTagsToAncestors( ClientTags.TAG_DISPLAY_ACTUAL, display_tag_service_id, set( tag_ids_to_ideal_tag_ids_for_parents.values() ) )
else:
# shouldn't ever happen with storage display
tag_ids_to_ideal_tag_ids_for_siblings = {}
tag_ids_to_ideal_tag_ids_for_parents = {}
ideal_tag_ids_to_sibling_chain_tag_ids = {}
ideal_tag_ids_to_ancestor_tag_ids = {}
tag_ids_we_want_to_look_up = set( tag_ids )
tag_ids_we_want_to_look_up.update( itertools.chain.from_iterable( ideal_tag_ids_to_sibling_chain_tag_ids.values() ) )
tag_ids_we_want_to_look_up.update( itertools.chain.from_iterable( ideal_tag_ids_to_ancestor_tag_ids.values() ) )
if job_key is not None and job_key.IsCancelled():
return []
tag_ids_to_tags = self.modules_tags_local_cache.GetTagIdsToTags( tag_ids = tag_ids_we_want_to_look_up )
if job_key is not None and job_key.IsCancelled():
return []
ideal_tag_ids_to_chain_tags = { ideal_tag_id : { tag_ids_to_tags[ chain_tag_id ] for chain_tag_id in chain_tag_ids } for ( ideal_tag_id, chain_tag_ids ) in ideal_tag_ids_to_sibling_chain_tag_ids.items() }
ideal_tag_ids_to_ancestor_tags = { ideal_tag_id : { tag_ids_to_tags[ ancestor_tag_id ] for ancestor_tag_id in ancestor_tag_ids } for ( ideal_tag_id, ancestor_tag_ids ) in ideal_tag_ids_to_ancestor_tag_ids.items() }
for ( tag_id, ( min_current_count, max_current_count, min_pending_count, max_pending_count ) ) in tag_ids_to_full_counts.items():
tag = tag_ids_to_tags[ tag_id ]
predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_TAG, value = tag, inclusive = inclusive, count = ClientSearch.PredicateCount( min_current_count, min_pending_count, max_current_count, max_pending_count ) )
if tag_id in tag_ids_to_ideal_tag_ids_for_siblings:
ideal_tag_id = tag_ids_to_ideal_tag_ids_for_siblings[ tag_id ]
if ideal_tag_id != tag_id:
predicate.SetIdealSibling( tag_ids_to_tags[ ideal_tag_id ] )
predicate.SetKnownSiblings( ideal_tag_ids_to_chain_tags[ ideal_tag_id ] )
if tag_id in tag_ids_to_ideal_tag_ids_for_parents:
ideal_tag_id = tag_ids_to_ideal_tag_ids_for_parents[ tag_id ]
parents = ideal_tag_ids_to_ancestor_tags[ ideal_tag_id ]
if len( parents ) > 0:
predicate.SetKnownParents( parents )
predicates.append( predicate )
elif tag_display_type == ClientTags.TAG_DISPLAY_ACTUAL:
tag_ids_to_known_chain_tag_ids = collections.defaultdict( set )
if display_tag_service_id == self.modules_services.combined_tag_service_id:
search_tag_service_ids = self.modules_services.GetServiceIds( HC.REAL_TAG_SERVICES )
else:
search_tag_service_ids = ( display_tag_service_id, )
for search_tag_service_id in search_tag_service_ids:
tag_ids_that_are_sibling_chained = self.modules_tag_siblings.FilterChained( ClientTags.TAG_DISPLAY_ACTUAL, search_tag_service_id, tag_ids )
tag_ids_to_ideal_tag_ids_for_siblings = self.modules_tag_siblings.GetTagIdsToIdealTagIds( ClientTags.TAG_DISPLAY_ACTUAL, search_tag_service_id, tag_ids_that_are_sibling_chained )
ideal_tag_ids = set( tag_ids_to_ideal_tag_ids_for_siblings.values() )
ideal_tag_ids_to_sibling_chain_tag_ids = self.modules_tag_siblings.GetIdealTagIdsToChains( ClientTags.TAG_DISPLAY_ACTUAL, search_tag_service_id, ideal_tag_ids )
for ( tag_id, ideal_tag_id ) in tag_ids_to_ideal_tag_ids_for_siblings.items():
tag_ids_to_known_chain_tag_ids[ tag_id ].update( ideal_tag_ids_to_sibling_chain_tag_ids[ ideal_tag_id ] )
tag_ids_we_want_to_look_up = set( tag_ids ).union( itertools.chain.from_iterable( tag_ids_to_known_chain_tag_ids.values() ) )
if job_key is not None and job_key.IsCancelled():
return []
tag_ids_to_tags = self.modules_tags_local_cache.GetTagIdsToTags( tag_ids = tag_ids_we_want_to_look_up )
if job_key is not None and job_key.IsCancelled():
return []
for ( tag_id, ( min_current_count, max_current_count, min_pending_count, max_pending_count ) ) in tag_ids_to_full_counts.items():
tag = tag_ids_to_tags[ tag_id ]
predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_TAG, value = tag, inclusive = inclusive, count = ClientSearch.PredicateCount( min_current_count, min_pending_count, max_current_count, max_pending_count ) )
if tag_id in tag_ids_to_known_chain_tag_ids:
chain_tags = { tag_ids_to_tags[ chain_tag_id ] for chain_tag_id in tag_ids_to_known_chain_tag_ids[ tag_id ] }
predicate.SetKnownSiblings( chain_tags )
predicates.append( predicate )
return predicates
def GetApplication( self ):
service_keys_to_sibling_applicable_service_keys = self.modules_tag_siblings.GetApplication()
service_keys_to_parent_applicable_service_keys = self.modules_tag_parents.GetApplication()
return ( service_keys_to_sibling_applicable_service_keys, service_keys_to_parent_applicable_service_keys )
def GetApplicationStatus( self, service_id ):
( sibling_rows_to_add, sibling_rows_to_remove, num_actual_sibling_rows, num_ideal_sibling_rows ) = self.modules_tag_siblings.GetApplicationStatus( service_id )
( parent_rows_to_add, parent_rows_to_remove, num_actual_parent_rows, num_ideal_parent_rows ) = self.modules_tag_parents.GetApplicationStatus( service_id )
num_actual_rows = num_actual_sibling_rows + num_actual_parent_rows
num_ideal_rows = num_ideal_sibling_rows + num_ideal_parent_rows
return ( sibling_rows_to_add, sibling_rows_to_remove, parent_rows_to_add, parent_rows_to_remove, num_actual_rows, num_ideal_rows )
def GetApplicableServiceIds( self, tag_service_id ) -> typing.Set[ int ]:
return set( self.modules_tag_siblings.GetApplicableServiceIds( tag_service_id ) ).union( self.modules_tag_parents.GetApplicableServiceIds( tag_service_id ) )
def GetChainsMembers( self, display_type, tag_service_id, tag_ids ) -> typing.Set[ int ]:
# all parent definitions are sibling collapsed, so are terminus of their sibling chains
# so get all of the parent chain, then get all chains that point to those
ideal_tag_ids = self.modules_tag_siblings.GetIdealTagIds( display_type, tag_service_id, tag_ids )
parent_chain_members = self.modules_tag_parents.GetChainsMembers( display_type, tag_service_id, ideal_tag_ids )
sibling_chain_members = self.modules_tag_siblings.GetChainsMembersFromIdeals( display_type, tag_service_id, parent_chain_members )
return sibling_chain_members.union( parent_chain_members )
# ok revisit this sometime I guess but it needs work
'''
with self._MakeTemporaryIntegerTable( tag_ids, 'tag_id' ) as temp_tag_ids_table_name:
with self._MakeTemporaryIntegerTable( [], 'ideal_tag_id' ) as temp_ideal_tag_ids_table_name:
self.modules_tag_siblings.GetIdealTagIdsIntoTable( display_type, tag_service_id, temp_tag_ids_table_name, temp_ideal_tag_ids_table_name )
with self._MakeTemporaryIntegerTable( [], 'ideal_tag_id' ) as temp_parent_chain_members_table_name:
# this is actually not implemented LMAO
self.modules_tag_parents.GetChainsMembersTables( display_type, tag_service_id, temp_ideal_tag_ids_table_name, temp_parent_chain_members_table_name, 'ideal_tag_id' )
with self._MakeTemporaryIntegerTable( [], 'tag_id' ) as temp_chain_members_table_name:
self.modules_tag_siblings.GetChainsMembersFromIdealsTables( display_type, tag_service_id, temp_parent_chain_members_table_name, temp_chain_members_table_name )
return self._STS( self._Execute( 'SELECT tag_id FROM {};'.format( temp_chain_members_table_name ) ) )
'''
def GetImpliedBy( self, display_type, tag_service_id, tag_id ) -> typing.Set[ int ]:
ideal_tag_id = self.modules_tag_siblings.GetIdealTagId( display_type, tag_service_id, tag_id )
if ideal_tag_id == tag_id:
# this tag exists in display
# it is also implied by any descendant
# and any of its or those descendants' siblings
# these are all ideal siblings
self_and_descendant_ids = { tag_id }.union( self.modules_tag_parents.GetDescendants( display_type, tag_service_id, ideal_tag_id ) )
implication_ids = self.modules_tag_siblings.GetChainsMembersFromIdeals( display_type, tag_service_id, self_and_descendant_ids )
else:
# this tag does not exist in display
implication_ids = set()
return implication_ids
def GetImplies( self, display_type, tag_service_id, tag_id ) -> typing.Set[ int ]:
# a tag implies its ideal sibling and any ancestors
ideal_tag_id = self.modules_tag_siblings.GetIdealTagId( display_type, tag_service_id, tag_id )
implies = { ideal_tag_id }
implies.update( self.modules_tag_parents.GetAncestors( display_type, tag_service_id, ideal_tag_id ) )
return implies
def GetInterestedServiceIds( self, tag_service_id ) -> typing.Set[ int ]:
return set( self.modules_tag_siblings.GetInterestedServiceIds( tag_service_id ) ).union( self.modules_tag_parents.GetInterestedServiceIds( tag_service_id ) )
def GetMediaPredicates( self, tag_context: ClientSearch.TagContext, tags_to_counts, inclusive, job_key = None ):
if HG.autocomplete_delay_mode:
time_to_stop = HydrusData.GetNowFloat() + 3.0
while not HydrusData.TimeHasPassedFloat( time_to_stop ):
time.sleep( 0.1 )
if job_key.IsCancelled():
return []
display_tag_service_id = self.modules_services.GetServiceId( tag_context.display_service_key )
max_current_count = None
max_pending_count = None
tag_ids_to_full_counts = {}
showed_bad_tag_error = False
for ( i, ( tag, ( current_count, pending_count ) ) ) in enumerate( tags_to_counts.items() ):
try:
tag_id = self.modules_tags.GetTagId( tag )
except HydrusExceptions.TagSizeException:
if not showed_bad_tag_error:
showed_bad_tag_error = True
HydrusData.ShowText( 'Hey, you seem to have an invalid tag in view right now! Please run the \'repair invalid tags\' routine under the \'database\' menu asap!' )
continue
tag_ids_to_full_counts[ tag_id ] = ( current_count, max_current_count, pending_count, max_pending_count )
if i % 100 == 0:
if job_key is not None and job_key.IsCancelled():
return []
if job_key is not None and job_key.IsCancelled():
return []
predicates = self.GeneratePredicatesFromTagIdsAndCounts( ClientTags.TAG_DISPLAY_ACTUAL, display_tag_service_id, tag_ids_to_full_counts, inclusive, job_key = job_key )
return predicates
def GetSiblingsAndParentsForTags( self, tags ):
tag_services = self.modules_services.GetServices( HC.REAL_TAG_SERVICES )
service_keys = [ tag_service.GetServiceKey() for tag_service in tag_services ]
tags_to_service_keys_to_siblings_and_parents = {}
for tag in tags:
sibling_chain_members = { tag }
ideal_tag = tag
descendants = set()
ancestors = set()
tags_to_service_keys_to_siblings_and_parents[ tag ] = { service_key : ( sibling_chain_members, ideal_tag, descendants, ancestors ) for service_key in service_keys }
for service_key in service_keys:
tag_service_id = self.modules_services.GetServiceId( service_key )
existing_tags = { tag for tag in tags if self.modules_tags.TagExists( tag ) }
existing_tag_ids = { self.modules_tags.GetTagId( tag ) for tag in existing_tags }
tag_ids_to_ideal_tag_ids = self.modules_tag_siblings.GetTagIdsToIdealTagIds( ClientTags.TAG_DISPLAY_ACTUAL, tag_service_id, existing_tag_ids )
ideal_tag_ids = set( tag_ids_to_ideal_tag_ids.values() )
ideal_tag_ids_to_sibling_chain_ids = self.modules_tag_siblings.GetIdealTagIdsToChains( ClientTags.TAG_DISPLAY_ACTUAL, tag_service_id, ideal_tag_ids )
ideal_tag_ids_to_descendant_tag_ids = self.modules_tag_parents.GetTagsToDescendants( ClientTags.TAG_DISPLAY_ACTUAL, tag_service_id, ideal_tag_ids )
ideal_tag_ids_to_ancestor_tag_ids = self.modules_tag_parents.GetTagsToAncestors( ClientTags.TAG_DISPLAY_ACTUAL, tag_service_id, ideal_tag_ids )
all_tag_ids = set()
all_tag_ids.update( ideal_tag_ids_to_sibling_chain_ids.keys() )
all_tag_ids.update( itertools.chain.from_iterable( ideal_tag_ids_to_sibling_chain_ids.values() ) )
all_tag_ids.update( itertools.chain.from_iterable( ideal_tag_ids_to_descendant_tag_ids.values() ) )
all_tag_ids.update( itertools.chain.from_iterable( ideal_tag_ids_to_ancestor_tag_ids.values() ) )
tag_ids_to_tags = self.modules_tags_local_cache.GetTagIdsToTags( tag_ids = all_tag_ids )
for tag_id in existing_tag_ids:
ideal_tag_id = tag_ids_to_ideal_tag_ids[ tag_id ]
sibling_chain_ids = ideal_tag_ids_to_sibling_chain_ids[ ideal_tag_id ]
descendant_tag_ids = ideal_tag_ids_to_descendant_tag_ids[ ideal_tag_id ]
ancestor_tag_ids = ideal_tag_ids_to_ancestor_tag_ids[ ideal_tag_id ]
tag = tag_ids_to_tags[ tag_id ]
ideal_tag = tag_ids_to_tags[ ideal_tag_id ]
sibling_chain_members = { tag_ids_to_tags[ sibling_chain_id ] for sibling_chain_id in sibling_chain_ids }
descendants = { tag_ids_to_tags[ descendant_tag_id ] for descendant_tag_id in descendant_tag_ids }
ancestors = { tag_ids_to_tags[ ancestor_tag_id ] for ancestor_tag_id in ancestor_tag_ids }
tags_to_service_keys_to_siblings_and_parents[ tag ][ service_key ] = ( sibling_chain_members, ideal_tag, descendants, ancestors )
return tags_to_service_keys_to_siblings_and_parents
def GetTablesAndColumnsThatUseDefinitions( self, content_type: int ) -> typing.List[ typing.Tuple[ str, str ] ]:
return []
def GetTagsToImpliedBy( self, display_type, tag_service_id, tag_ids, tags_are_ideal = False ):
tag_ids_to_implied_by = collections.defaultdict( set )
if tags_are_ideal:
tag_ids_that_exist_in_display = set( tag_ids )
else:
tag_ids_to_ideals = self.modules_tag_siblings.GetTagIdsToIdealTagIds( display_type, tag_service_id, tag_ids )
tag_ids_that_exist_in_display = set()
for ( tag_id, ideal_tag_id ) in tag_ids_to_ideals.items():
if tag_id == ideal_tag_id:
tag_ids_that_exist_in_display.add( ideal_tag_id )
else:
# this tag does not exist in display
tag_ids_to_implied_by[ tag_id ] = set()
# tags are implied by descendants, and their siblings
tag_ids_to_descendants = self.modules_tag_parents.GetTagsToDescendants( display_type, tag_service_id, tag_ids_that_exist_in_display )
all_tags_and_descendants = set( tag_ids_that_exist_in_display )
all_tags_and_descendants.update( itertools.chain.from_iterable( tag_ids_to_descendants.values() ) )
# these are all ideal_tag_ids
all_tags_and_descendants_to_chains = self.modules_tag_siblings.GetIdealTagIdsToChains( display_type, tag_service_id, all_tags_and_descendants )
for ( tag_id, descendants ) in tag_ids_to_descendants.items():
implications = set( itertools.chain.from_iterable( ( all_tags_and_descendants_to_chains[ descendant ] for descendant in descendants ) ) )
implications.update( all_tags_and_descendants_to_chains[ tag_id ] )
tag_ids_to_implied_by[ tag_id ] = implications
return tag_ids_to_implied_by
def GetTagsToImplies( self, display_type, tag_service_id, tag_ids ):
# a tag implies its ideal sibling and any ancestors
tag_ids_to_implies = collections.defaultdict( set )
tag_ids_to_ideals = self.modules_tag_siblings.GetTagIdsToIdealTagIds( display_type, tag_service_id, tag_ids )
ideal_tag_ids = set( tag_ids_to_ideals.values() )
ideal_tag_ids_to_ancestors = self.modules_tag_parents.GetTagsToAncestors( display_type, tag_service_id, ideal_tag_ids )
for ( tag_id, ideal_tag_id ) in tag_ids_to_ideals.items():
implies = { ideal_tag_id }
implies.update( ideal_tag_ids_to_ancestors[ ideal_tag_id ] )
tag_ids_to_implies[ tag_id ] = implies
return tag_ids_to_implies
def GetUIDecorators( self, service_key, tags ):
tags_to_display_decorators = { tag : None for tag in tags }
if service_key == CC.COMBINED_TAG_SERVICE_KEY:
return tags_to_display_decorators
tag_service_id = self.modules_services.GetServiceId( service_key )
existing_tags = { tag for tag in tags if self.modules_tags.TagExists( tag ) }
existing_tag_ids = { self.modules_tags.GetTagId( tag ) for tag in existing_tags }
existing_tag_ids_to_ideal_tag_ids = self.modules_tag_siblings.GetTagIdsToIdealTagIds( ClientTags.TAG_DISPLAY_ACTUAL, tag_service_id, existing_tag_ids )
ideal_tag_ids = set( existing_tag_ids_to_ideal_tag_ids.values() )
interesting_tag_ids_to_ideal_tag_ids = { tag_id : ideal_tag_id for ( tag_id, ideal_tag_id ) in existing_tag_ids_to_ideal_tag_ids.items() if tag_id != ideal_tag_id }
ideal_tag_ids_to_ancestor_tag_ids = self.modules_tag_parents.GetTagsToAncestors( ClientTags.TAG_DISPLAY_ACTUAL, tag_service_id, ideal_tag_ids )
existing_tag_ids_to_ancestor_tag_ids = { existing_tag_id : ideal_tag_ids_to_ancestor_tag_ids[ existing_tag_ids_to_ideal_tag_ids[ existing_tag_id ] ] for existing_tag_id in existing_tag_ids }
interesting_tag_ids_to_ancestor_tag_ids = { tag_id : ancestor_tag_ids for ( tag_id, ancestor_tag_ids ) in existing_tag_ids_to_ancestor_tag_ids.items() if len( ancestor_tag_ids ) > 0 }
all_interesting_tag_ids = set()
all_interesting_tag_ids.update( interesting_tag_ids_to_ideal_tag_ids.keys() )
all_interesting_tag_ids.update( interesting_tag_ids_to_ideal_tag_ids.values() )
all_interesting_tag_ids.update( interesting_tag_ids_to_ancestor_tag_ids.keys() )
all_interesting_tag_ids.update( itertools.chain.from_iterable( interesting_tag_ids_to_ancestor_tag_ids.values() ) )
tag_ids_to_tags = self.modules_tags_local_cache.GetTagIdsToTags( tag_ids = all_interesting_tag_ids )
for tag_id in existing_tag_ids:
if tag_id in interesting_tag_ids_to_ideal_tag_ids:
ideal = tag_ids_to_tags[ interesting_tag_ids_to_ideal_tag_ids[ tag_id ] ]
else:
ideal = None
if tag_id in interesting_tag_ids_to_ancestor_tag_ids:
parents = { tag_ids_to_tags[ ancestor_tag_id ] for ancestor_tag_id in interesting_tag_ids_to_ancestor_tag_ids[ tag_id ] }
else:
parents = None
if ideal is not None or parents is not None:
tag = tag_ids_to_tags[ tag_id ]
tags_to_display_decorators[ tag ] = ( ideal, parents )
return tags_to_display_decorators
def IsChained( self, display_type, tag_service_id, tag_id ) -> bool:
return self.modules_tag_parents.IsChained( display_type, tag_service_id, tag_id ) or self.modules_tag_siblings.IsChained( display_type, tag_service_id, tag_id )
def NotifyParentsChanged( self, tag_service_id_that_changed, tag_ids_that_changed ):
if len( tag_ids_that_changed ) == 0:
return
# the parents for tag_ids have changed for tag_service_id
# therefore any service that is interested in tag_service_ids's parents needs to regen the respective chains for these tags
interested_tag_service_ids = self.modules_tag_parents.GetInterestedServiceIds( tag_service_id_that_changed )
self.modules_tag_parents.RegenChains( interested_tag_service_ids, tag_ids_that_changed )
def NotifySiblingsChanged( self, tag_service_id_that_changed, tag_ids_that_changed ):
if len( tag_ids_that_changed ) == 0:
return
# the siblings for tag_ids have changed for tag_service_id
# therefore any service that is interested in tag_service_ids's siblings needs to regen the respective chains for these tags
interested_tag_service_ids = self.modules_tag_siblings.GetInterestedServiceIds( tag_service_id_that_changed )
self.modules_tag_siblings.RegenChains( interested_tag_service_ids, tag_ids_that_changed )
# since siblings just changed, parents can as well! any interested service that has any of these tag_ids in its parent structure may need new ids, so let's regen
self.modules_tag_parents.RegenChains( interested_tag_service_ids, tag_ids_that_changed )
def RegenerateTagSiblingsAndParentsCache( self, only_these_service_ids = None ):
if only_these_service_ids is None:
tag_service_ids = self.modules_services.GetServiceIds( HC.REAL_TAG_SERVICES )
else:
tag_service_ids = only_these_service_ids
self.modules_tag_siblings.Regen( tag_service_ids )
# as siblings may have changed, parents may have as well
self.modules_tag_parents.Regen( tag_service_ids )
self._cursor_transaction_wrapper.pub_after_job( 'notify_new_tag_display_application' )
def SetApplication( self, service_keys_to_sibling_applicable_service_keys, service_keys_to_parent_applicable_service_keys ):
sibling_service_ids_to_sync = self.modules_tag_siblings.SetApplication( service_keys_to_sibling_applicable_service_keys )
parent_service_ids_to_sync = self.modules_tag_parents.SetApplication( service_keys_to_parent_applicable_service_keys )
service_ids_to_sync = sibling_service_ids_to_sync.union( parent_service_ids_to_sync )
#
self.RegenerateTagSiblingsAndParentsCache( only_these_service_ids = service_ids_to_sync )
self._cursor_transaction_wrapper.pub_after_job( 'notify_new_tag_display_application' )