Version 144
This commit is contained in:
parent
d05ba33fb9
commit
d13afc0285
|
@ -8,6 +8,30 @@
|
|||
<div class="content">
|
||||
<h3>changelog</h3>
|
||||
<ul>
|
||||
<li><h3>version 144</h3></li>
|
||||
<ul>
|
||||
<li>files named 'Thumbs.db' will now be skipped in the import files dialog</li>
|
||||
<li>fixed wildcard searches, which last week's predicate rewrite broke</li>
|
||||
<li>fixed a typo that was showing namespace predicates as exclusive (-series:*) when they were actually inclusive (series:*) and vice versa</li>
|
||||
<li>added wildcard namespace searching for database autocomplete queries</li>
|
||||
<li>fixed database wildcard autocomplete searching when wildcard match is not the first word in a tag</li>
|
||||
<li>fixed database file searching when wildcard match is not the first word in a tag</li>
|
||||
<li>added a comprehensive suite of predicate-unicode conversion tests</li>
|
||||
<li>cleaned and improved some of the downloader code</li>
|
||||
<li>added five second per-gallery-page delay to subscription daemon</li>
|
||||
<li>added three second per-file-delay for regular gallery downloads and subscriptions, just to be polite to those web services</li>
|
||||
<li>added three second per-file-delay to the thread watcher for the same reason</li>
|
||||
<li>added a 'check now' button to the thread watcher</li>
|
||||
<li>fixed a problem that was sometimes causing subscriptions, when paused, to continually restart</li>
|
||||
<li>removed unnamespaced tag parsing from deviant art</li>
|
||||
<li>fixed creator parsing for deviant art, which was formerly cutting off the first character</li>
|
||||
<li>patched an account sync problem in the manage tags dialog</li>
|
||||
<li>in add tags by path dialog, tags are now sorted before being added to the file list</li>
|
||||
<li>in add tags by path dialog, the regex sections now generate tags for every match in the string, not just the first</li>
|
||||
<li>stopped collapsible panels resizing dialogs to minsize on collapse or expand</li>
|
||||
<li>added shortcut for 'open externally', default Ctrl+E</li>
|
||||
<li>moved 8chan to new 8ch.net domain (old domain still works)</li>
|
||||
</ul>
|
||||
<li><h3>version 143</h3></li>
|
||||
<ul>
|
||||
<li>when making a READ autocomplete tag query, instances of tags that only have a count in a single namespaced domain will no longer accumulate helper results in the non-namespaced domain i.e. no more 'blah (1)' 'title:blah (1)' dupes</li>
|
||||
|
|
|
@ -262,6 +262,7 @@ shortcuts[ wx.ACCEL_CTRL ][ ord( 'M' ) ] = 'set_media_focus'
|
|||
shortcuts[ wx.ACCEL_CTRL ][ ord( 'I' ) ] = 'synchronised_wait_switch'
|
||||
shortcuts[ wx.ACCEL_CTRL ][ ord( 'Z' ) ] = 'undo'
|
||||
shortcuts[ wx.ACCEL_CTRL ][ ord( 'Y' ) ] = 'redo'
|
||||
shortcuts[ wx.ACCEL_CTRL ][ ord( 'E' ) ] = 'open_externally'
|
||||
|
||||
shortcuts[ wx.ACCEL_NORMAL ][ wx.WXK_UP ] = 'previous'
|
||||
shortcuts[ wx.ACCEL_NORMAL ][ wx.WXK_LEFT ] = 'previous'
|
||||
|
|
|
@ -1849,7 +1849,14 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
|
||||
|
||||
def GetPossibleTagIds():
|
||||
def GetPossibleWildcardNamespaceIds( wildcard_namespace ):
|
||||
|
||||
wildcard_namespace = wildcard_namespace.replace( '*', '%' )
|
||||
|
||||
return [ namespace_id for ( namespace_id, ) in self._c.execute( 'SELECT namespace_id FROM namespaces WHERE namespace LIKE ?;', ( wildcard_namespace, ) ) ]
|
||||
|
||||
|
||||
def GetPossibleTagIds( h_c_t ):
|
||||
|
||||
# the issue is that the tokenizer for fts4 doesn't like weird characters
|
||||
# a search for '[s' actually only does 's'
|
||||
|
@ -1857,10 +1864,10 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
# note that queries with '*' are passed to LIKE, because MATCH only supports appended wildcards 'gun*', and not complex stuff like '*gun*'
|
||||
|
||||
if half_complete_tag_can_be_matched: return [ tag_id for ( tag_id, ) in self._c.execute( 'SELECT docid FROM tags_fts4 WHERE tag MATCH ?;', ( '"' + half_complete_tag + '*"', ) ) ]
|
||||
if half_complete_tag_can_be_matched: return [ tag_id for ( tag_id, ) in self._c.execute( 'SELECT docid FROM tags_fts4 WHERE tag MATCH ?;', ( '"' + h_c_t + '*"', ) ) ]
|
||||
else:
|
||||
|
||||
possible_tag_ids_half_complete_tag = half_complete_tag
|
||||
possible_tag_ids_half_complete_tag = h_c_t
|
||||
|
||||
if '*' in possible_tag_ids_half_complete_tag:
|
||||
|
||||
|
@ -1868,7 +1875,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
else: possible_tag_ids_half_complete_tag += '%'
|
||||
|
||||
return [ tag_id for ( tag_id, ) in self._c.execute( 'SELECT tag_id FROM tags WHERE tag LIKE ? OR tag LIKE ?;', ( possible_tag_ids_half_complete_tag, ' ' + possible_tag_ids_half_complete_tag ) ) ]
|
||||
return [ tag_id for ( tag_id, ) in self._c.execute( 'SELECT tag_id FROM tags WHERE tag LIKE ? OR tag LIKE ?;', ( possible_tag_ids_half_complete_tag, '% ' + possible_tag_ids_half_complete_tag ) ) ]
|
||||
|
||||
|
||||
|
||||
|
@ -1881,22 +1888,34 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
if half_complete_tag == '': return CC.AutocompleteMatchesCounted( {} )
|
||||
else:
|
||||
|
||||
result = self._c.execute( 'SELECT namespace_id FROM namespaces WHERE namespace = ?;', ( namespace, ) ).fetchone()
|
||||
|
||||
if result is None: return CC.AutocompleteMatchesCounted( {} )
|
||||
if '*' in namespace:
|
||||
|
||||
possible_namespace_ids = GetPossibleWildcardNamespaceIds( namespace )
|
||||
|
||||
predicates_phrase_1 = 'namespace_id IN ' + HC.SplayListForDB( possible_namespace_ids )
|
||||
|
||||
else:
|
||||
|
||||
( namespace_id, ) = result
|
||||
|
||||
possible_tag_ids = GetPossibleTagIds()
|
||||
result = self._c.execute( 'SELECT namespace_id FROM namespaces WHERE namespace = ?;', ( namespace, ) ).fetchone()
|
||||
|
||||
predicates_phrase = 'namespace_id = ' + HC.u( namespace_id ) + ' AND tag_id IN ' + HC.SplayListForDB( possible_tag_ids )
|
||||
if result is None: return CC.AutocompleteMatchesCounted( {} )
|
||||
else:
|
||||
|
||||
( namespace_id, ) = result
|
||||
|
||||
predicates_phrase_1 = 'namespace_id = ' + HC.u( namespace_id )
|
||||
|
||||
|
||||
|
||||
possible_tag_ids = GetPossibleTagIds( half_complete_tag )
|
||||
|
||||
predicates_phrase = predicates_phrase_1 + ' AND tag_id IN ' + HC.SplayListForDB( possible_tag_ids )
|
||||
|
||||
|
||||
else:
|
||||
|
||||
possible_tag_ids = GetPossibleTagIds()
|
||||
possible_tag_ids = GetPossibleTagIds( half_complete_tag )
|
||||
|
||||
predicates_phrase = 'tag_id IN ' + HC.SplayListForDB( possible_tag_ids )
|
||||
|
||||
|
@ -2632,7 +2651,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
|||
|
||||
w = w.replace( '*', '%' )
|
||||
|
||||
return { tag_id for ( tag_id, ) in self._c.execute( 'SELECT tag_id FROM tags WHERE tag LIKE ?;', ( w, ) ) }
|
||||
return { tag_id for ( tag_id, ) in self._c.execute( 'SELECT tag_id FROM tags WHERE tag LIKE ? or tag LIKE ?;', ( w, '% ' + w ) ) }
|
||||
|
||||
else:
|
||||
|
||||
|
@ -5326,25 +5345,6 @@ class DB( ServiceDB ):
|
|||
|
||||
def _UpdateDB( self, version ):
|
||||
|
||||
if version == 94:
|
||||
|
||||
# I changed a variable name in account, so old yaml dumps need to be refreshed
|
||||
|
||||
unknown_account = HC.GetUnknownAccount()
|
||||
|
||||
self._c.execute( 'UPDATE accounts SET account = ?;', ( unknown_account, ) )
|
||||
|
||||
for ( name, info ) in self._c.execute( 'SELECT name, info FROM gui_sessions;' ).fetchall():
|
||||
|
||||
for ( page_name, c_text, args, kwargs ) in info:
|
||||
|
||||
if 'do_query' in kwargs: del kwargs[ 'do_query' ]
|
||||
|
||||
|
||||
self._c.execute( 'UPDATE gui_sessions SET info = ? WHERE name = ?;', ( info, name ) )
|
||||
|
||||
|
||||
|
||||
if version == 95:
|
||||
|
||||
self._c.execute( 'COMMIT' )
|
||||
|
@ -5964,6 +5964,15 @@ class DB( ServiceDB ):
|
|||
self._c.execute( 'REPLACE INTO yaml_dumps VALUES ( ?, ?, ? );', ( YAML_DUMP_ID_REMOTE_BOORU, 'sankaku chan', CC.DEFAULT_BOORUS[ 'sankaku chan' ] ) )
|
||||
|
||||
|
||||
if version == 143:
|
||||
|
||||
( HC.options, ) = self._c.execute( 'SELECT options FROM options;' ).fetchone()
|
||||
|
||||
HC.options[ 'shortcuts' ][ wx.ACCEL_CTRL ][ ord( 'E' ) ] = 'open_externally'
|
||||
|
||||
self._c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||
|
||||
|
||||
self._c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
|
||||
|
||||
HC.is_db_updated = True
|
||||
|
@ -7223,7 +7232,7 @@ def DAEMONSynchroniseRepositories():
|
|||
|
||||
def DAEMONSynchroniseSubscriptions():
|
||||
|
||||
HC.repos_changed = False
|
||||
HC.subs_changed = False
|
||||
|
||||
if not HC.options[ 'pause_subs_sync' ]:
|
||||
|
||||
|
@ -7373,6 +7382,8 @@ def DAEMONSynchroniseSubscriptions():
|
|||
job_key.SetVariable( 'popup_message_text_1', 'found ' + HC.ConvertIntToPrettyString( len( all_url_args ) ) + ' new files' )
|
||||
|
||||
|
||||
time.sleep( 5 )
|
||||
|
||||
|
||||
for downloader in downloaders_to_remove: downloaders.remove( downloader )
|
||||
|
||||
|
@ -7503,6 +7514,8 @@ def DAEMONSynchroniseSubscriptions():
|
|||
|
||||
HC.app.WaitUntilGoodTimeToUseGUIThread()
|
||||
|
||||
time.sleep( 3 )
|
||||
|
||||
|
||||
job_key.DeleteVariable( 'popup_message_gauge_1' )
|
||||
|
||||
|
|
|
@ -705,12 +705,15 @@ class Canvas( object ):
|
|||
|
||||
def _OpenExternally( self ):
|
||||
|
||||
hash = self._current_display_media.GetHash()
|
||||
mime = self._current_display_media.GetMime()
|
||||
|
||||
path = CC.GetFilePath( hash, mime )
|
||||
|
||||
HC.LaunchFile( path )
|
||||
if self._current_display_media is not None:
|
||||
|
||||
hash = self._current_display_media.GetHash()
|
||||
mime = self._current_display_media.GetMime()
|
||||
|
||||
path = CC.GetFilePath( hash, mime )
|
||||
|
||||
HC.LaunchFile( path )
|
||||
|
||||
|
||||
|
||||
def _PrefetchImages( self ): pass
|
||||
|
|
|
@ -3364,18 +3364,20 @@ class CollapsiblePanel( wx.Panel ):
|
|||
|
||||
parent_of_container = self.GetParent().GetParent()
|
||||
|
||||
old_height = self.GetMinHeight()
|
||||
|
||||
parent_of_container.Layout()
|
||||
|
||||
new_height = self.GetMinHeight()
|
||||
|
||||
height_difference = new_height - old_height
|
||||
|
||||
if isinstance( parent_of_container, wx.ScrolledWindow ):
|
||||
|
||||
# fitinside is like fit, but it does the virtual size!
|
||||
parent_of_container.FitInside()
|
||||
|
||||
|
||||
tlp = self.GetTopLevelParent()
|
||||
|
||||
if issubclass( type( tlp ), wx.Dialog ): tlp.Fit()
|
||||
|
||||
|
||||
def ExpandCollapse( self ): self._Change()
|
||||
|
||||
|
|
|
@ -886,7 +886,7 @@ class DialogInputCustomFilterAction( Dialog ):
|
|||
|
||||
self._none_panel = ClientGUICommon.StaticBox( self, 'non-service actions' )
|
||||
|
||||
self._none_actions = wx.Choice( self._none_panel, choices = [ 'manage_tags', 'manage_ratings', 'archive', 'inbox', 'delete', 'fullscreen_switch', 'frame_back', 'frame_next', 'previous', 'next', 'first', 'last' ] )
|
||||
self._none_actions = wx.Choice( self._none_panel, choices = [ 'manage_tags', 'manage_ratings', 'archive', 'inbox', 'delete', 'fullscreen_switch', 'frame_back', 'frame_next', 'previous', 'next', 'first', 'last', 'open_externally' ] )
|
||||
|
||||
self._ok_none = wx.Button( self._none_panel, label = 'ok' )
|
||||
self._ok_none.Bind( wx.EVT_BUTTON, self.EventOKNone )
|
||||
|
@ -2683,6 +2683,8 @@ class DialogInputLocalFiles( Dialog ):
|
|||
|
||||
for ( i, path ) in enumerate( file_paths ):
|
||||
|
||||
if path.endswith( os.path.sep + 'Thumbs.db' ) or path.endswith( os.path.sep + 'thumbs.db' ): continue
|
||||
|
||||
if i % 500 == 0: gc.collect()
|
||||
|
||||
wx.CallAfter( self.SetGaugeInfo, num_file_paths, i, u'Done ' + HC.u( i ) + '/' + HC.u( num_file_paths ) )
|
||||
|
@ -3444,7 +3446,7 @@ class DialogInputShortcut( Dialog ):
|
|||
|
||||
self._shortcut = ClientGUICommon.Shortcut( self, modifier, key )
|
||||
|
||||
self._actions = wx.Choice( self, choices = [ 'archive', 'inbox', 'close_page', 'filter', 'fullscreen_switch', 'ratings_filter', 'frame_back', 'frame_next', 'manage_ratings', 'manage_tags', 'new_page', 'refresh', 'set_search_focus', 'show_hide_splitters', 'synchronised_wait_switch', 'previous', 'next', 'first', 'last', 'undo', 'redo' ] )
|
||||
self._actions = wx.Choice( self, choices = [ 'archive', 'inbox', 'close_page', 'filter', 'fullscreen_switch', 'ratings_filter', 'frame_back', 'frame_next', 'manage_ratings', 'manage_tags', 'new_page', 'refresh', 'set_search_focus', 'show_hide_splitters', 'synchronised_wait_switch', 'previous', 'next', 'first', 'last', 'undo', 'redo', 'open_externally' ] )
|
||||
|
||||
self._ok = wx.Button( self, id= wx.ID_OK, label = 'Ok' )
|
||||
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
|
||||
|
@ -4452,14 +4454,9 @@ class DialogPathsToTagsRegex( Dialog ):
|
|||
|
||||
try:
|
||||
|
||||
m = re.search( regex, path )
|
||||
result = re.findall( regex, path )
|
||||
|
||||
if m is not None:
|
||||
|
||||
match = m.group()
|
||||
|
||||
if len( match ) > 0: tags.append( match )
|
||||
|
||||
for match in result: tags.append( match )
|
||||
|
||||
except: pass
|
||||
|
||||
|
@ -4468,14 +4465,9 @@ class DialogPathsToTagsRegex( Dialog ):
|
|||
|
||||
try:
|
||||
|
||||
m = re.search( regex, path )
|
||||
result = re.findall( regex, path )
|
||||
|
||||
if m is not None:
|
||||
|
||||
match = m.group()
|
||||
|
||||
if len( match ) > 0: tags.append( namespace + ':' + match )
|
||||
|
||||
for match in result: tags.append( namespace + ':' + match )
|
||||
|
||||
except: pass
|
||||
|
||||
|
@ -4491,6 +4483,10 @@ class DialogPathsToTagsRegex( Dialog ):
|
|||
|
||||
tags = HC.CleanTags( tags )
|
||||
|
||||
tags = list( tags )
|
||||
|
||||
tags.sort()
|
||||
|
||||
return tags
|
||||
|
||||
|
||||
|
@ -5272,7 +5268,7 @@ class DialogSetupCustomFilterActions( Dialog ):
|
|||
|
||||
for ( key, action ) in key_dict.items():
|
||||
|
||||
if action in ( 'manage_tags', 'manage_ratings', 'archive', 'inbox', 'fullscreen_switch', 'frame_back', 'frame_next', 'previous', 'next', 'first', 'last', 'pan_up', 'pan_down', 'pan_left', 'pan_right' ):
|
||||
if action in ( 'manage_tags', 'manage_ratings', 'archive', 'inbox', 'fullscreen_switch', 'frame_back', 'frame_next', 'previous', 'next', 'first', 'last', 'pan_up', 'pan_down', 'pan_left', 'pan_right', 'open_externally' ):
|
||||
|
||||
service_key = None
|
||||
|
||||
|
|
|
@ -7703,7 +7703,6 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
if self._i_am_local_tag_service: self._modify_mappers.Hide()
|
||||
else:
|
||||
|
||||
if not ( self._account.HasPermission( HC.POST_DATA ) or self._account.IsUnknownAccount() ): self._add_tag_box.Hide()
|
||||
if not self._account.HasPermission( HC.MANAGE_USERS ): self._modify_mappers.Hide()
|
||||
|
||||
|
||||
|
@ -7737,7 +7736,8 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
|
||||
service = HC.app.GetManager( 'services' ).GetService( tag_service_key )
|
||||
|
||||
self._account = service.GetInfo( 'account' )
|
||||
try: self._account = service.GetInfo( 'account' )
|
||||
except: self._account = HC.GetUnknownAccount()
|
||||
|
||||
|
||||
hashes = set( itertools.chain.from_iterable( ( m.GetHashes() for m in media ) ) )
|
||||
|
@ -7899,7 +7899,7 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def SetTagBoxFocus( self ):
|
||||
|
||||
if self._i_am_local_tag_service or self._account.HasPermission( HC.POST_DATA ) or self._account.IsUnknownAccount(): self._add_tag_box.SetFocus()
|
||||
self._add_tag_box.SetFocus()
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1222,8 +1222,8 @@ class ManagementPanelImport( ManagementPanel ):
|
|||
|
||||
import_controller_job_key = self._import_controller.GetJobKey( 'controller' )
|
||||
import_job_key = self._import_controller.GetJobKey( 'import' )
|
||||
import_queue_position_job_key = self._import_controller.GetJobKey( 'import_queue_position' )
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
# info
|
||||
|
||||
|
@ -1247,13 +1247,13 @@ class ManagementPanelImport( ManagementPanel ):
|
|||
|
||||
if import_status != self._import_current_info.GetLabel(): self._import_current_info.SetLabel( import_status )
|
||||
|
||||
import_queue_status = import_queue_position_job_key.GetVariable( 'status' )
|
||||
import_queue_status = import_queue_job_key.GetVariable( 'status' )
|
||||
|
||||
if import_queue_status != self._import_queue_info.GetLabel(): self._import_queue_info.SetLabel( import_queue_status )
|
||||
|
||||
# buttons
|
||||
|
||||
if import_queue_position_job_key.IsPaused():
|
||||
if import_queue_job_key.IsPaused():
|
||||
|
||||
if self._import_pause_button.GetLabel() != 'resume':
|
||||
|
||||
|
@ -1270,7 +1270,7 @@ class ManagementPanelImport( ManagementPanel ):
|
|||
|
||||
|
||||
|
||||
if import_queue_position_job_key.IsWorking() and not import_queue_position_job_key.IsCancelled():
|
||||
if import_queue_job_key.IsWorking() and not import_queue_job_key.IsCancelled():
|
||||
|
||||
self._import_pause_button.Enable()
|
||||
self._import_cancel_button.Enable()
|
||||
|
@ -1294,11 +1294,11 @@ class ManagementPanelImport( ManagementPanel ):
|
|||
self._import_gauge.SetValue( value )
|
||||
|
||||
|
||||
queue = import_queue_job_key.GetVariable( 'queue' )
|
||||
queue = import_queue_builder_job_key.GetVariable( 'queue' )
|
||||
|
||||
if len( queue ) == 0:
|
||||
|
||||
if import_queue_job_key.IsWorking(): self._import_queue_gauge.Pulse()
|
||||
if import_queue_builder_job_key.IsWorking(): self._import_queue_gauge.Pulse()
|
||||
else:
|
||||
|
||||
self._import_queue_gauge.SetRange( 1 )
|
||||
|
@ -1307,7 +1307,7 @@ class ManagementPanelImport( ManagementPanel ):
|
|||
|
||||
else:
|
||||
|
||||
queue_position = import_queue_position_job_key.GetVariable( 'queue_position' )
|
||||
queue_position = import_queue_job_key.GetVariable( 'queue_position' )
|
||||
|
||||
self._import_queue_gauge.SetRange( len( queue ) )
|
||||
self._import_queue_gauge.SetValue( queue_position )
|
||||
|
@ -1316,20 +1316,20 @@ class ManagementPanelImport( ManagementPanel ):
|
|||
|
||||
def EventCancelImportQueue( self, event ):
|
||||
|
||||
import_queue_position_job_key = self._import_controller.GetJobKey( 'import_queue_position' )
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
import_queue_position_job_key.Cancel()
|
||||
import_queue_job_key.Cancel()
|
||||
import_queue_builder_job_key.Cancel()
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
||||
def EventPauseImportQueue( self, event ):
|
||||
|
||||
import_queue_position_job_key = self._import_controller.GetJobKey( 'import_queue_position' )
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
|
||||
import_queue_position_job_key.PauseResume()
|
||||
import_queue_job_key.PauseResume()
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
@ -1340,9 +1340,9 @@ class ManagementPanelImport( ManagementPanel ):
|
|||
|
||||
def TestAbleToClose( self ):
|
||||
|
||||
import_queue_position_job_key = self._import_controller.GetJobKey( 'import_queue_position' )
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
|
||||
if import_queue_position_job_key.IsWorking() and not import_queue_position_job_key.IsPaused():
|
||||
if import_queue_job_key.IsWorking() and not import_queue_job_key.IsPaused():
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, 'This page is still importing. Are you sure you want to close it?' ) as dlg:
|
||||
|
||||
|
@ -1364,11 +1364,11 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
self._building_import_queue_info = wx.StaticText( self._building_import_queue_panel )
|
||||
|
||||
self._building_import_queue_pause_button = wx.Button( self._building_import_queue_panel, label = 'pause' )
|
||||
self._building_import_queue_pause_button.Bind( wx.EVT_BUTTON, self.EventPauseBuildImportQueue )
|
||||
self._building_import_queue_pause_button.Bind( wx.EVT_BUTTON, self.EventPauseImportQueueBuilder )
|
||||
self._building_import_queue_pause_button.Disable()
|
||||
|
||||
self._building_import_queue_cancel_button = wx.Button( self._building_import_queue_panel, label = 'that\'s enough' )
|
||||
self._building_import_queue_cancel_button.Bind( wx.EVT_BUTTON, self.EventCancelBuildImportQueue )
|
||||
self._building_import_queue_cancel_button.Bind( wx.EVT_BUTTON, self.EventCancelImportQueueBuilder )
|
||||
self._building_import_queue_cancel_button.SetForegroundColour( ( 128, 0, 0 ) )
|
||||
self._building_import_queue_cancel_button.Disable()
|
||||
|
||||
|
@ -1424,20 +1424,20 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
ManagementPanelImport._UpdateGUI( self )
|
||||
|
||||
import_job_key = self._import_controller.GetJobKey( 'import' )
|
||||
import_queue_position_job_key = self._import_controller.GetJobKey( 'import_queue_position' )
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
# info
|
||||
|
||||
extend_import_queue_status = import_queue_job_key.GetVariable( 'status' )
|
||||
import_queue_builder_status = import_queue_builder_job_key.GetVariable( 'status' )
|
||||
|
||||
if extend_import_queue_status != self._building_import_queue_info.GetLabel(): self._building_import_queue_info.SetLabel( extend_import_queue_status )
|
||||
if import_queue_builder_status != self._building_import_queue_info.GetLabel(): self._building_import_queue_info.SetLabel( import_queue_builder_status )
|
||||
|
||||
# buttons
|
||||
|
||||
#
|
||||
|
||||
if import_queue_job_key.IsPaused():
|
||||
if import_queue_builder_job_key.IsPaused():
|
||||
|
||||
if self._building_import_queue_pause_button.GetLabel() != 'resume':
|
||||
|
||||
|
@ -1454,7 +1454,7 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
|
||||
|
||||
|
||||
if import_queue_job_key.IsWorking() and not import_queue_job_key.IsCancelled():
|
||||
if import_queue_builder_job_key.IsWorking() and not import_queue_job_key.IsCancelled():
|
||||
|
||||
self._building_import_queue_pause_button.Enable()
|
||||
self._building_import_queue_cancel_button.Enable()
|
||||
|
@ -1480,19 +1480,19 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
|
||||
# pending import queues
|
||||
|
||||
import_queues = self._import_controller.GetPendingImportQueues()
|
||||
pending_import_queue_jobs = self._import_controller.GetPendingImportQueueJobs()
|
||||
|
||||
if import_queues != self._pending_import_queues_listbox.GetItems():
|
||||
if pending_import_queue_jobs != self._pending_import_queues_listbox.GetItems():
|
||||
|
||||
self._pending_import_queues_listbox.SetItems( import_queues )
|
||||
self._pending_import_queues_listbox.SetItems( pending_import_queue_jobs )
|
||||
|
||||
|
||||
|
||||
def EventCancelBuildImportQueue( self, event ):
|
||||
def EventCancelImportQueueBuilder( self, event ):
|
||||
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
import_queue_job_key.Cancel()
|
||||
import_queue_builder_job_key.Cancel()
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
@ -1505,7 +1505,7 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
|
||||
if s != '':
|
||||
|
||||
self._import_controller.PendImportQueue( s )
|
||||
self._import_controller.PendImportQueueJob( s )
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
@ -1515,11 +1515,11 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
else: event.Skip()
|
||||
|
||||
|
||||
def EventPauseBuildImportQueue( self, event ):
|
||||
def EventPauseImportQueueBuilder( self, event ):
|
||||
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
import_queue_job_key.PauseResume()
|
||||
import_queue_builder_job_key.PauseResume()
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
@ -1534,7 +1534,7 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
|
||||
s = self._pending_import_queues_listbox.GetString( selection )
|
||||
|
||||
self._import_controller.MovePendingImportQueueUp( s )
|
||||
self._import_controller.MovePendingImportQueueJobUp( s )
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
@ -1551,7 +1551,7 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
|
||||
s = self._pending_import_queues_listbox.GetString( selection )
|
||||
|
||||
self._import_controller.RemovePendingImportQueue( s )
|
||||
self._import_controller.RemovePendingImportQueueJob( s )
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
@ -1567,7 +1567,7 @@ class ManagementPanelImports( ManagementPanelImport ):
|
|||
|
||||
s = self._pending_import_queues_listbox.GetString( selection )
|
||||
|
||||
self._import_controller.MovePendingImportQueueDown( s )
|
||||
self._import_controller.MovePendingImportQueueJobDown( s )
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
@ -1679,7 +1679,10 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
self._thread_input.Bind( wx.EVT_KEY_DOWN, self.EventKeyDown )
|
||||
|
||||
self._thread_pause_button = wx.Button( self._thread_panel, label = 'pause' )
|
||||
self._thread_pause_button.Bind( wx.EVT_BUTTON, self.EventPauseBuildImportQueue )
|
||||
self._thread_pause_button.Bind( wx.EVT_BUTTON, self.EventPauseImportQueueBuilder )
|
||||
|
||||
self._thread_manual_refresh_button = wx.Button( self._thread_panel, label = 'check now' )
|
||||
self._thread_manual_refresh_button.Bind( wx.EVT_BUTTON, self.EventManualRefresh )
|
||||
|
||||
hbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
|
@ -1689,10 +1692,15 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
hbox.AddF( self._thread_check_period, FLAGS_MIXED )
|
||||
hbox.AddF( wx.StaticText( self._thread_panel, label = ' seconds' ), FLAGS_MIXED )
|
||||
|
||||
button_box = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
button_box.AddF( self._thread_pause_button, FLAGS_EXPAND_BOTH_WAYS )
|
||||
button_box.AddF( self._thread_manual_refresh_button, FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
self._thread_panel.AddF( self._thread_info, FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._thread_panel.AddF( self._thread_input, FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._thread_panel.AddF( hbox, FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
self._thread_panel.AddF( self._thread_pause_button, FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._thread_panel.AddF( button_box, FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
|
||||
vbox.AddF( self._thread_panel, FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
|
||||
|
@ -1705,13 +1713,14 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
|
||||
def _SetThreadVariables( self ):
|
||||
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
thread_time = self._thread_check_period.GetValue()
|
||||
thread_times_to_check = self._thread_times_to_check.GetValue()
|
||||
|
||||
import_queue_job_key.SetVariable( 'thread_time', thread_time )
|
||||
import_queue_job_key.SetVariable( 'thread_times_to_check', thread_times_to_check )
|
||||
import_queue_builder_job_key.SetVariable( 'manual_refresh', False )
|
||||
import_queue_builder_job_key.SetVariable( 'thread_time', thread_time )
|
||||
import_queue_builder_job_key.SetVariable( 'thread_times_to_check', thread_times_to_check )
|
||||
|
||||
|
||||
def _UpdateGUI( self ):
|
||||
|
@ -1719,21 +1728,21 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
ManagementPanelImport._UpdateGUI( self )
|
||||
|
||||
import_job_key = self._import_controller.GetJobKey( 'import' )
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
# thread_info
|
||||
|
||||
status = import_queue_job_key.GetVariable( 'status' )
|
||||
status = import_queue_builder_job_key.GetVariable( 'status' )
|
||||
|
||||
if status != self._thread_info.GetLabel(): self._thread_info.SetLabel( status )
|
||||
|
||||
# button
|
||||
|
||||
if import_queue_job_key.IsWorking():
|
||||
if import_queue_builder_job_key.IsWorking():
|
||||
|
||||
self._thread_pause_button.Enable()
|
||||
|
||||
if import_queue_job_key.IsPaused():
|
||||
if import_queue_builder_job_key.IsPaused():
|
||||
|
||||
self._thread_pause_button.SetLabel( 'resume' )
|
||||
self._thread_pause_button.SetForegroundColour( ( 0, 128, 0 ) )
|
||||
|
@ -1750,12 +1759,21 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
|
||||
try:
|
||||
|
||||
thread_times_to_check = import_queue_job_key.GetVariable( 'thread_times_to_check' )
|
||||
thread_times_to_check = import_queue_builder_job_key.GetVariable( 'thread_times_to_check' )
|
||||
|
||||
self._thread_times_to_check.SetValue( thread_times_to_check )
|
||||
|
||||
except: self._SetThreadVariables()
|
||||
|
||||
try:
|
||||
|
||||
manual_refresh = import_queue_builder_job_key.GetVariable( 'manual_refresh' )
|
||||
|
||||
if not import_queue_builder_job_key.IsWorking() or manual_refresh: self._thread_manual_refresh_button.Disable()
|
||||
else: self._thread_manual_refresh_button.Enable()
|
||||
|
||||
except: self._SetThreadVariables()
|
||||
|
||||
|
||||
def EventKeyDown( self, event ):
|
||||
|
||||
|
@ -1782,7 +1800,7 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
except: raise Exception ( 'Could not understand that url!' )
|
||||
|
||||
is_4chan = '4chan.org' in host
|
||||
is_8chan = '8chan.co' in host
|
||||
is_8chan = '8chan.co' in host or '8ch.net' in host
|
||||
|
||||
if not ( is_4chan or is_8chan ): raise Exception( 'This only works for 4chan and 8chan right now!' )
|
||||
|
||||
|
@ -1813,16 +1831,16 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
( board, rest_of_request ) = request[1:].split( '/res/', 1 )
|
||||
|
||||
json_url = url[:-4] + 'json'
|
||||
image_base = 'http://8chan.co/' + board + '/src/'
|
||||
image_base = 'http://8ch.net/' + board + '/src/'
|
||||
|
||||
|
||||
except: raise Exception( 'Could not understand the board or thread id!' )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
import_queue_job_key.SetVariable( 'status', HC.u( e ) )
|
||||
import_queue_builder_job_key.SetVariable( 'status', HC.u( e ) )
|
||||
|
||||
HC.ShowException( e )
|
||||
|
||||
|
@ -1833,16 +1851,25 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
|
||||
self._SetThreadVariables()
|
||||
|
||||
self._import_controller.PendImportQueue( ( json_url, image_base ) )
|
||||
self._import_controller.PendImportQueueJob( ( json_url, image_base ) )
|
||||
|
||||
else: event.Skip()
|
||||
|
||||
|
||||
def EventPauseBuildImportQueue( self, event ):
|
||||
def EventManualRefresh( self, event ):
|
||||
|
||||
import_queue_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
import_queue_job_key.PauseResume()
|
||||
import_queue_builder_job_key.SetVariable( 'manual_refresh', True )
|
||||
|
||||
self._thread_manual_refresh_button.Disable()
|
||||
|
||||
|
||||
def EventPauseImportQueueBuilder( self, event ):
|
||||
|
||||
import_queue_builder_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
import_queue_builder_job_key.PauseResume()
|
||||
|
||||
self._UpdateGUI()
|
||||
|
||||
|
@ -1858,9 +1885,9 @@ class ManagementPanelImportThreadWatcher( ManagementPanelImport ):
|
|||
|
||||
def TestAbleToClose( self ):
|
||||
|
||||
import_queue_position_job_key = self._import_controller.GetJobKey( 'import_queue' )
|
||||
import_queue_builder_position_job_key = self._import_controller.GetJobKey( 'import_queue_builder' )
|
||||
|
||||
if self._thread_times_to_check.GetValue() > 0 and import_queue_position_job_key.IsWorking() and not import_queue_position_job_key.IsPaused():
|
||||
if self._thread_times_to_check.GetValue() > 0 and import_queue_builder_position_job_key.IsWorking() and not import_queue_builder_position_job_key.IsPaused():
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, 'This page is still importing. Are you sure you want to close it?' ) as dlg:
|
||||
|
||||
|
|
|
@ -469,12 +469,15 @@ class MediaPanel( ClientGUIMixins.ListeningMediaList, wx.ScrolledWindow ):
|
|||
|
||||
def _OpenExternally( self ):
|
||||
|
||||
hash = self._focussed_media.GetHash()
|
||||
mime = self._focussed_media.GetMime()
|
||||
|
||||
path = CC.GetFilePath( hash, mime )
|
||||
|
||||
HC.LaunchFile( path )
|
||||
if self._focussed_media is not None:
|
||||
|
||||
hash = self._focussed_media.GetHash()
|
||||
mime = self._focussed_media.GetMime()
|
||||
|
||||
path = CC.GetFilePath( hash, mime )
|
||||
|
||||
HC.LaunchFile( path )
|
||||
|
||||
|
||||
|
||||
def _PetitionFiles( self, file_service_key ):
|
||||
|
|
|
@ -260,11 +260,11 @@ class PageImport( PageWithMedia ):
|
|||
return factory
|
||||
|
||||
|
||||
def _GenerateImportQueueGeneratorFactory( self ):
|
||||
def _GenerateImportQueueBuilderFactory( self ):
|
||||
|
||||
def factory( job_key, item ):
|
||||
|
||||
return HydrusDownloading.ImportQueueGenerator( job_key, item )
|
||||
return HydrusDownloading.ImportQueueBuilder( job_key, item )
|
||||
|
||||
|
||||
return factory
|
||||
|
@ -275,9 +275,9 @@ class PageImport( PageWithMedia ):
|
|||
def _InitControllers( self ):
|
||||
|
||||
import_args_generator_factory = self._GenerateImportArgsGeneratorFactory()
|
||||
import_queue_generator_factory = self._GenerateImportQueueGeneratorFactory()
|
||||
import_queue_builder_factory = self._GenerateImportQueueBuilderFactory()
|
||||
|
||||
self._import_controller = HydrusDownloading.ImportController( import_args_generator_factory, import_queue_generator_factory, page_key = self._page_key )
|
||||
self._import_controller = HydrusDownloading.ImportController( import_args_generator_factory, import_queue_builder_factory, page_key = self._page_key )
|
||||
|
||||
self._import_controller.StartDaemon()
|
||||
|
||||
|
@ -338,13 +338,13 @@ class PageImportGallery( PageImport ):
|
|||
return factory
|
||||
|
||||
|
||||
def _GenerateImportQueueGeneratorFactory( self ):
|
||||
def _GenerateImportQueueBuilderFactory( self ):
|
||||
|
||||
def factory( job_key, item ):
|
||||
|
||||
downloaders_factory = self._GetDownloadersFactory()
|
||||
|
||||
return HydrusDownloading.ImportQueueGeneratorGallery( job_key, item, downloaders_factory )
|
||||
return HydrusDownloading.ImportQueueBuilderGallery( job_key, item, downloaders_factory )
|
||||
|
||||
|
||||
return factory
|
||||
|
@ -471,7 +471,7 @@ class PageImportGallery( PageImport ):
|
|||
if self._gallery_type == 'artist':
|
||||
|
||||
name = 'deviant art'
|
||||
namespaces = [ 'creator', 'title', '' ]
|
||||
namespaces = [ 'creator', 'title' ]
|
||||
initial_search_value = 'artist username'
|
||||
|
||||
|
||||
|
@ -538,7 +538,7 @@ class PageImportHDD( PageImport ):
|
|||
|
||||
PageImport.__init__( self, parent, initial_hashes = initial_hashes, starting_from_session = starting_from_session )
|
||||
|
||||
self._import_controller.PendImportQueue( self._paths_info )
|
||||
self._import_controller.PendImportQueueJob( self._paths_info )
|
||||
|
||||
|
||||
def _GenerateImportArgsGeneratorFactory( self ):
|
||||
|
@ -582,11 +582,11 @@ class PageImportThreadWatcher( PageImport ):
|
|||
return factory
|
||||
|
||||
|
||||
def _GenerateImportQueueGeneratorFactory( self ):
|
||||
def _GenerateImportQueueBuilderFactory( self ):
|
||||
|
||||
def factory( job_key, item ):
|
||||
|
||||
return HydrusDownloading.ImportQueueGeneratorThread( job_key, item )
|
||||
return HydrusDownloading.ImportQueueBuilderThread( job_key, item )
|
||||
|
||||
|
||||
return factory
|
||||
|
@ -608,11 +608,11 @@ class PageImportURL( PageImport ):
|
|||
return factory
|
||||
|
||||
|
||||
def _GenerateImportQueueGeneratorFactory( self ):
|
||||
def _GenerateImportQueueBuilderFactory( self ):
|
||||
|
||||
def factory( job_key, item ):
|
||||
|
||||
return HydrusDownloading.ImportQueueGeneratorURLs( job_key, item )
|
||||
return HydrusDownloading.ImportQueueBuilderURLs( job_key, item )
|
||||
|
||||
|
||||
return factory
|
||||
|
|
|
@ -66,7 +66,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 15
|
||||
SOFTWARE_VERSION = 143
|
||||
SOFTWARE_VERSION = 144
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
@ -2228,7 +2228,7 @@ class Predicate( HydrusYAMLBase ):
|
|||
|
||||
( operator, value ) = info
|
||||
|
||||
base += u' ' + operator + u' ' + u( value )
|
||||
base += u' ' + operator + u' ' + ConvertIntToPrettyString( value )
|
||||
|
||||
|
||||
elif system_predicate_type == SYSTEM_PREDICATE_TYPE_RATIO:
|
||||
|
@ -2261,7 +2261,7 @@ class Predicate( HydrusYAMLBase ):
|
|||
|
||||
value = info
|
||||
|
||||
base += u' is ' + u( value )
|
||||
base += u' is ' + ConvertIntToPrettyString( value )
|
||||
|
||||
|
||||
elif system_predicate_type == SYSTEM_PREDICATE_TYPE_AGE:
|
||||
|
@ -2312,7 +2312,7 @@ class Predicate( HydrusYAMLBase ):
|
|||
|
||||
elif system_predicate_type == SYSTEM_PREDICATE_TYPE_SIMILAR_TO:
|
||||
|
||||
base = u'system:similar to '
|
||||
base = u'system:similar to'
|
||||
|
||||
if info is not None:
|
||||
|
||||
|
@ -2323,16 +2323,14 @@ class Predicate( HydrusYAMLBase ):
|
|||
|
||||
elif system_predicate_type == SYSTEM_PREDICATE_TYPE_FILE_SERVICE:
|
||||
|
||||
base = u'system:file service'
|
||||
base = u'system:'
|
||||
|
||||
if info is not None:
|
||||
|
||||
( operator, current_or_pending, service_key ) = info
|
||||
|
||||
base += u':'
|
||||
|
||||
if operator == True: base += u' is'
|
||||
else: base += u' is not'
|
||||
if operator == True: base += u'is'
|
||||
else: base += u'is not'
|
||||
|
||||
if current_or_pending == PENDING: base += u' pending to '
|
||||
else: base += u' currently in '
|
||||
|
@ -2376,14 +2374,14 @@ class Predicate( HydrusYAMLBase ):
|
|||
|
||||
namespace = self._value
|
||||
|
||||
if not self._inclusive == '-': base = u'-'
|
||||
if not self._inclusive: base = u'-'
|
||||
else: base = u''
|
||||
|
||||
base += namespace + u':*'
|
||||
|
||||
elif self._predicate_type == PREDICATE_TYPE_WILDCARD:
|
||||
|
||||
( operator, wildcard ) = self._value
|
||||
wildcard = self._value
|
||||
|
||||
if not self._inclusive: base = u'-'
|
||||
else: base = u''
|
||||
|
|
|
@ -359,6 +359,7 @@ class DownloaderDeviantArt( Downloader ):
|
|||
def __init__( self, artist ):
|
||||
|
||||
self._gallery_url = 'http://' + artist + '.deviantart.com/gallery/?catpath=/&offset='
|
||||
self._artist = artist
|
||||
|
||||
Downloader.__init__( self )
|
||||
|
||||
|
@ -383,38 +384,18 @@ class DownloaderDeviantArt( Downloader ):
|
|||
|
||||
page_url = link[ 'href' ] # something in the form of blah.da.com/art/blah-123456
|
||||
|
||||
raw_title = link[ 'title' ] # sweet dolls by ~AngeniaC, Feb 29, 2012 in Artisan Crafts > Miniatures > Jewelry
|
||||
raw_title = link[ 'title' ] # sweet dolls by AngeniaC, date, blah blah blah
|
||||
|
||||
raw_title_reversed = raw_title[::-1] # yrleweJ ;tg& serutainiM ;tg& stfarC nasitrA ni 2102 ,92 beF ,CainegnA~ yb sllod teews
|
||||
raw_title_reversed = raw_title[::-1] # trAtnaiveD no CainegnA yb sllod teews
|
||||
|
||||
( creator_and_date_and_tags_reversed, title_reversed ) = raw_title_reversed.split( ' yb ', 1 )
|
||||
|
||||
creator_and_date_and_tags = creator_and_date_and_tags_reversed[::-1] # ~AngeniaC, Feb 29, 2012 in Artisan Crafts > Miniatures > Jewelry
|
||||
|
||||
( creator_with_username_char, date_and_tags ) = creator_and_date_and_tags.split( ',', 1 )
|
||||
|
||||
creator = creator_with_username_char[1:] # AngeniaC
|
||||
( creator_and_gumpf_reversed, title_reversed ) = raw_title_reversed.split( ' yb ', 1 )
|
||||
|
||||
title = title_reversed[::-1] # sweet dolls
|
||||
|
||||
try:
|
||||
|
||||
( date_gumpf, raw_category_tags ) = date_and_tags.split( ' in ', 1 )
|
||||
|
||||
category_tags = raw_category_tags.split( ' > ' )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
HC.ShowException( e )
|
||||
|
||||
category_tags = []
|
||||
|
||||
|
||||
tags = []
|
||||
|
||||
tags.append( 'title:' + title )
|
||||
tags.append( 'creator:' + creator )
|
||||
tags.extend( category_tags )
|
||||
tags.append( 'creator:' + self._artist )
|
||||
|
||||
results.append( ( page_url, tags ) )
|
||||
|
||||
|
@ -1153,6 +1134,8 @@ class ImportArgsGeneratorGallery( ImportArgsGenerator ):
|
|||
|
||||
service_keys_to_tags = ConvertTagsToServiceKeysToTags( tags, self._advanced_tag_options )
|
||||
|
||||
time.sleep( 3 )
|
||||
|
||||
return ( url, temp_path, service_keys_to_tags, url )
|
||||
|
||||
|
||||
|
@ -1186,6 +1169,8 @@ class ImportArgsGeneratorGallery( ImportArgsGenerator ):
|
|||
|
||||
HC.app.Write( 'content_updates', service_keys_to_content_updates )
|
||||
|
||||
time.sleep( 3 )
|
||||
|
||||
|
||||
return ( status, media_result )
|
||||
|
||||
|
@ -1280,6 +1265,8 @@ class ImportArgsGeneratorThread( ImportArgsGenerator ):
|
|||
|
||||
service_keys_to_tags = ConvertTagsToServiceKeysToTags( tags, self._advanced_tag_options )
|
||||
|
||||
time.sleep( 3 )
|
||||
|
||||
return ( image_url, temp_path, service_keys_to_tags, image_url )
|
||||
|
||||
|
||||
|
@ -1297,6 +1284,21 @@ class ImportArgsGeneratorThread( ImportArgsGenerator ):
|
|||
|
||||
( media_result, ) = HC.app.ReadDaemon( 'media_results', HC.LOCAL_FILE_SERVICE_KEY, ( hash, ) )
|
||||
|
||||
do_tags = len( self._advanced_tag_options ) > 0
|
||||
|
||||
if do_tags:
|
||||
|
||||
tags = [ 'filename:' + filename ]
|
||||
|
||||
service_keys_to_tags = ConvertTagsToServiceKeysToTags( tags, self._advanced_tag_options )
|
||||
|
||||
service_keys_to_content_updates = ConvertServiceKeysToTagsToServiceKeysToContentUpdates( hash, service_keys_to_tags )
|
||||
|
||||
HC.app.Write( 'content_updates', service_keys_to_content_updates )
|
||||
|
||||
time.sleep( 3 )
|
||||
|
||||
|
||||
return ( status, media_result )
|
||||
|
||||
else: return ( status, None )
|
||||
|
@ -1344,17 +1346,17 @@ class ImportArgsGeneratorURLs( ImportArgsGenerator ):
|
|||
|
||||
class ImportController( object ):
|
||||
|
||||
def __init__( self, import_args_generator_factory, import_queue_generator_factory, page_key = None ):
|
||||
def __init__( self, import_args_generator_factory, import_queue_builder_factory, page_key = None ):
|
||||
|
||||
self._controller_job_key = self._GetNewJobKey( 'controller' )
|
||||
|
||||
self._import_args_generator_factory = import_args_generator_factory
|
||||
self._import_queue_generator_factory = import_queue_generator_factory
|
||||
self._import_queue_builder_factory = import_queue_builder_factory
|
||||
self._page_key = page_key
|
||||
|
||||
self._import_job_key = self._GetNewJobKey( 'import' )
|
||||
self._import_queue_position_job_key = self._GetNewJobKey( 'import_queue_position' )
|
||||
self._import_queue_job_key = self._GetNewJobKey( 'import_queue' )
|
||||
self._import_queue_builder_job_key = self._GetNewJobKey( 'import_queue_builder' )
|
||||
self._pending_import_queue_jobs = []
|
||||
|
||||
self._lock = threading.Lock()
|
||||
|
@ -1381,11 +1383,11 @@ class ImportController( object ):
|
|||
job_key.SetVariable( 'range', 1 )
|
||||
job_key.SetVariable( 'value', 0 )
|
||||
|
||||
elif job_type == 'import_queue_position':
|
||||
elif job_type == 'import_queue':
|
||||
|
||||
job_key.SetVariable( 'queue_position', 0 )
|
||||
|
||||
elif job_type == 'import_queue':
|
||||
elif job_type == 'import_queue_builder':
|
||||
|
||||
job_key.SetVariable( 'queue', [] )
|
||||
|
||||
|
@ -1402,22 +1404,22 @@ class ImportController( object ):
|
|||
|
||||
if job_type == 'controller': return self._controller_job_key
|
||||
elif job_type == 'import': return self._import_job_key
|
||||
elif job_type == 'import_queue_position': return self._import_queue_position_job_key
|
||||
elif job_type == 'import_queue': return self._import_queue_job_key
|
||||
elif job_type == 'import_queue_builder': return self._import_queue_builder_job_key
|
||||
|
||||
|
||||
|
||||
def GetPendingImportQueues( self ):
|
||||
def GetPendingImportQueueJobs( self ):
|
||||
|
||||
with self._lock: return self._pending_import_queue_jobs
|
||||
|
||||
|
||||
def PendImportQueue( self, job ):
|
||||
def PendImportQueueJob( self, job ):
|
||||
|
||||
with self._lock: self._pending_import_queue_jobs.append( job )
|
||||
|
||||
|
||||
def RemovePendingImportQueue( self, job ):
|
||||
def RemovePendingImportQueueJob( self, job ):
|
||||
|
||||
with self._lock:
|
||||
|
||||
|
@ -1425,7 +1427,7 @@ class ImportController( object ):
|
|||
|
||||
|
||||
|
||||
def MovePendingImportQueueUp( self, job ):
|
||||
def MovePendingImportQueueJobUp( self, job ):
|
||||
|
||||
with self._lock:
|
||||
|
||||
|
@ -1443,7 +1445,7 @@ class ImportController( object ):
|
|||
|
||||
|
||||
|
||||
def MovePendingImportQueueDown( self, job ):
|
||||
def MovePendingImportQueueJobDown( self, job ):
|
||||
|
||||
with self._lock:
|
||||
|
||||
|
@ -1472,8 +1474,8 @@ class ImportController( object ):
|
|||
time.sleep( 0.1 )
|
||||
|
||||
self._import_job_key.Pause()
|
||||
self._import_queue_position_job_key.Pause()
|
||||
self._import_queue_job_key.Pause()
|
||||
self._import_queue_builder_job_key.Pause()
|
||||
|
||||
if HC.shutdown or self._controller_job_key.IsDone(): break
|
||||
|
||||
|
@ -1482,8 +1484,8 @@ class ImportController( object ):
|
|||
|
||||
with self._lock:
|
||||
|
||||
queue_position = self._import_queue_position_job_key.GetVariable( 'queue_position' )
|
||||
queue = self._import_queue_job_key.GetVariable( 'queue' )
|
||||
queue_position = self._import_queue_job_key.GetVariable( 'queue_position' )
|
||||
queue = self._import_queue_builder_job_key.GetVariable( 'queue' )
|
||||
|
||||
if self._import_job_key.IsDone():
|
||||
|
||||
|
@ -1499,23 +1501,23 @@ class ImportController( object ):
|
|||
|
||||
queue_position += 1
|
||||
|
||||
self._import_queue_position_job_key.SetVariable( 'queue_position', queue_position )
|
||||
self._import_queue_job_key.SetVariable( 'queue_position', queue_position )
|
||||
|
||||
|
||||
position_string = HC.u( queue_position + 1 ) + '/' + HC.u( len( queue ) )
|
||||
|
||||
if self._import_queue_position_job_key.IsPaused(): self._import_queue_position_job_key.SetVariable( 'status', 'paused at ' + position_string )
|
||||
elif self._import_queue_position_job_key.IsWorking():
|
||||
if self._import_queue_job_key.IsPaused(): self._import_queue_job_key.SetVariable( 'status', 'paused at ' + position_string )
|
||||
elif self._import_queue_job_key.IsWorking():
|
||||
|
||||
if self._import_job_key.IsWorking():
|
||||
|
||||
self._import_queue_position_job_key.SetVariable( 'status', 'processing ' + position_string )
|
||||
self._import_queue_job_key.SetVariable( 'status', 'processing ' + position_string )
|
||||
|
||||
else:
|
||||
|
||||
if queue_position < len( queue ):
|
||||
|
||||
self._import_queue_position_job_key.SetVariable( 'status', 'preparing ' + position_string )
|
||||
self._import_queue_job_key.SetVariable( 'status', 'preparing ' + position_string )
|
||||
|
||||
self._import_job_key.Begin()
|
||||
|
||||
|
@ -1527,38 +1529,38 @@ class ImportController( object ):
|
|||
|
||||
else:
|
||||
|
||||
if self._import_queue_job_key.IsWorking(): self._import_queue_position_job_key.SetVariable( 'status', 'waiting for more items' )
|
||||
else: self._import_queue_position_job_key.Finish()
|
||||
if self._import_queue_builder_job_key.IsWorking(): self._import_queue_job_key.SetVariable( 'status', 'waiting for more items' )
|
||||
else: self._import_queue_job_key.Finish()
|
||||
|
||||
|
||||
|
||||
else:
|
||||
|
||||
if self._import_queue_position_job_key.IsDone():
|
||||
if self._import_queue_job_key.IsDone():
|
||||
|
||||
if self._import_queue_position_job_key.IsCancelled(): status = 'cancelled at ' + position_string
|
||||
if self._import_queue_job_key.IsCancelled(): status = 'cancelled at ' + position_string
|
||||
else: status = 'done'
|
||||
|
||||
self._import_queue_position_job_key = self._GetNewJobKey( 'import_queue_position' )
|
||||
|
||||
self._import_queue_job_key = self._GetNewJobKey( 'import_queue' )
|
||||
|
||||
self._import_queue_builder_job_key = self._GetNewJobKey( 'import_queue_builder' )
|
||||
|
||||
else: status = ''
|
||||
|
||||
self._import_queue_position_job_key.SetVariable( 'status', status )
|
||||
self._import_queue_job_key.SetVariable( 'status', status )
|
||||
|
||||
if len( self._pending_import_queue_jobs ) > 0:
|
||||
|
||||
self._import_queue_position_job_key.Begin()
|
||||
|
||||
self._import_queue_job_key.Begin()
|
||||
|
||||
self._import_queue_builder_job_key.Begin()
|
||||
|
||||
item = self._pending_import_queue_jobs.pop( 0 )
|
||||
|
||||
queue_generator = self._import_queue_generator_factory( self._import_queue_job_key, item )
|
||||
queue_builder = self._import_queue_builder_factory( self._import_queue_builder_job_key, item )
|
||||
|
||||
# make it a daemon, not a thread job, as it has a loop!
|
||||
threading.Thread( target = queue_generator ).start()
|
||||
threading.Thread( target = queue_builder ).start()
|
||||
|
||||
|
||||
|
||||
|
@ -1570,14 +1572,14 @@ class ImportController( object ):
|
|||
finally:
|
||||
|
||||
self._import_job_key.Cancel()
|
||||
self._import_queue_position_job_key.Cancel()
|
||||
self._import_queue_job_key.Cancel()
|
||||
self._import_queue_builder_job_key.Cancel()
|
||||
|
||||
|
||||
|
||||
def StartDaemon( self ): threading.Thread( target = self.MainLoop ).start()
|
||||
|
||||
class ImportQueueGenerator( object ):
|
||||
class ImportQueueBuilder( object ):
|
||||
|
||||
def __init__( self, job_key, item ):
|
||||
|
||||
|
@ -1594,11 +1596,11 @@ class ImportQueueGenerator( object ):
|
|||
self._job_key.Finish()
|
||||
|
||||
|
||||
class ImportQueueGeneratorGallery( ImportQueueGenerator ):
|
||||
class ImportQueueBuilderGallery( ImportQueueBuilder ):
|
||||
|
||||
def __init__( self, job_key, item, downloaders_factory ):
|
||||
|
||||
ImportQueueGenerator.__init__( self, job_key, item )
|
||||
ImportQueueBuilder.__init__( self, job_key, item )
|
||||
|
||||
self._downloaders_factory = downloaders_factory
|
||||
|
||||
|
@ -1686,7 +1688,7 @@ class ImportQueueGeneratorGallery( ImportQueueGenerator ):
|
|||
finally: self._job_key.Finish()
|
||||
|
||||
|
||||
class ImportQueueGeneratorURLs( ImportQueueGenerator ):
|
||||
class ImportQueueBuilderURLs( ImportQueueBuilder ):
|
||||
|
||||
def __call__( self ):
|
||||
|
||||
|
@ -1719,7 +1721,7 @@ class ImportQueueGeneratorURLs( ImportQueueGenerator ):
|
|||
finally: self._job_key.Finish()
|
||||
|
||||
|
||||
class ImportQueueGeneratorThread( ImportQueueGenerator ):
|
||||
class ImportQueueBuilderThread( ImportQueueBuilder ):
|
||||
|
||||
def __call__( self ):
|
||||
|
||||
|
@ -1731,6 +1733,7 @@ class ImportQueueGeneratorThread( ImportQueueGenerator ):
|
|||
image_infos_already_added = set()
|
||||
|
||||
first_run = True
|
||||
manual_refresh = False
|
||||
|
||||
while True:
|
||||
|
||||
|
@ -1767,7 +1770,11 @@ class ImportQueueGeneratorThread( ImportQueueGenerator ):
|
|||
|
||||
next_thread_check = last_thread_check + thread_time
|
||||
|
||||
if next_thread_check < HC.GetNow():
|
||||
manual_refresh = self._job_key.GetVariable( 'manual_refresh' )
|
||||
|
||||
not_too_soon_for_manual_refresh = HC.GetNow() - last_thread_check > 10
|
||||
|
||||
if ( manual_refresh and not_too_soon_for_manual_refresh ) or next_thread_check < HC.GetNow():
|
||||
|
||||
self._job_key.SetVariable( 'status', 'checking thread' )
|
||||
|
||||
|
@ -1812,6 +1819,7 @@ class ImportQueueGeneratorThread( ImportQueueGenerator ):
|
|||
last_thread_check = HC.GetNow()
|
||||
|
||||
if first_run: first_run = False
|
||||
elif manual_refresh: self._job_key.SetVariable( 'manual_refresh', False )
|
||||
else:
|
||||
|
||||
if thread_times_to_check > 0: self._job_key.SetVariable( 'thread_times_to_check', thread_times_to_check - 1 )
|
||||
|
|
|
@ -29,9 +29,9 @@ class TestDownloaders( unittest.TestCase ):
|
|||
with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'da_page.html' ) as f: da_page = f.read()
|
||||
|
||||
HC.http.SetResponse( HC.GET, 'http://sakimichan.deviantart.com/gallery/?catpath=/&offset=0', da_gallery )
|
||||
HC.http.SetResponse( HC.GET, 'http://sakimichan.deviantart.com/art/Thumbs-up-411079893', da_page )
|
||||
HC.http.SetResponse( HC.GET, 'http://sakimichan.deviantart.com/art/Sailor-moon-in-PJs-506918040', da_page )
|
||||
|
||||
HC.http.SetResponse( HC.GET, 'http://fc04.deviantart.net/fs70/f/2013/306/1/5/thumbs_up_by_sakimichan-d6sqv9x.jpg', 'image file' )
|
||||
HC.http.SetResponse( HC.GET, 'http://fc00.deviantart.net/fs71/f/2015/013/3/c/3c026edbe356b22c802e7be0db6fbd0b-d8dt0go.jpg', 'image file' )
|
||||
|
||||
#
|
||||
|
||||
|
@ -41,15 +41,15 @@ class TestDownloaders( unittest.TestCase ):
|
|||
|
||||
gallery_urls = downloader.GetAnotherPage()
|
||||
|
||||
expected_gallery_urls = [('http://sakimichan.deviantart.com/art/Thumbs-up-411079893', ['title:Thumbs up', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Sci-Fi']), ('http://sakimichan.deviantart.com/art/The-Major-405852926', ['title:The Major', 'creator:akimichan', 'Fan Art', 'Cartoons & Comics', 'Digital', 'Movies & TV']), ('http://sakimichan.deviantart.com/art/Little-mermaid-fearie-401197163', ['title:Little mermaid fearie', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/Get-Em-Boy-or-not-399250537', ['title:Get Em Boy..or not', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/Welcome-To-The-Gang-398381756', ['title:Welcome To The Gang', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/Sci-Fi-Elf-398195577', ['title:Sci-Fi Elf', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Sci-Fi']), ('http://sakimichan.deviantart.com/art/Ahri-391295844', ['title:Ahri', 'creator:akimichan', 'Fan Art', 'Cartoons & Comics', 'Digital', 'Games']), ('http://sakimichan.deviantart.com/art/Orphan-386257383', ['title:Orphan', 'creator:akimichan', 'Manga & Anime', 'Digital Media', 'Drawings']), ('http://sakimichan.deviantart.com/art/The-summon-385996679', ['title:The summon', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/Rainbow2-377174679', ['title:Rainbow2', 'creator:akimichan', 'Manga & Anime', 'Digital Media', 'Drawings']), ('http://sakimichan.deviantart.com/art/Sword-Art-online-378517412', ['title:Sword Art online', 'creator:akimichan', 'Fan Art', 'Cartoons & Comics', 'Digital', 'Movies & TV']), ('http://sakimichan.deviantart.com/art/Adventure-Time-Group-photo-371913392', ['title:Adventure Time Group photo', 'creator:akimichan', 'Fan Art', 'Cartoons & Comics', 'Digital', 'Movies & TV']), ('http://sakimichan.deviantart.com/art/resurrection-353827147', ['title:resurrection', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/playful-Snow-Harpy-343275265', ['title:playful Snow Harpy', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/Link-369553015', ['title:Link', 'creator:akimichan', 'Fan Art', 'Digital Art', 'Painting & Airbrushing', 'Games']), ('http://sakimichan.deviantart.com/art/Dc-girls-363385250', ['title:Dc girls', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/Running-With-Spirits-337981944', ['title:Running With Spirits', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/FMA-358647977', ['title:FMA', 'creator:akimichan', 'Fan Art', 'Cartoons & Comics', 'Digital', 'Movies & TV']), ('http://sakimichan.deviantart.com/art/Wonder-woman-347864644', ['title:Wonder woman', 'creator:akimichan', 'Fan Art', 'Cartoons & Comics', 'Digital', 'Movies & TV']), ('http://sakimichan.deviantart.com/art/Ariel-found-Headphones-341927000', ['title:Ariel found Headphones', 'creator:akimichan', 'Fan Art', 'Cartoons & Comics', 'Digital', 'Movies & TV']), ('http://sakimichan.deviantart.com/art/Jack-Frost-340925669', ['title:Jack Frost', 'creator:akimichan', 'Fan Art', 'Cartoons & Comics', 'Digital', 'Movies & TV']), ('http://sakimichan.deviantart.com/art/Musics-blooming-336308163', ['title:Musics blooming', 'creator:akimichan', 'Digital Art', 'Drawings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/Yin-Yang-Goddess-327641961', ['title:Yin Yang Goddess', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy']), ('http://sakimichan.deviantart.com/art/Angelof-Justice-322844340', ['title:Angelof Justice', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Fantasy'])]
|
||||
expected_gallery_urls = [('http://sakimichan.deviantart.com/art/Sailor-moon-in-PJs-506918040', ['title:Sailor moon in PJs', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Johnny-Bravo-505601401', ['title:Johnny Bravo', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Daphne-505394693', ['title:Daphne !', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/kim-Possible-505195132', ['title:kim Possible', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Levi-s-evil-plan-504966437', ["title:Levi's evil plan", 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Velma-504483448', ['title:Velma', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Scoobydoo-504238131', ['title:Scoobydoo', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Kerrigan-chilling-503477012', ['title:Kerrigan chilling', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Kiki-498525851', ['title:Kiki', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Waiter-Howl-502377515', ['title:Waiter Howl', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Modern-Loki-497985045', ['title:Modern Loki', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Emma-501919103', ['title:Emma', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Lola-494941222', ['title:Lola', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Elsas-501262184', ['title:Elsas', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Tsunade-499517356', ['title:Tsunade', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/A-little-cold-out-commission-498326494', ['title:A little cold out(commission)', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Girl-496999831', ['title:Girl', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Green-elf-496797148', ['title:Green elf', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Itachi-496625357', ['title:Itachi', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Sesshomaru-495474394', ['title:Sesshomaru', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Mononoke-years-later-502160436', ['title:Mononoke years later', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Jinx-488513585', ['title:Jinx', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Alex-in-wonderland-485819661', ['title:Alex in wonderland', 'creator:sakimichan']), ('http://sakimichan.deviantart.com/art/Ariels-476991263', ['title:Ariels', 'creator:sakimichan'])]
|
||||
|
||||
self.assertEqual( gallery_urls, expected_gallery_urls )
|
||||
|
||||
#
|
||||
|
||||
tags = ['title:Thumbs up', 'creator:akimichan', 'Digital Art', 'Drawings & Paintings', 'Sci-Fi']
|
||||
tags = ['title:Sailor moon in PJs', 'creator:sakimichan']
|
||||
|
||||
info = downloader.GetFileAndTags( 'http://sakimichan.deviantart.com/art/Thumbs-up-411079893', tags )
|
||||
info = downloader.GetFileAndTags( 'http://sakimichan.deviantart.com/art/Sailor-moon-in-PJs-506918040', tags )
|
||||
|
||||
( temp_path, tags ) = info
|
||||
|
||||
|
|
|
@ -388,6 +388,153 @@ class TestTagsManager( unittest.TestCase ):
|
|||
self.assertEqual( self._other_tags_manager.GetPetitioned( self._reset_service_key ), set() )
|
||||
|
||||
|
||||
class TestTagObjects( unittest.TestCase ):
|
||||
|
||||
def test_predicates( self ):
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_TAG, 'tag' )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'tag' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', counts = { HC.CURRENT : 1, HC.PENDING : 2 } )
|
||||
|
||||
self.assertEqual( p.GetUnicode( with_count = False ), u'tag' )
|
||||
self.assertEqual( p.GetUnicode( with_count = True ), u'tag (1) (+2)' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', inclusive = False )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'-tag' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_TAG, 'tag', inclusive = False, counts = { HC.CURRENT : 1, HC.PENDING : 2 } )
|
||||
|
||||
self.assertEqual( p.GetUnicode( with_count = False ), u'-tag' )
|
||||
self.assertEqual( p.GetUnicode( with_count = True ), u'-tag (1) (+2)' )
|
||||
|
||||
#
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_AGE, ( '<', 1, 2, 3, 4 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:age < 1y2m3d4h' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_AGE, ( u'\u2248', 1, 2, 3, 4 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:age ' + u'\u2248' + ' 1y2m3d4h' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_AGE, ( '>', 1, 2, 3, 4 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:age > 1y2m3d4h' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_ARCHIVE, None ), counts = { HC.CURRENT : 1000 } )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:archive (1,000)' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_DURATION, ( '<', 1000 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:duration < 1,000' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_EVERYTHING, None ), counts = { HC.CURRENT : 2000 } )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:everything (2,000)' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_FILE_SERVICE, ( True, HC.CURRENT, HC.LOCAL_FILE_SERVICE_KEY ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:is currently in local files' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_FILE_SERVICE, ( False, HC.PENDING, HC.LOCAL_FILE_SERVICE_KEY ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:is not pending to local files' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_HASH, 'abcd'.decode( 'hex' ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:hash is abcd' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_HEIGHT, ( '<', 2000 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:height < 2,000' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_INBOX, None ), counts = { HC.CURRENT : 1000 } )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:inbox (1,000)' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_LIMIT, 2000 ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:limit is 2,000' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_LOCAL, None ), counts = { HC.CURRENT : 100 } )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:local (100)' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_MIME, HC.IMAGES ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:mime is image' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_MIME, HC.VIDEO_WEBM ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:mime is video/webm' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_NOT_LOCAL, None ), counts = { HC.CURRENT : 100 } )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:not local (100)' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_NUM_TAGS, ( '<', 2 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:number of tags < 2' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_NUM_WORDS, ( '<', 5000 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:number of words < 5,000' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_RATING, ( HC.LOCAL_FILE_SERVICE_KEY, '>', 0.2 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:rating for local files > 0.2' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_RATIO, ( '=', 16, 9 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:ratio = 16:9' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_SIMILAR_TO, ( 'abcd'.decode( 'hex' ), 5 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:similar to abcd using max hamming of 5' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_SIZE, ( '>', 5, 1048576 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:size > 5MB' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_UNTAGGED, HC.IMAGES ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:untagged' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_SYSTEM, ( HC.SYSTEM_PREDICATE_TYPE_WIDTH, ( '=', 1920 ) ) )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'system:width = 1,920' )
|
||||
|
||||
#
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_NAMESPACE, 'series' )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'series:*' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_TAG, 'series', inclusive = False )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'-series' )
|
||||
|
||||
#
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_WILDCARD, 'a*i:o*' )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'a*i:o*' )
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_TAG, 'a*i:o*', inclusive = False )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u'-a*i:o*' )
|
||||
|
||||
#
|
||||
|
||||
p = HC.Predicate( HC.PREDICATE_TYPE_PARENT, 'series:game of thrones' )
|
||||
|
||||
self.assertEqual( p.GetUnicode(), u' series:game of thrones' )
|
||||
|
||||
|
||||
class TestTagParents( unittest.TestCase ):
|
||||
|
||||
@classmethod
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue