changelog
-
+
version 180
+ - middle click on any taglist now does 'open a new search page for selection' +
- moved mouse idle checking code to the wx thread, which seems to have fixed a serious X11 crash +
- memory gunk should now be painted over when transparent animations are resized on linux +
- fixed some page up/down index calculation on the autocomplete dropdown +
- system predicates will remove themselves from the active predicate list silently again +
- system predicates will work again in queries that include tags! +
- greatly improved my string/unicode conversion code +
- dropped many inefficient unicode conversions from db code +
- improved the sql-grammar of some specifically efficient db code +
- removed incorrect unicode conversions from url/network request code +
- removed unicode conversion code from network response code +
- all directory iteration should now occur in unicode +
- all inputted paths should now be converted to unicode +
- replaced every single ugly raw path concatenation with a better method +
- improved some bitmap placeholder initialisation that was causing Linux terminal spam +
- added an option to always hide the preview window to options->gui +
- the preview window will not accept setmedia calls if it is hidden +
- if the preview window is actively hidden due to an unsplitting event, it will null its current media +
- fixed a shutdown calculation that was under-remembering the height of the preview window by four pixels every time +
- improved thumbnail waterfall code--it should be a little faster. less subject to lag when taxed, and waterfall with more genuine randomness +
- improved some thumbnail page drawing and clean/dirty conversion code +
- when pages are dirtied, any to-be-waterfalled thumbnails are cancelled, making superfast scrolling less crashtastic +
- new dirty thumbnail pages are now generated as needed, rather than precached +
- subscriptions will now correctly do a polite wait after fetching tags for redundant files +
- splash screen will now explicitly raise itself to the front on init +
- the export tag txts function of the export dialog now exports the tag txt to [filename].jpg.txt, rather than [filename].txt +
- the server now stores its updates in service specific subdirectories, like the client +
- some importers will better report when they are waiting politely +
- OS X (and anything else with OpenCV 3.0.0) now uses OpenCV to render gifs by default, falling back to PIL on error (like only Windows used to) +
- 'open externally' from thumbnails now defocusses the preview window +
- refactored away a bunch of bad global controller references +
- added some shutdownexceptions +
- silenced shutdownexception terminal spam +
- reworded the 'maintenace and processing' options panel a little to explain things better +
- improved how the base_dir is figured out on program boot +
- improved serverside 'should I clean dirty updates?' check code +
- deleted some old code +
- split path-specific functions off from HydrusFileHandling to HydrusPaths and de-looped my import tree appropriately +
- general refactoring +
version 179
- all tag listboxes support multiple selection diff --git a/include/ClientCaches.py b/include/ClientCaches.py index d0a7f1db..c2287d9f 100644 --- a/include/ClientCaches.py +++ b/include/ClientCaches.py @@ -6,6 +6,7 @@ import HydrusConstants as HC import HydrusExceptions import HydrusFileHandling import HydrusImageHandling +import HydrusPaths import os import random import Queue @@ -86,7 +87,7 @@ class DataCache( object ): with self._lock: - if key not in self._keys_to_data: raise Exception( 'Cache error! Looking for ' + HydrusData.ToString( key ) + ', but it was missing.' ) + if key not in self._keys_to_data: raise Exception( 'Cache error! Looking for ' + HydrusData.ToUnicode( key ) + ', but it was missing.' ) for ( i, ( fifo_key, last_access_time ) ) in enumerate( self._keys_fifo ): @@ -436,7 +437,12 @@ class ThumbnailCache( object ): self._data_cache = DataCache( 'thumbnail_cache_size' ) - self._queue = Queue.Queue() + self._lock = threading.Lock() + + self._waterfall_queue_quick = set() + self._waterfall_queue_random = [] + + self._waterfall_event = threading.Event() self._special_thumbs = {} @@ -447,6 +453,23 @@ class ThumbnailCache( object ): HydrusGlobals.client_controller.sub( self, 'Clear', 'thumbnail_resize' ) + def _RecalcWaterfallQueueRandom( self ): + + self._waterfall_queue_random = list( self._waterfall_queue_quick ) + + random.shuffle( self._waterfall_queue_random ) + + + def CancelWaterfall( self, page_key, medias ): + + with self._lock: + + self._waterfall_queue_quick.difference_update( ( ( page_key, media ) for media in medias ) ) + + self._RecalcWaterfallQueueRandom() + + + def Clear( self ): self._data_cache.Clear() @@ -455,13 +478,13 @@ class ThumbnailCache( object ): names = [ 'hydrus', 'flash', 'pdf', 'audio', 'video' ] - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: for name in names: - path = HC.STATIC_DIR + os.path.sep + name + '.png' + path = os.path.join( HC.STATIC_DIR, name + '.png' ) options = HydrusGlobals.client_controller.GetOptions() @@ -476,7 +499,7 @@ class ThumbnailCache( object ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) @@ -517,7 +540,17 @@ class ThumbnailCache( object ): else: return self._special_thumbs[ 'hydrus' ] - def Waterfall( self, page_key, medias ): self._queue.put( ( page_key, medias ) ) + def Waterfall( self, page_key, medias ): + + with self._lock: + + self._waterfall_queue_quick.update( ( ( page_key, media ) for media in medias ) ) + + self._RecalcWaterfallQueueRandom() + + + self._waterfall_event.set() + def DAEMONWaterfall( self ): @@ -525,25 +558,47 @@ class ThumbnailCache( object ): while not HydrusGlobals.view_shutdown: - try: ( page_key, medias ) = self._queue.get( timeout = 1 ) - except Queue.Empty: continue + with self._lock: + + do_wait = len( self._waterfall_queue_random ) == 0 + + + if do_wait: + + self._waterfall_event.wait( 1 ) + + self._waterfall_event.clear() + + last_paused = HydrusData.GetNowPrecise() + + + with self._lock: + + if len( self._waterfall_queue_random ) == 0: + + continue + + else: + + result = self._waterfall_queue_random.pop( 0 ) + + self._waterfall_queue_quick.discard( result ) + + ( page_key, media ) = result + + try: - random.shuffle( medias ) + thumbnail = self.GetThumbnail( media ) - for media in medias: + HydrusGlobals.client_controller.pub( 'waterfall_thumbnail', page_key, media, thumbnail ) + + if HydrusData.GetNowPrecise() - last_paused > 0.005: - thumbnail = self.GetThumbnail( media ) + time.sleep( 0.00001 ) - HydrusGlobals.client_controller.pub( 'waterfall_thumbnail', page_key, media, thumbnail ) - - if HydrusData.GetNowPrecise() - last_paused > 0.005: - - time.sleep( 0.00001 ) - - last_paused = HydrusData.GetNowPrecise() - + last_paused = HydrusData.GetNowPrecise() except Exception as e: diff --git a/include/ClientConstants.py b/include/ClientConstants.py index af872f00..4ee3ca68 100755 --- a/include/ClientConstants.py +++ b/include/ClientConstants.py @@ -339,63 +339,63 @@ class GlobalBMPs( object ): # these have to be created after the wxApp is instantiated, for silly GDI reasons - GlobalBMPs.bold = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_bold.png' ) - GlobalBMPs.italic = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_italic.png' ) - GlobalBMPs.underline = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_underline.png' ) + GlobalBMPs.bold = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_bold.png' ) ) + GlobalBMPs.italic = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_italic.png' ) ) + GlobalBMPs.underline = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_underline.png' ) ) - GlobalBMPs.align_left = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_align_left.png' ) - GlobalBMPs.align_center = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_align_center.png' ) - GlobalBMPs.align_right = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_align_right.png' ) - GlobalBMPs.align_justify = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_align_justify.png' ) + GlobalBMPs.align_left = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_align_left.png' ) ) + GlobalBMPs.align_center = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_align_center.png' ) ) + GlobalBMPs.align_right = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_align_right.png' ) ) + GlobalBMPs.align_justify = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_align_justify.png' ) ) - GlobalBMPs.indent_less = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_indent_remove.png' ) - GlobalBMPs.indent_more = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'text_indent.png' ) + GlobalBMPs.indent_less = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_indent_remove.png' ) ) + GlobalBMPs.indent_more = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'text_indent.png' ) ) - GlobalBMPs.font = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'font.png' ) - GlobalBMPs.colour = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'color_swatch.png' ) + GlobalBMPs.font = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'font.png' ) ) + GlobalBMPs.colour = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'color_swatch.png' ) ) - GlobalBMPs.link = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'link.png' ) - GlobalBMPs.link_break = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'link_break.png' ) + GlobalBMPs.link = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'link.png' ) ) + GlobalBMPs.link_break = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'link_break.png' ) ) - GlobalBMPs.transparent = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'transparent.png' ) - GlobalBMPs.downloading = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'downloading.png' ) - GlobalBMPs.file_repository = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'file_repository_small.png' ) - GlobalBMPs.file_repository_pending = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'file_repository_pending_small.png' ) - GlobalBMPs.file_repository_petitioned = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'file_repository_petitioned_small.png' ) + GlobalBMPs.transparent = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'transparent.png' ) ) + GlobalBMPs.downloading = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'downloading.png' ) ) + GlobalBMPs.file_repository = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'file_repository_small.png' ) ) + GlobalBMPs.file_repository_pending = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'file_repository_pending_small.png' ) ) + GlobalBMPs.file_repository_petitioned = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'file_repository_petitioned_small.png' ) ) - GlobalBMPs.collection = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'collection.png' ) - GlobalBMPs.inbox = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'inbox.png' ) - GlobalBMPs.trash = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'trash.png' ) + GlobalBMPs.collection = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'collection.png' ) ) + GlobalBMPs.inbox = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'inbox.png' ) ) + GlobalBMPs.trash = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'trash.png' ) ) - GlobalBMPs.archive = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'archive.png' ) - GlobalBMPs.to_inbox = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'to_inbox.png' ) - GlobalBMPs.delete = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'trash.png' ) - GlobalBMPs.trash_delete = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'delete.png' ) - GlobalBMPs.undelete = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'undelete.png' ) - GlobalBMPs.zoom_in = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'zoom_in.png' ) - GlobalBMPs.zoom_out = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'zoom_out.png' ) - GlobalBMPs.zoom_switch = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'zoom_switch.png' ) - GlobalBMPs.fullscreen_switch = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'fullscreen_switch.png' ) - GlobalBMPs.open_externally = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'open_externally.png' ) + GlobalBMPs.archive = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'archive.png' ) ) + GlobalBMPs.to_inbox = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'to_inbox.png' ) ) + GlobalBMPs.delete = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'trash.png' ) ) + GlobalBMPs.trash_delete = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'delete.png' ) ) + GlobalBMPs.undelete = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'undelete.png' ) ) + GlobalBMPs.zoom_in = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'zoom_in.png' ) ) + GlobalBMPs.zoom_out = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'zoom_out.png' ) ) + GlobalBMPs.zoom_switch = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'zoom_switch.png' ) ) + GlobalBMPs.fullscreen_switch = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'fullscreen_switch.png' ) ) + GlobalBMPs.open_externally = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'open_externally.png' ) ) - GlobalBMPs.dump_ok = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'dump_ok.png' ) - GlobalBMPs.dump_recoverable = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'dump_recoverable.png' ) - GlobalBMPs.dump_fail = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'dump_fail.png' ) + GlobalBMPs.dump_ok = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'dump_ok.png' ) ) + GlobalBMPs.dump_recoverable = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'dump_recoverable.png' ) ) + GlobalBMPs.dump_fail = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'dump_fail.png' ) ) - GlobalBMPs.pause = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'pause.png' ) - GlobalBMPs.play = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'play.png' ) - GlobalBMPs.stop = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'stop.png' ) + GlobalBMPs.pause = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'pause.png' ) ) + GlobalBMPs.play = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'play.png' ) ) + GlobalBMPs.stop = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'stop.png' ) ) - GlobalBMPs.seed_cache = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'seed_cache.png' ) + GlobalBMPs.seed_cache = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'seed_cache.png' ) ) - GlobalBMPs.eight_chan = wx.Bitmap( HC.STATIC_DIR + os.path.sep + '8chan.png' ) - GlobalBMPs.twitter = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'twitter.png' ) - GlobalBMPs.tumblr = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'tumblr.png' ) + GlobalBMPs.eight_chan = wx.Bitmap( os.path.join( HC.STATIC_DIR, '8chan.png' ) ) + GlobalBMPs.twitter = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'twitter.png' ) ) + GlobalBMPs.tumblr = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'tumblr.png' ) ) - GlobalBMPs.first = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'first.png' ) - GlobalBMPs.previous = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'previous.png' ) - GlobalBMPs.next = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'next.png' ) - GlobalBMPs.last = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'last.png' ) + GlobalBMPs.first = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'first.png' ) ) + GlobalBMPs.previous = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'previous.png' ) ) + GlobalBMPs.next = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'next.png' ) ) + GlobalBMPs.last = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'last.png' ) ) LOCAL_TAG_SERVICE_KEY = 'local tags' diff --git a/include/ClientController.py b/include/ClientController.py index 715d610a..a8038771 100755 --- a/include/ClientController.py +++ b/include/ClientController.py @@ -57,7 +57,7 @@ class Controller( HydrusController.HydrusController ): if dlg.ShowModal() == wx.ID_OK: - path = dlg.GetPath() + path = HydrusData.ToUnicode( dlg.GetPath() ) text = 'Are you sure "' + path + '" is the correct directory?' text += os.linesep * 2 @@ -104,7 +104,10 @@ class Controller( HydrusController.HydrusController ): while not job_key.IsDone(): - if HydrusGlobals.model_shutdown: return + if self._model_shutdown: + + return + time.sleep( 0.05 ) @@ -342,7 +345,7 @@ class Controller( HydrusController.HydrusController ): try: - self._splash = ClientGUI.FrameSplash() + self._splash = ClientGUI.FrameSplash( self ) except Exception as e: @@ -468,7 +471,7 @@ class Controller( HydrusController.HydrusController ): def wx_code_gui(): - self._gui = ClientGUI.FrameGUI() + self._gui = ClientGUI.FrameGUI( self ) # this is because of some bug in wx C++ that doesn't add these by default wx.richtext.RichTextBuffer.AddHandler( wx.richtext.RichTextHTMLHandler() ) @@ -500,7 +503,7 @@ class Controller( HydrusController.HydrusController ): self._daemons.append( HydrusThreading.DAEMONQueue( self, 'FlushRepositoryUpdates', ClientDaemons.DAEMONFlushServiceUpdates, 'service_updates_delayed', period = 5 ) ) if HydrusGlobals.is_first_start: wx.CallAfter( self._gui.DoFirstStart ) - if HydrusGlobals.is_db_updated: wx.CallLater( 1, HydrusData.ShowText, 'The client has updated to version ' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + '!' ) + if HydrusGlobals.is_db_updated: wx.CallLater( 1, HydrusData.ShowText, 'The client has updated to version ' + str( HC.SOFTWARE_VERSION ) + '!' ) def MaintainDB( self ): @@ -602,7 +605,7 @@ class Controller( HydrusController.HydrusController ): connection = HydrusNetworking.GetLocalConnection( port ) connection.close() - text = 'The client\'s booru server could not start because something was already bound to port ' + HydrusData.ToString( port ) + '.' + text = 'The client\'s booru server could not start because something was already bound to port ' + str( port ) + '.' text += os.linesep * 2 text += 'This usually means another hydrus client is already running and occupying that port. It could be a previous instantiation of this client that has yet to shut itself down.' text += os.linesep * 2 @@ -621,9 +624,9 @@ class Controller( HydrusController.HydrusController ): except Exception as e: - text = 'Tried to bind port ' + HydrusData.ToString( port ) + ' for the local booru, but it failed:' + text = 'Tried to bind port ' + str( port ) + ' for the local booru, but it failed:' text += os.linesep * 2 - text += HydrusData.ToString( e ) + text += HydrusData.ToUnicode( e ) wx.CallLater( 1, HydrusData.ShowText, text ) @@ -662,7 +665,7 @@ class Controller( HydrusController.HydrusController ): connection = HydrusNetworking.GetLocalConnection( port ) connection.close() - text = 'The client\'s local server could not start because something was already bound to port ' + HydrusData.ToString( port ) + '.' + text = 'The client\'s local server could not start because something was already bound to port ' + str( port ) + '.' text += os.linesep * 2 text += 'This usually means another hydrus client is already running and occupying that port. It could be a previous instantiation of this client that has yet to shut itself down.' text += os.linesep * 2 @@ -681,9 +684,9 @@ class Controller( HydrusController.HydrusController ): except Exception as e: - text = 'Tried to bind port ' + HydrusData.ToString( port ) + ' for the local server, but it failed:' + text = 'Tried to bind port ' + str( port ) + ' for the local server, but it failed:' text += os.linesep * 2 - text += HydrusData.ToString( e ) + text += HydrusData.ToUnicode( e ) wx.CallLater( 1, HydrusData.ShowText, text ) @@ -713,7 +716,7 @@ class Controller( HydrusController.HydrusController ): if dlg.ShowModal() == wx.ID_OK: - path = dlg.GetPath() + path = HydrusData.ToUnicode( dlg.GetPath() ) text = 'Are you sure you want to restore a backup from "' + path + '"?' text += os.linesep * 2 @@ -758,7 +761,7 @@ class Controller( HydrusController.HydrusController ): try: - self._splash = ClientGUI.FrameSplash() + self._splash = ClientGUI.FrameSplash( self ) except: diff --git a/include/ClientDB.py b/include/ClientDB.py index a7f015c8..508707e2 100755 --- a/include/ClientDB.py +++ b/include/ClientDB.py @@ -17,6 +17,7 @@ import HydrusExceptions import HydrusFileHandling import HydrusImageHandling import HydrusNATPunch +import HydrusPaths import HydrusSerialisable import HydrusServer import HydrusTagArchive @@ -107,7 +108,7 @@ class MessageDB( object ): for file in files: - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -119,7 +120,7 @@ class MessageDB( object ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) @@ -294,7 +295,7 @@ class MessageDB( object ): else: - sql_predicates = [ '( contact_id_from = ' + HydrusData.ToString( contact_id ) + ' OR contact_id_to = ' + HydrusData.ToString( contact_id ) + ' )' ] + sql_predicates = [ '( contact_id_from = ' + str( contact_id ) + ' OR contact_id_to = ' + str( contact_id ) + ' )' ] if name != 'Anonymous': @@ -309,32 +310,32 @@ class MessageDB( object ): status_id = self._GetStatusId( status ) - sql_predicates.append( '( contact_id_to = ' + HydrusData.ToString( contact_id ) + ' AND status_id = ' + HydrusData.ToString( status_id ) + ')' ) + sql_predicates.append( '( contact_id_to = ' + str( contact_id ) + ' AND status_id = ' + str( status_id ) + ')' ) if contact_from is not None: contact_id_from = self._GetContactId( contact_from ) - sql_predicates.append( 'contact_id_from = ' + HydrusData.ToString( contact_id_from ) ) + sql_predicates.append( 'contact_id_from = ' + str( contact_id_from ) ) if contact_to is not None: contact_id_to = self._GetContactId( contact_to ) - sql_predicates.append( 'contact_id_to = ' + HydrusData.ToString( contact_id_to ) ) + sql_predicates.append( 'contact_id_to = ' + str( contact_id_to ) ) if contact_started is not None: contact_id_started = self._GetContactId( contact_started ) - sql_predicates.append( 'conversation_id = message_id AND contact_id_from = ' + HydrusData.ToString( contact_id_started ) ) + sql_predicates.append( 'conversation_id = message_id AND contact_id_from = ' + str( contact_id_started ) ) - if min_timestamp is not None: sql_predicates.append( 'timestamp >= ' + HydrusData.ToString( min_timestamp ) ) - if max_timestamp is not None: sql_predicates.append( 'timestamp <= ' + HydrusData.ToString( max_timestamp ) ) + if min_timestamp is not None: sql_predicates.append( 'timestamp >= ' + str( min_timestamp ) ) + if max_timestamp is not None: sql_predicates.append( 'timestamp <= ' + str( max_timestamp ) ) query_message_ids = { message_id for ( message_id, ) in self._c.execute( 'SELECT message_id FROM messages, message_destination_map USING ( message_id ) WHERE ' + ' AND '.join( sql_predicates ) + ';' ) } @@ -375,7 +376,7 @@ class MessageDB( object ): num_inbox = len( convo_ids ) if num_inbox == 0: inbox_string = 'message inbox empty' - else: inbox_string = HydrusData.ToString( num_inbox ) + ' in message inbox' + else: inbox_string = str( num_inbox ) + ' in message inbox' self.pub_after_commit( 'inbox_status', inbox_string ) @@ -491,7 +492,7 @@ class MessageDB( object ): # we have a new contact from an outside source! # let's generate a name that'll fit into the db - while self._c.execute( 'SELECT 1 FROM contacts WHERE name = ?;', ( name, ) ).fetchone() is not None: name += HydrusData.ToString( random.randint( 0, 9 ) ) + while self._c.execute( 'SELECT 1 FROM contacts WHERE name = ?;', ( name, ) ).fetchone() is not None: name += str( random.randint( 0, 9 ) ) else: @@ -1185,18 +1186,18 @@ class DB( HydrusDB.HydrusDB ): for deletee_filename in deletee_filenames: - deletee_path = path + os.path.sep + deletee_filename + deletee_path = os.path.join( path, deletee_filename ) ClientData.DeletePath( deletee_path ) - shutil.copy( self._db_path, path + os.path.sep + 'client.db' ) - if os.path.exists( self._db_path + '-wal' ): shutil.copy( self._db_path + '-wal', path + os.path.sep + 'client.db-wal' ) + shutil.copy( self._db_path, os.path.join( path, 'client.db' ) ) + if os.path.exists( self._db_path + '-wal' ): shutil.copy( self._db_path + '-wal', os.path.join( path, 'client.db-wal' ) ) - shutil.copytree( HC.CLIENT_ARCHIVES_DIR, path + os.path.sep + 'client_archives' ) - shutil.copytree( HC.CLIENT_FILES_DIR, path + os.path.sep + 'client_files' ) - shutil.copytree( HC.CLIENT_THUMBNAILS_DIR, path + os.path.sep + 'client_thumbnails' ) - shutil.copytree( HC.CLIENT_UPDATES_DIR, path + os.path.sep + 'client_updates' ) + shutil.copytree( HC.CLIENT_ARCHIVES_DIR, os.path.join( path, 'client_archives' ) ) + shutil.copytree( HC.CLIENT_FILES_DIR, os.path.join( path, 'client_files' ) ) + shutil.copytree( HC.CLIENT_THUMBNAILS_DIR, os.path.join( path, 'client_thumbnails' ) ) + shutil.copytree( HC.CLIENT_UPDATES_DIR, os.path.join( path, 'client_updates' ) ) HydrusData.ShowText( 'Database backup done!' ) @@ -1300,7 +1301,9 @@ class DB( HydrusDB.HydrusDB ): if move_location is not None: - move_path = move_location + os.path.sep + 'believed ' + hash.encode( 'hex' ) + ' actually ' + actual_hash.encode( 'hex' ) + HC.mime_ext_lookup[ mime ] + move_filename = 'believed ' + hash.encode( 'hex' ) + ' actually ' + actual_hash.encode( 'hex' ) + HC.mime_ext_lookup[ mime ] + + move_path = os.path.join( move_location, move_filename ) shutil.move( path, move_path ) @@ -1375,7 +1378,7 @@ class DB( HydrusDB.HydrusDB ): except Exception as e: - error_messages.add( HydrusData.ToString( e ) ) + error_messages.add( HydrusData.ToUnicode( e ) ) @@ -1398,11 +1401,11 @@ class DB( HydrusDB.HydrusDB ): for ( one, two ) in itertools.product( hex_chars, hex_chars ): - dir = HC.CLIENT_FILES_DIR + os.path.sep + one + two + dir = os.path.join( HC.CLIENT_FILES_DIR, one + two ) if not os.path.exists( dir ): os.mkdir( dir ) - dir = HC.CLIENT_THUMBNAILS_DIR + os.path.sep + one + two + dir = os.path.join( HC.CLIENT_THUMBNAILS_DIR, one + two ) if not os.path.exists( dir ): os.mkdir( dir ) @@ -1413,7 +1416,7 @@ class DB( HydrusDB.HydrusDB ): try: self._c.execute( 'BEGIN IMMEDIATE' ) except Exception as e: - raise HydrusExceptions.DBAccessException( HydrusData.ToString( e ) ) + raise HydrusExceptions.DBAccessException( HydrusData.ToUnicode( e ) ) self._c.execute( 'CREATE TABLE services ( service_id INTEGER PRIMARY KEY, service_key BLOB_BYTES, service_type INTEGER, name TEXT, info TEXT_YAML );' ) @@ -2072,7 +2075,7 @@ class DB( HydrusDB.HydrusDB ): ( namespace_id, ) = result - predicates_phrase_1 = 'namespace_id = ' + HydrusData.ToString( namespace_id ) + predicates_phrase_1 = 'namespace_id = ' + str( namespace_id ) @@ -2094,8 +2097,8 @@ class DB( HydrusDB.HydrusDB ): ( namespace_id, tag_id ) = self._GetNamespaceIdTagId( tag ) - if ':' in tag: predicates_phrase = 'namespace_id = ' + HydrusData.ToString( namespace_id ) + ' AND tag_id = ' + HydrusData.ToString( tag_id ) - else: predicates_phrase = 'tag_id = ' + HydrusData.ToString( tag_id ) + if ':' in tag: predicates_phrase = 'namespace_id = ' + str( namespace_id ) + ' AND tag_id = ' + str( tag_id ) + else: predicates_phrase = 'tag_id = ' + str( tag_id ) except: predicates_phrase = '1 = 1' @@ -2152,7 +2155,7 @@ class DB( HydrusDB.HydrusDB ): count_phrase = 'SELECT tag_id, COUNT( * ) FROM ' - predicates.append( 'mappings.service_id = ' + HydrusData.ToString( tag_service_id ) ) + predicates.append( 'mappings.service_id = ' + str( tag_service_id ) ) if file_service_key == CC.COMBINED_FILE_SERVICE_KEY: @@ -2163,7 +2166,7 @@ class DB( HydrusDB.HydrusDB ): table_phrase = 'mappings, files_info USING ( hash_id ) ' - predicates.append( 'files_info.service_id = ' + HydrusData.ToString( file_service_id ) ) + predicates.append( 'files_info.service_id = ' + str( file_service_id ) ) predicates_phrase = 'WHERE ' + ' AND '.join( predicates ) + ' AND ' @@ -2417,14 +2420,14 @@ class DB( HydrusDB.HydrusDB ): file_service_id = self._GetServiceId( file_service_key ) - predicates.append( 'files_info.service_id = ' + HydrusData.ToString( file_service_id ) ) + predicates.append( 'files_info.service_id = ' + str( file_service_id ) ) if tag_service_key != CC.COMBINED_TAG_SERVICE_KEY: tag_service_id = self._GetServiceId( tag_service_key ) - predicates.append( 'mappings.service_id = ' + HydrusData.ToString( tag_service_id ) ) + predicates.append( 'mappings.service_id = ' + str( tag_service_id ) ) if len( predicates ) > 0: predicates_phrase = ' AND '.join( predicates ) + ' AND ' @@ -2471,9 +2474,9 @@ class DB( HydrusDB.HydrusDB ): simple_preds = system_predicates.GetSimpleInfo() - if 'min_size' in simple_preds: sql_predicates.append( 'size > ' + HydrusData.ToString( simple_preds[ 'min_size' ] ) ) - if 'size' in simple_preds: sql_predicates.append( 'size = ' + HydrusData.ToString( simple_preds[ 'size' ] ) ) - if 'max_size' in simple_preds: sql_predicates.append( 'size < ' + HydrusData.ToString( simple_preds[ 'max_size' ] ) ) + if 'min_size' in simple_preds: sql_predicates.append( 'size > ' + str( simple_preds[ 'min_size' ] ) ) + if 'size' in simple_preds: sql_predicates.append( 'size = ' + str( simple_preds[ 'size' ] ) ) + if 'max_size' in simple_preds: sql_predicates.append( 'size < ' + str( simple_preds[ 'max_size' ] ) ) if 'mimes' in simple_preds: @@ -2483,75 +2486,75 @@ class DB( HydrusDB.HydrusDB ): ( mime, ) = mimes - sql_predicates.append( 'mime = ' + HydrusData.ToString( mime ) ) + sql_predicates.append( 'mime = ' + str( mime ) ) else: sql_predicates.append( 'mime IN ' + HydrusData.SplayListForDB( mimes ) ) - if 'min_timestamp' in simple_preds: sql_predicates.append( 'timestamp >= ' + HydrusData.ToString( simple_preds[ 'min_timestamp' ] ) ) - if 'max_timestamp' in simple_preds: sql_predicates.append( 'timestamp <= ' + HydrusData.ToString( simple_preds[ 'max_timestamp' ] ) ) + if 'min_timestamp' in simple_preds: sql_predicates.append( 'timestamp >= ' + str( simple_preds[ 'min_timestamp' ] ) ) + if 'max_timestamp' in simple_preds: sql_predicates.append( 'timestamp <= ' + str( simple_preds[ 'max_timestamp' ] ) ) - if 'min_width' in simple_preds: sql_predicates.append( 'width > ' + HydrusData.ToString( simple_preds[ 'min_width' ] ) ) - if 'width' in simple_preds: sql_predicates.append( 'width = ' + HydrusData.ToString( simple_preds[ 'width' ] ) ) - if 'max_width' in simple_preds: sql_predicates.append( 'width < ' + HydrusData.ToString( simple_preds[ 'max_width' ] ) ) + if 'min_width' in simple_preds: sql_predicates.append( 'width > ' + str( simple_preds[ 'min_width' ] ) ) + if 'width' in simple_preds: sql_predicates.append( 'width = ' + str( simple_preds[ 'width' ] ) ) + if 'max_width' in simple_preds: sql_predicates.append( 'width < ' + str( simple_preds[ 'max_width' ] ) ) - if 'min_height' in simple_preds: sql_predicates.append( 'height > ' + HydrusData.ToString( simple_preds[ 'min_height' ] ) ) - if 'height' in simple_preds: sql_predicates.append( 'height = ' + HydrusData.ToString( simple_preds[ 'height' ] ) ) - if 'max_height' in simple_preds: sql_predicates.append( 'height < ' + HydrusData.ToString( simple_preds[ 'max_height' ] ) ) + if 'min_height' in simple_preds: sql_predicates.append( 'height > ' + str( simple_preds[ 'min_height' ] ) ) + if 'height' in simple_preds: sql_predicates.append( 'height = ' + str( simple_preds[ 'height' ] ) ) + if 'max_height' in simple_preds: sql_predicates.append( 'height < ' + str( simple_preds[ 'max_height' ] ) ) - if 'min_num_pixels' in simple_preds: sql_predicates.append( 'width * height > ' + HydrusData.ToString( simple_preds[ 'min_num_pixels' ] ) ) - if 'num_pixels' in simple_preds: sql_predicates.append( 'width * height = ' + HydrusData.ToString( simple_preds[ 'num_pixels' ] ) ) - if 'max_num_pixels' in simple_preds: sql_predicates.append( 'width * height < ' + HydrusData.ToString( simple_preds[ 'max_num_pixels' ] ) ) + if 'min_num_pixels' in simple_preds: sql_predicates.append( 'width * height > ' + str( simple_preds[ 'min_num_pixels' ] ) ) + if 'num_pixels' in simple_preds: sql_predicates.append( 'width * height = ' + str( simple_preds[ 'num_pixels' ] ) ) + if 'max_num_pixels' in simple_preds: sql_predicates.append( 'width * height < ' + str( simple_preds[ 'max_num_pixels' ] ) ) if 'min_ratio' in simple_preds: ( ratio_width, ratio_height ) = simple_preds[ 'min_ratio' ] - sql_predicates.append( '( width * 1.0 ) / height > ' + HydrusData.ToString( float( ratio_width ) ) + ' / ' + HydrusData.ToString( ratio_height ) ) + sql_predicates.append( '( width * 1.0 ) / height > ' + str( float( ratio_width ) ) + ' / ' + str( ratio_height ) ) if 'ratio' in simple_preds: ( ratio_width, ratio_height ) = simple_preds[ 'ratio' ] - sql_predicates.append( '( width * 1.0 ) / height = ' + HydrusData.ToString( float( ratio_width ) ) + ' / ' + HydrusData.ToString( ratio_height ) ) + sql_predicates.append( '( width * 1.0 ) / height = ' + str( float( ratio_width ) ) + ' / ' + str( ratio_height ) ) if 'max_ratio' in simple_preds: ( ratio_width, ratio_height ) = simple_preds[ 'max_ratio' ] - sql_predicates.append( '( width * 1.0 ) / height < ' + HydrusData.ToString( float( ratio_width ) ) + ' / ' + HydrusData.ToString( ratio_height ) ) + sql_predicates.append( '( width * 1.0 ) / height < ' + str( float( ratio_width ) ) + ' / ' + str( ratio_height ) ) - if 'min_num_words' in simple_preds: sql_predicates.append( 'num_words > ' + HydrusData.ToString( simple_preds[ 'min_num_words' ] ) ) + if 'min_num_words' in simple_preds: sql_predicates.append( 'num_words > ' + str( simple_preds[ 'min_num_words' ] ) ) if 'num_words' in simple_preds: num_words = simple_preds[ 'num_words' ] if num_words == 0: sql_predicates.append( '( num_words IS NULL OR num_words = 0 )' ) - else: sql_predicates.append( 'num_words = ' + HydrusData.ToString( num_words ) ) + else: sql_predicates.append( 'num_words = ' + str( num_words ) ) if 'max_num_words' in simple_preds: max_num_words = simple_preds[ 'max_num_words' ] - if max_num_words == 0: sql_predicates.append( 'num_words < ' + HydrusData.ToString( max_num_words ) ) - else: sql_predicates.append( '( num_words < ' + HydrusData.ToString( max_num_words ) + ' OR num_words IS NULL )' ) + if max_num_words == 0: sql_predicates.append( 'num_words < ' + str( max_num_words ) ) + else: sql_predicates.append( '( num_words < ' + str( max_num_words ) + ' OR num_words IS NULL )' ) - if 'min_duration' in simple_preds: sql_predicates.append( 'duration > ' + HydrusData.ToString( simple_preds[ 'min_duration' ] ) ) + if 'min_duration' in simple_preds: sql_predicates.append( 'duration > ' + str( simple_preds[ 'min_duration' ] ) ) if 'duration' in simple_preds: duration = simple_preds[ 'duration' ] if duration == 0: sql_predicates.append( '( duration IS NULL OR duration = 0 )' ) - else: sql_predicates.append( 'duration = ' + HydrusData.ToString( duration ) ) + else: sql_predicates.append( 'duration = ' + str( duration ) ) if 'max_duration' in simple_preds: max_duration = simple_preds[ 'max_duration' ] - if max_duration == 0: sql_predicates.append( 'duration < ' + HydrusData.ToString( max_duration ) ) - else: sql_predicates.append( '( duration < ' + HydrusData.ToString( max_duration ) + ' OR duration IS NULL )' ) + if max_duration == 0: sql_predicates.append( 'duration < ' + str( max_duration ) ) + else: sql_predicates.append( '( duration < ' + str( max_duration ) + ' OR duration IS NULL )' ) if len( tags_to_include ) > 0 or len( namespaces_to_include ) > 0 or len( wildcards_to_include ) > 0: @@ -2579,6 +2582,11 @@ class DB( HydrusDB.HydrusDB ): else: query_hash_ids.intersection_update( wildcard_query_hash_ids ) + if len( sql_predicates ) > 0: + + query_hash_ids.intersection_update( [ id for ( id, ) in self._c.execute( 'SELECT hash_id FROM files_info WHERE ' + ' AND '.join( sql_predicates ) + ';' ) ] ) + + else: if file_service_key != CC.COMBINED_FILE_SERVICE_KEY: @@ -2598,7 +2606,7 @@ class DB( HydrusDB.HydrusDB ): query_hash_ids = { id for ( id, ) in self._c.execute( 'SELECT DISTINCT hash_id FROM mappings UNION SELECT hash_id FROM files_info;' ) } - if len( sql_predicates ) > 1: + if len( sql_predicates ) > 0: query_hash_ids.intersection_update( [ id for ( id, ) in self._c.execute( 'SELECT hash_id FROM files_info WHERE ' + ' AND '.join( sql_predicates ) + ';' ) ] ) @@ -2687,8 +2695,8 @@ class DB( HydrusDB.HydrusDB ): elif value == 'not rated': query_hash_ids.difference_update( [ hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM local_ratings WHERE service_id = ?;', ( service_id, ) ) ] ) else: - if operator == u'\u2248': predicate = HydrusData.ToString( value * 0.95 ) + ' < rating AND rating < ' + HydrusData.ToString( value * 1.05 ) - else: predicate = 'rating ' + operator + ' ' + HydrusData.ToString( value ) + if operator == u'\u2248': predicate = str( value * 0.95 ) + ' < rating AND rating < ' + str( value * 1.05 ) + else: predicate = 'rating ' + operator + ' ' + str( value ) query_hash_ids.intersection_update( [ hash_id for ( hash_id, ) in self._c.execute( 'SELECT hash_id FROM local_ratings WHERE service_id = ? AND ' + predicate + ';', ( service_id, ) ) ] ) @@ -2782,7 +2790,7 @@ class DB( HydrusDB.HydrusDB ): tag_predicates_care_about_zero_counts = len( tag_predicates ) > 0 and False not in ( pred( 0 ) for pred in tag_predicates ) if tag_service_key == CC.COMBINED_TAG_SERVICE_KEY: service_phrase = '' - else: service_phrase = 'service_id = ' + HydrusData.ToString( tag_service_id ) + ' AND ' + else: service_phrase = 'service_id = ' + str( tag_service_id ) + ' AND ' if num_tags_zero or num_tags_nonzero or tag_predicates_care_about_zero_counts: @@ -2849,14 +2857,14 @@ class DB( HydrusDB.HydrusDB ): file_service_id = self._GetServiceId( file_service_key ) - predicates.append( 'files_info.service_id = ' + HydrusData.ToString( file_service_id ) ) + predicates.append( 'files_info.service_id = ' + str( file_service_id ) ) if tag_service_key != CC.COMBINED_TAG_SERVICE_KEY: tag_service_id = self._GetServiceId( tag_service_key ) - predicates.append( 'mappings.service_id = ' + HydrusData.ToString( tag_service_id ) ) + predicates.append( 'mappings.service_id = ' + str( tag_service_id ) ) if len( predicates ) > 0: predicates_phrase = ' AND '.join( predicates ) + ' AND ' @@ -2903,14 +2911,14 @@ class DB( HydrusDB.HydrusDB ): file_service_id = self._GetServiceId( file_service_key ) - predicates.append( 'files_info.service_id = ' + HydrusData.ToString( file_service_id ) ) + predicates.append( 'files_info.service_id = ' + str( file_service_id ) ) if tag_service_key != CC.COMBINED_TAG_SERVICE_KEY: tag_service_id = self._GetServiceId( tag_service_key ) - predicates.append( 'mappings.service_id = ' + HydrusData.ToString( tag_service_id ) ) + predicates.append( 'mappings.service_id = ' + str( tag_service_id ) ) if len( predicates ) > 0: predicates_phrase = ' AND '.join( predicates ) + ' AND ' @@ -4142,7 +4150,7 @@ class DB( HydrusDB.HydrusDB ): try: - hta = HydrusTagArchive.HydrusTagArchive( HC.CLIENT_ARCHIVES_DIR + os.path.sep + filename ) + hta = HydrusTagArchive.HydrusTagArchive( os.path.join( HC.CLIENT_ARCHIVES_DIR, filename ) ) archive_name = filename[:-3] @@ -4183,7 +4191,7 @@ class DB( HydrusDB.HydrusDB ): db_traceback = os.linesep.join( traceback.format_exception( etype, value, tb ) ) - new_e = HydrusExceptions.DBException( HydrusData.ToString( e ), 'Unknown Caller, probably GUI.', db_traceback ) + new_e = HydrusExceptions.DBException( HydrusData.ToUnicode( e ), 'Unknown Caller, probably GUI.', db_traceback ) if job.IsSynchronous(): job.PutResult( new_e ) else: HydrusData.ShowException( new_e ) @@ -4922,20 +4930,6 @@ class DB( HydrusDB.HydrusDB ): return result - def _RecalcCombinedMappings( self ): - - self._c.execute( 'DELETE FROM mappings WHERE service_id = ?;', ( self._combined_tag_service_id, ) ) - - service_ids = self._GetServiceIds( ( HC.LOCAL_TAG, HC.TAG_REPOSITORY ) ) - - for service_id in service_ids: - - self._c.execute( 'INSERT OR IGNORE INTO mappings SELECT ?, namespace_id, tag_id, hash_id, status FROM mappings INDEXED BY mappings_service_id_status_index WHERE service_id = ? AND status IN ( ?, ? );', ( self._combined_tag_service_id, service_id, HC.CURRENT, HC.PENDING ) ) - - - self._c.execute( 'DELETE FROM autocomplete_tags_cache WHERE tag_service_id = ?;', ( self._combined_tag_service_id, ) ) - - def _ResetService( self, service_key, delete_updates = False ): service_id = self._GetServiceId( service_key ) @@ -5240,56 +5234,7 @@ class DB( HydrusDB.HydrusDB ): def _UpdateDB( self, version ): - self._controller.pub( 'splash_set_title_text', 'updating db to v' + HydrusData.ToString( version + 1 ) ) - - if version == 125: - - options = self._GetOptions() - - options[ 'default_tag_repository' ] = options[ 'default_tag_repository' ].GetServiceKey() - - self._c.execute( 'UPDATE options SET options = ?;', ( options, ) ) - - # - - results = self._c.execute( 'SELECT * FROM yaml_dumps WHERE dump_type = ?;', ( YAML_DUMP_ID_SUBSCRIPTION, ) ).fetchall() - - for ( dump_type, dump_name, dump ) in results: - - advanced_tag_options = dump[ 'advanced_tag_options' ] - - new_advanced_tag_options = {} - - for ( service_identifier, namespaces ) in advanced_tag_options: - - new_advanced_tag_options[ service_identifier.GetServiceKey() ] = namespaces - - - dump[ 'advanced_tag_options' ] = new_advanced_tag_options - - self._c.execute( 'UPDATE yaml_dumps SET dump = ? WHERE dump_type = ? and dump_name = ?;', ( dump, dump_type, dump_name ) ) - - - - if version == 126: - - self._c.execute( 'DELETE FROM yaml_dumps WHERE dump_type = ?;', ( YAML_DUMP_ID_GUI_SESSION, ) ) - - - if version == 130: - - self._c.execute( 'DROP TABLE tag_service_precedence;' ) - - # - - self._combined_tag_service_id = self._GetServiceId( CC.COMBINED_TAG_SERVICE_KEY ) # needed for recalccombinedmappings - - service_ids = self._GetServiceIds( ( HC.LOCAL_TAG, HC.TAG_REPOSITORY, HC.COMBINED_TAG ) ) - - for service_id in service_ids: self._c.execute( 'DELETE FROM service_info WHERE service_id = ?;', ( service_id, ) ) - - self._RecalcCombinedMappings() - + self._controller.pub( 'splash_set_title_text', 'updating db to v' + str( version + 1 ) ) if version == 131: @@ -5351,7 +5296,7 @@ class DB( HydrusDB.HydrusDB ): with open( path, 'rb' ) as f: - for block in HydrusData.ReadFileLikeAsBlocks( f ): h_sha512.update( block ) + for block in HydrusPaths.ReadFileLikeAsBlocks( f ): h_sha512.update( block ) sha512 = h_sha512.digest() @@ -5618,7 +5563,7 @@ class DB( HydrusDB.HydrusDB ): for filename in os.listdir( HC.CLIENT_UPDATES_DIR ): - path = HC.CLIENT_UPDATES_DIR + os.path.sep + filename + path = os.path.join( HC.CLIENT_UPDATES_DIR, filename ) ClientData.DeletePath( path ) @@ -5652,7 +5597,7 @@ class DB( HydrusDB.HydrusDB ): for filename in os.listdir( HC.CLIENT_UPDATES_DIR ): - path = HC.CLIENT_UPDATES_DIR + os.path.sep + filename + path = os.path.join( HC.CLIENT_UPDATES_DIR, filename ) with open( path, 'rb' ) as f: @@ -5778,15 +5723,15 @@ class DB( HydrusDB.HydrusDB ): continue - dest_dir = HC.CLIENT_UPDATES_DIR + os.path.sep + service_key_encoded + dest_dir = os.path.join( HC.CLIENT_UPDATES_DIR, service_key_encoded ) if not os.path.exists( dest_dir ): os.mkdir( dest_dir ) - source_path = HC.CLIENT_UPDATES_DIR + os.path.sep + filename - dest_path = dest_dir + os.path.sep + gumpf + source_path = os.path.join( HC.CLIENT_UPDATES_DIR, filename ) + dest_path = os.path.join( dest_dir, gumpf ) shutil.move( source_path, dest_path ) @@ -6133,7 +6078,7 @@ class DB( HydrusDB.HydrusDB ): self._c.execute( 'CREATE INDEX mappings_service_id_status_index ON mappings ( service_id, status );' ) - self._controller.pub( 'splash_set_title_text', 'updating db to v' + HydrusData.ToString( version + 1 ) ) + self._controller.pub( 'splash_set_title_text', 'updating db to v' + str( version + 1 ) ) self._c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) ) @@ -6453,7 +6398,7 @@ class DB( HydrusDB.HydrusDB ): info[ 'port' ] = server_options[ 'port' ] info[ 'access_key' ] = service_keys_to_access_keys[ service_key ] - name = HC.service_string_lookup[ service_type ] + ' at ' + host + ':' + HydrusData.ToString( info[ 'port' ] ) + name = HC.service_string_lookup[ service_type ] + ' at ' + host + ':' + str( info[ 'port' ] ) self._AddService( service_key, service_type, name, info ) @@ -6740,18 +6685,20 @@ class DB( HydrusDB.HydrusDB ): if deletee_filename.startswith( 'client' ): - deletee_path = HC.DB_DIR + os.path.sep + deletee_filename + deletee_path = os.path.join( HC.DB_DIR, deletee_filename ) ClientData.DeletePath( deletee_path ) - shutil.copy( path + os.path.sep + 'client.db', self._db_path ) - if os.path.exists( path + os.path.sep + 'client.db-wal' ): shutil.copy( path + os.path.sep + 'client.db-wal', self._db_path + '-wal' ) + shutil.copy( os.path.join( path, 'client.db' ), self._db_path ) - shutil.copytree( path + os.path.sep + 'client_archives', HC.CLIENT_ARCHIVES_DIR ) - shutil.copytree( path + os.path.sep + 'client_files', HC.CLIENT_FILES_DIR ) - shutil.copytree( path + os.path.sep + 'client_thumbnails', HC.CLIENT_THUMBNAILS_DIR ) - shutil.copytree( path + os.path.sep + 'client_updates', HC.CLIENT_UPDATES_DIR ) + wal_path = os.path.join( path, 'client.db-wal' ) + if os.path.exists( wal_path ): shutil.copy( wal_path, self._db_path + '-wal' ) + + shutil.copytree( os.path.join( path, 'client_archives' ), HC.CLIENT_ARCHIVES_DIR ) + shutil.copytree( os.path.join( path, 'client_files' ), HC.CLIENT_FILES_DIR ) + shutil.copytree( os.path.join( path, 'client_thumbnails' ), HC.CLIENT_THUMBNAILS_DIR ) + shutil.copytree( os.path.join( path, 'client_updates' ), HC.CLIENT_UPDATES_DIR ) \ No newline at end of file diff --git a/include/ClientDaemons.py b/include/ClientDaemons.py index f51fba08..a9a5d061 100644 --- a/include/ClientDaemons.py +++ b/include/ClientDaemons.py @@ -8,9 +8,9 @@ import HydrusConstants as HC import HydrusData import HydrusEncryption import HydrusExceptions -import HydrusFileHandling import HydrusImageHandling import HydrusNATPunch +import HydrusPaths import HydrusServer import HydrusSerialisable import HydrusTagArchive @@ -29,15 +29,14 @@ import time import traceback import wx import yaml -import HydrusGlobals -def DAEMONCheckExportFolders(): +def DAEMONCheckExportFolders( controller ): - options = HydrusGlobals.client_controller.GetOptions() + options = controller.GetOptions() if not options[ 'pause_export_folders_sync' ]: - export_folders = HydrusGlobals.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_EXPORT_FOLDER ) + export_folders = controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_EXPORT_FOLDER ) for export_folder in export_folders: @@ -50,13 +49,13 @@ def DAEMONCheckExportFolders(): -def DAEMONCheckImportFolders(): +def DAEMONCheckImportFolders( controller ): - options = HydrusGlobals.client_controller.GetOptions() + options = controller.GetOptions() if not options[ 'pause_import_folders_sync' ]: - import_folders = HydrusGlobals.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER ) + import_folders = controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER ) for import_folder in import_folders: @@ -69,13 +68,13 @@ def DAEMONCheckImportFolders(): -def DAEMONCheckMouseIdle(): +def DAEMONCheckMouseIdle( controller ): - HydrusGlobals.client_controller.CheckMouseIdle() + wx.CallAfter( controller.CheckMouseIdle ) -def DAEMONDownloadFiles(): +def DAEMONDownloadFiles( controller ): - hashes = HydrusGlobals.client_controller.Read( 'downloads' ) + hashes = controller.Read( 'downloads' ) num_downloads = len( hashes ) @@ -87,13 +86,13 @@ def DAEMONDownloadFiles(): job_key.SetVariable( 'popup_text_1', 'initialising downloader' ) - HydrusGlobals.client_controller.pub( 'message', job_key ) + controller.pub( 'message', job_key ) for hash in hashes: job_key.SetVariable( 'popup_text_1', 'downloading ' + HydrusData.ConvertIntToPrettyString( num_downloads - len( successful_hashes ) ) + ' files from repositories' ) - ( media_result, ) = HydrusGlobals.client_controller.Read( 'media_results', CC.COMBINED_FILE_SERVICE_KEY, ( hash, ) ) + ( media_result, ) = controller.Read( 'media_results', CC.COMBINED_FILE_SERVICE_KEY, ( hash, ) ) service_keys = list( media_result.GetLocationsManager().GetCurrent() ) @@ -104,7 +103,7 @@ def DAEMONDownloadFiles(): if service_key == CC.LOCAL_FILE_SERVICE_KEY: break elif service_key == CC.TRASH_SERVICE_KEY: continue - try: file_repository = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + try: file_repository = controller.GetServicesManager().GetService( service_key ) except HydrusExceptions.NotFoundException: continue if file_repository.CanDownload(): @@ -113,15 +112,15 @@ def DAEMONDownloadFiles(): request_args = { 'hash' : hash.encode( 'hex' ) } - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: file_repository.Request( HC.GET, 'file', request_args = request_args, temp_path = temp_path ) - HydrusGlobals.client_controller.WaitUntilPubSubsEmpty() + controller.WaitUntilPubSubsEmpty() - HydrusGlobals.client_controller.WriteSynchronous( 'import_file', temp_path, override_deleted = True ) + controller.WriteSynchronous( 'import_file', temp_path, override_deleted = True ) successful_hashes.add( hash ) @@ -129,7 +128,7 @@ def DAEMONDownloadFiles(): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) except HydrusExceptions.ServerBusyException: @@ -140,7 +139,7 @@ def DAEMONDownloadFiles(): job_key.Delete() - HydrusGlobals.client_controller.pub( 'notify_new_downloads' ) + controller.pub( 'notify_new_downloads' ) return @@ -170,19 +169,19 @@ def DAEMONDownloadFiles(): job_key.Delete() -def DAEMONFlushServiceUpdates( list_of_service_keys_to_service_updates ): +def DAEMONFlushServiceUpdates( controller, list_of_service_keys_to_service_updates ): service_keys_to_service_updates = HydrusData.MergeKeyToListDicts( list_of_service_keys_to_service_updates ) - HydrusGlobals.client_controller.WriteSynchronous( 'service_updates', service_keys_to_service_updates ) + controller.WriteSynchronous( 'service_updates', service_keys_to_service_updates ) -def DAEMONMaintainTrash(): +def DAEMONMaintainTrash( controller ): if HC.options[ 'trash_max_size' ] is not None: max_size = HC.options[ 'trash_max_size' ] * 1048576 - service_info = HydrusGlobals.client_controller.Read( 'service_info', CC.TRASH_SERVICE_KEY ) + service_info = controller.Read( 'service_info', CC.TRASH_SERVICE_KEY ) while service_info[ HC.SERVICE_INFO_TOTAL_SIZE ] > max_size: @@ -191,7 +190,7 @@ def DAEMONMaintainTrash(): return - hashes = HydrusGlobals.client_controller.Read( 'oldest_trash_hashes' ) + hashes = controller.Read( 'oldest_trash_hashes' ) if len( hashes ) == 0: @@ -202,11 +201,11 @@ def DAEMONMaintainTrash(): service_keys_to_content_updates = { CC.TRASH_SERVICE_KEY : [ content_update ] } - HydrusGlobals.client_controller.WaitUntilPubSubsEmpty() + controller.WaitUntilPubSubsEmpty() - HydrusGlobals.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates ) + controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates ) - service_info = HydrusGlobals.client_controller.Read( 'service_info', CC.TRASH_SERVICE_KEY ) + service_info = controller.Read( 'service_info', CC.TRASH_SERVICE_KEY ) @@ -214,7 +213,7 @@ def DAEMONMaintainTrash(): max_age = HC.options[ 'trash_max_age' ] * 3600 - hashes = HydrusGlobals.client_controller.Read( 'oldest_trash_hashes', minimum_age = max_age ) + hashes = controller.Read( 'oldest_trash_hashes', minimum_age = max_age ) while len( hashes ) > 0: @@ -227,19 +226,19 @@ def DAEMONMaintainTrash(): service_keys_to_content_updates = { CC.TRASH_SERVICE_KEY : [ content_update ] } - HydrusGlobals.client_controller.WaitUntilPubSubsEmpty() + controller.WaitUntilPubSubsEmpty() - HydrusGlobals.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates ) + controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates ) - hashes = HydrusGlobals.client_controller.Read( 'oldest_trash_hashes', minimum_age = max_age ) + hashes = controller.Read( 'oldest_trash_hashes', minimum_age = max_age ) -def DAEMONSynchroniseAccounts(): +def DAEMONSynchroniseAccounts( controller ): - services = HydrusGlobals.client_controller.GetServicesManager().GetServices( HC.RESTRICTED_SERVICES ) + services = controller.GetServicesManager().GetServices( HC.RESTRICTED_SERVICES ) - options = HydrusGlobals.client_controller.GetOptions() + options = controller.GetOptions() do_notify = False @@ -270,7 +269,7 @@ def DAEMONSynchroniseAccounts(): account.MakeFresh() - HydrusGlobals.client_controller.WriteSynchronous( 'service_updates', { service_key : [ HydrusData.ServiceUpdate( HC.SERVICE_UPDATE_ACCOUNT, account ) ] } ) + controller.WriteSynchronous( 'service_updates', { service_key : [ HydrusData.ServiceUpdate( HC.SERVICE_UPDATE_ACCOUNT, account ) ] } ) do_notify = True @@ -285,16 +284,16 @@ def DAEMONSynchroniseAccounts(): if do_notify: - HydrusGlobals.client_controller.pub( 'notify_new_permissions' ) + controller.pub( 'notify_new_permissions' ) -def DAEMONSynchroniseRepositories(): +def DAEMONSynchroniseRepositories( controller ): - options = HydrusGlobals.client_controller.GetOptions() + options = controller.GetOptions() if not options[ 'pause_repo_sync' ]: - services = HydrusGlobals.client_controller.GetServicesManager().GetServices( HC.REPOSITORIES ) + services = controller.GetServicesManager().GetServices( HC.REPOSITORIES ) for service in services: @@ -303,7 +302,7 @@ def DAEMONSynchroniseRepositories(): break - if HydrusGlobals.client_controller.CurrentlyIdle(): + if controller.CurrentlyIdle(): service.Sync( only_when_idle = True ) @@ -312,28 +311,28 @@ def DAEMONSynchroniseRepositories(): time.sleep( 5 ) -def DAEMONSynchroniseSubscriptions(): +def DAEMONSynchroniseSubscriptions( controller ): - options = HydrusGlobals.client_controller.GetOptions() + options = controller.GetOptions() - subscription_names = HydrusGlobals.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION ) + subscription_names = controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION ) for name in subscription_names: p1 = options[ 'pause_subs_sync' ] - p2 = HydrusGlobals.view_shutdown + p2 = controller.ViewIsShutdown() if p1 or p2: return - subscription = HydrusGlobals.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION, name ) + subscription = controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION, name ) subscription.Sync() -def DAEMONUPnP(): +def DAEMONUPnP( controller ): try: @@ -345,7 +344,7 @@ def DAEMONUPnP(): except: return # This IGD probably doesn't support UPnP, so don't spam the user with errors they can't fix! - services = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.LOCAL_BOORU, ) ) + services = controller.GetServicesManager().GetServices( ( HC.LOCAL_BOORU, ) ) for service in services: diff --git a/include/ClientData.py b/include/ClientData.py index 222a4c6d..0548501d 100644 --- a/include/ClientData.py +++ b/include/ClientData.py @@ -36,7 +36,11 @@ def CatchExceptionClient( etype, value, tb ): job_key = HydrusThreading.JobKey() - if etype == HydrusExceptions.DBException: + if etype == HydrusExceptions.ShutdownException: + + return + + elif etype == HydrusExceptions.DBException: ( text, caller_traceback, db_traceback ) = value @@ -54,15 +58,15 @@ def CatchExceptionClient( etype, value, tb ): if etype == wx.PyDeadObjectError: print( 'Got a PyDeadObjectError, which can probably be ignored, but here it is anyway:' ) - print( HydrusData.ToString( value ) ) + print( HydrusData.ToUnicode( value ) ) print( trace ) return - try: job_key.SetVariable( 'popup_title', HydrusData.ToString( etype.__name__ ) ) - except: job_key.SetVariable( 'popup_title', HydrusData.ToString( etype ) ) - job_key.SetVariable( 'popup_text_1', HydrusData.ToString( value ) ) + try: job_key.SetVariable( 'popup_title', HydrusData.ToUnicode( etype.__name__ ) ) + except: job_key.SetVariable( 'popup_title', HydrusData.ToUnicode( etype ) ) + job_key.SetVariable( 'popup_text_1', HydrusData.ToUnicode( value ) ) job_key.SetVariable( 'popup_traceback', trace ) @@ -85,7 +89,7 @@ def CatchExceptionClient( etype, value, tb ): text += os.linesep - text += HydrusData.ToString( ( etype, value, tb ) ) + text += HydrusData.ToUnicode( ( etype, value, tb ) ) try: text += traceback.format_exc() except: pass @@ -210,27 +214,15 @@ def GetMediasTagCount( pool, tag_service_key = CC.COMBINED_TAG_SERVICE_KEY ): return ( current_tags_to_count, deleted_tags_to_count, pending_tags_to_count, petitioned_tags_to_count ) -def IsWXAncestor( child, ancestor ): - - parent = child - - while not isinstance( parent, wx.TopLevelWindow ): - - if parent == ancestor: - - return True - - - parent = parent.GetParent() - - - return False - def ShowExceptionClient( e ): job_key = HydrusThreading.JobKey() - if isinstance( e, HydrusExceptions.DBException ): + if isinstance( e, HydrusExceptions.ShutdownException ): + + return + + elif isinstance( e, HydrusExceptions.DBException ): ( text, caller_traceback, db_traceback ) = e.args @@ -246,7 +238,7 @@ def ShowExceptionClient( e ): if etype is None: etype = type( e ) - value = HydrusData.ToString( e ) + value = HydrusData.ToUnicode( e ) trace = ''.join( traceback.format_stack() ) @@ -255,17 +247,17 @@ def ShowExceptionClient( e ): if etype == wx.PyDeadObjectError: print( 'Got a PyDeadObjectError, which can probably be ignored, but here it is anyway:' ) - print( HydrusData.ToString( value ) ) + print( HydrusData.ToUnicode( value ) ) print( trace ) return - if hasattr( etype, '__name__' ): title = HydrusData.ToString( etype.__name__ ) - else: title = HydrusData.ToString( etype ) + if hasattr( etype, '__name__' ): title = HydrusData.ToUnicode( etype.__name__ ) + else: title = HydrusData.ToUnicode( etype ) job_key.SetVariable( 'popup_title', title ) - job_key.SetVariable( 'popup_text_1', HydrusData.ToString( value ) ) + job_key.SetVariable( 'popup_text_1', HydrusData.ToUnicode( value ) ) job_key.SetVariable( 'popup_traceback', trace ) @@ -288,7 +280,7 @@ def ShowTextClient( text ): job_key = HydrusThreading.JobKey() - job_key.SetVariable( 'popup_text_1', HydrusData.ToString( text ) ) + job_key.SetVariable( 'popup_text_1', HydrusData.ToUnicode( text ) ) text = job_key.ToString() @@ -459,7 +451,7 @@ class Credentials( HydrusData.HydrusYAMLBase ): def __ne__( self, other ): return self.__hash__() != other.__hash__() - def __repr__( self ): return 'Credentials: ' + HydrusData.ToString( ( self._host, self._port, self._access_key.encode( 'hex' ) ) ) + def __repr__( self ): return 'Credentials: ' + HydrusData.ToUnicode( ( self._host, self._port, self._access_key.encode( 'hex' ) ) ) def GetAccessKey( self ): return self._access_key @@ -471,7 +463,7 @@ class Credentials( HydrusData.HydrusYAMLBase ): if self.HasAccessKey(): connection_string += self._access_key.encode( 'hex' ) + '@' - connection_string += self._host + ':' + HydrusData.ToString( self._port ) + connection_string += self._host + ':' + str( self._port ) return connection_string @@ -1212,7 +1204,7 @@ class Predicate( HydrusSerialisable.SerialisableBase ): def __repr__( self ): - return 'Predicate: ' + HydrusData.ToString( ( self._predicate_type, self._value, self._counts ) ) + return 'Predicate: ' + HydrusData.ToUnicode( ( self._predicate_type, self._value, self._counts ) ) def _GetSerialisableInfo( self ): @@ -1351,7 +1343,7 @@ class Predicate( HydrusSerialisable.SerialisableBase ): ( operator, ratio_width, ratio_height ) = self._value - base += u' ' + operator + u' ' + HydrusData.ToString( ratio_width ) + u':' + HydrusData.ToString( ratio_height ) + base += u' ' + operator + u' ' + str( ratio_width ) + u':' + str( ratio_height ) elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIZE: @@ -1362,7 +1354,7 @@ class Predicate( HydrusSerialisable.SerialisableBase ): ( operator, size, unit ) = self._value - base += u' ' + operator + u' ' + HydrusData.ToString( size ) + HydrusData.ConvertIntToUnit( unit ) + base += u' ' + operator + u' ' + str( size ) + HydrusData.ConvertIntToUnit( unit ) elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_LIMIT: @@ -1384,9 +1376,9 @@ class Predicate( HydrusSerialisable.SerialisableBase ): ( operator, years, months, days, hours ) = self._value - base += u' ' + operator + u' ' + HydrusData.ToString( years ) + u'y' + HydrusData.ToString( months ) + u'm' + HydrusData.ToString( days ) + u'd' + HydrusData.ToString( hours ) + u'h' - + base += u' ' + operator + u' ' + str( years ) + u'y' + str( months ) + u'm' + str( days ) + u'd' + str( hours ) + u'h' + elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_PIXELS: base = u'system:num_pixels' @@ -1395,7 +1387,7 @@ class Predicate( HydrusSerialisable.SerialisableBase ): ( operator, num_pixels, unit ) = self._value - base += u' ' + operator + u' ' + HydrusData.ToString( num_pixels ) + ' ' + HydrusData.ConvertIntToPixels( unit ) + base += u' ' + operator + u' ' + str( num_pixels ) + ' ' + HydrusData.ConvertIntToPixels( unit ) elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH: @@ -1455,7 +1447,7 @@ class Predicate( HydrusSerialisable.SerialisableBase ): service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) - base += u' for ' + service.GetName() + u' ' + operator + u' ' + HydrusData.ToString( value ) + base += u' for ' + service.GetName() + u' ' + operator + u' ' + HydrusData.ToUnicode( value ) elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO: @@ -1466,7 +1458,7 @@ class Predicate( HydrusSerialisable.SerialisableBase ): ( hash, max_hamming ) = self._value - base += u' ' + hash.encode( 'hex' ) + u' using max hamming of ' + HydrusData.ToString( max_hamming ) + base += u' ' + hash.encode( 'hex' ) + u' using max hamming of ' + str( max_hamming ) elif self._predicate_type == HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE: @@ -1844,7 +1836,7 @@ class Service( HydrusData.HydrusYAMLBase ): ( host, port ) = credentials.GetAddress() - url = 'http://' + host + ':' + HydrusData.ToString( port ) + path_and_query + url = 'http://' + host + ':' + str( port ) + path_and_query ( response, size_of_response, response_headers, cookies ) = HydrusGlobals.client_controller.DoHTTP( method, url, request_headers, body, report_hooks = report_hooks, temp_path = temp_path, return_everything = True ) @@ -1869,7 +1861,7 @@ class Service( HydrusData.HydrusYAMLBase ): session_manager.DeleteSessionKey( self._service_key ) - HydrusGlobals.client_controller.Write( 'service_updates', { self._service_key : [ HydrusData.ServiceUpdate( HC.SERVICE_UPDATE_ERROR, HydrusData.ToString( e ) ) ] } ) + HydrusGlobals.client_controller.Write( 'service_updates', { self._service_key : [ HydrusData.ServiceUpdate( HC.SERVICE_UPDATE_ERROR, HydrusData.ToUnicode( e ) ) ] } ) if isinstance( e, HydrusExceptions.PermissionException ): @@ -2797,7 +2789,7 @@ class ClientServiceIdentifier( HydrusData.HydrusYAMLBase ): def __ne__( self, other ): return self.__hash__() != other.__hash__() - def __repr__( self ): return 'Client Service Identifier: ' + HydrusData.ToString( ( self._name, HC.service_string_lookup[ self._type ] ) ) + def __repr__( self ): return 'Client Service Identifier: ' + HydrusData.ToUnicode( ( self._name, HC.service_string_lookup[ self._type ] ) ) def GetInfo( self ): return ( self._service_key, self._type, self._name ) diff --git a/include/ClientDefaults.py b/include/ClientDefaults.py index 78726b4e..31d3b929 100644 --- a/include/ClientDefaults.py +++ b/include/ClientDefaults.py @@ -46,6 +46,7 @@ def GetClientDefaultOptions(): options[ 'confirm_archive' ] = True options[ 'delete_to_recycle_bin' ] = True options[ 'animation_start_position' ] = 0.0 + options[ 'hide_preview' ] = False regex_favourites = [] diff --git a/include/ClientDownloading.py b/include/ClientDownloading.py index 7be5de78..35990f72 100644 --- a/include/ClientDownloading.py +++ b/include/ClientDownloading.py @@ -4,6 +4,7 @@ import collections import httplib import HydrusConstants as HC import HydrusExceptions +import HydrusPaths import HydrusSerialisable import HydrusThreading import json @@ -19,7 +20,6 @@ import urlparse import wx import HydrusTags import HydrusData -import HydrusFileHandling import ClientConstants as CC import HydrusGlobals @@ -185,7 +185,7 @@ def GetYoutubeFormats( youtube_url ): try: p = pafy.Pafy( youtube_url ) except Exception as e: - raise Exception( 'Could not fetch video info from youtube!' + os.linesep + HydrusData.ToString( e ) ) + raise Exception( 'Could not fetch video info from youtube!' + os.linesep + HydrusData.ToUnicode( e ) ) info = { ( s.extension, s.resolution ) : ( s.url, s.title ) for s in p.streams if s.extension in ( 'flv', 'mp4' ) } @@ -205,7 +205,7 @@ def THREADDownloadURL( job_key, url, url_string ): job_key.SetVariable( 'popup_gauge_1', ( gauge_value, gauge_range ) ) - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -218,7 +218,7 @@ def THREADDownloadURL( job_key, url, url_string ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) if result in ( CC.STATUS_SUCCESSFUL, CC.STATUS_REDUNDANT ): @@ -276,7 +276,7 @@ def Parse4chanPostScreen( html ): return ( 'error', text ) - problem = HydrusData.ToString( problem_tag ) + problem = HydrusData.ToUnicode( problem_tag ) if 'CAPTCHA' in problem: return ( 'captcha', None ) elif 'seconds' in problem: return ( 'too quick', None ) @@ -506,7 +506,9 @@ class GalleryBooru( Gallery ): tags = tags_to_use - return self._search_url.replace( '%tags%', self._search_separator.join( [ urllib.quote( tag.encode( 'utf-8' ), '' ) for tag in tags ] ) ).replace( '%index%', HydrusData.ToString( url_index ) ) + tags_replace = self._search_separator.join( [ urllib.quote( HydrusData.ToByteString( tag ), '' ) for tag in tags ] ) + + return self._search_url.replace( '%tags%', tags_replace ).replace( '%index%', str( url_index ) ) def _ParseGalleryPage( self, html, url_base ): @@ -655,7 +657,7 @@ class GalleryBooru( Gallery ): except Exception as e: - raise HydrusExceptions.NotFoundException( 'Could not parse a download link for ' + url_base + '!' + os.linesep + HydrusData.ToString( e ) ) + raise HydrusExceptions.NotFoundException( 'Could not parse a download link for ' + url_base + '!' + os.linesep + HydrusData.ToUnicode( e ) ) if image_url is None: @@ -736,7 +738,7 @@ class GalleryDeviantArt( Gallery ): artist = query - return 'http://' + artist + '.deviantart.com/gallery/?catpath=/&offset=' + HydrusData.ToString( page_index * 24 ) + return 'http://' + artist + '.deviantart.com/gallery/?catpath=/&offset=' + str( page_index * 24 ) def _ParseGalleryPage( self, html, url_base ): @@ -861,7 +863,7 @@ class GalleryGiphy( Gallery ): tag = query - return 'http://giphy.com/api/gifs?tag=' + urllib.quote( tag.encode( 'utf-8' ).replace( ' ', '+' ), '' ) + '&page=' + HydrusData.ToString( page_index + 1 ) + return 'http://giphy.com/api/gifs?tag=' + urllib.quote( HydrusData.ToByteString( tag ).replace( ' ', '+' ), '' ) + '&page=' + str( page_index + 1 ) def _ParseGalleryPage( self, data, url_base ): @@ -900,7 +902,7 @@ class GalleryGiphy( Gallery ): else: - url = 'http://giphy.com/api/gifs/' + HydrusData.ToString( id ) + url = 'http://giphy.com/api/gifs/' + str( id ) try: @@ -1011,7 +1013,7 @@ class GalleryHentaiFoundry( Gallery ): except Exception as e: - raise Exception( 'Could not parse image url!' + os.linesep + HydrusData.ToString( e ) ) + raise Exception( 'Could not parse image url!' + os.linesep + HydrusData.ToUnicode( e ) ) soup = bs4.BeautifulSoup( html ) @@ -1022,7 +1024,7 @@ class GalleryHentaiFoundry( Gallery ): title = soup.find( 'title' ) - ( data, nothing ) = HydrusData.ToString( title.string ).split( ' - Hentai Foundry' ) + ( data, nothing ) = title.string.split( ' - Hentai Foundry' ) data_reversed = data[::-1] # want to do it right-side first, because title might have ' by ' in it @@ -1075,7 +1077,7 @@ class GalleryHentaiFoundryArtistPictures( GalleryHentaiFoundry ): gallery_url = 'http://www.hentai-foundry.com/pictures/user/' + artist - return gallery_url + '/page/' + HydrusData.ToString( page_index + 1 ) + return gallery_url + '/page/' + str( page_index + 1 ) class GalleryHentaiFoundryArtistScraps( GalleryHentaiFoundry ): @@ -1086,7 +1088,7 @@ class GalleryHentaiFoundryArtistScraps( GalleryHentaiFoundry ): gallery_url = 'http://www.hentai-foundry.com/pictures/user/' + artist + '/scraps' - return gallery_url + '/page/' + HydrusData.ToString( page_index + 1 ) + return gallery_url + '/page/' + str( page_index + 1 ) class GalleryHentaiFoundryTags( GalleryHentaiFoundry ): @@ -1095,7 +1097,7 @@ class GalleryHentaiFoundryTags( GalleryHentaiFoundry ): tags = query.split( ' ' ) - return 'http://www.hentai-foundry.com/search/pictures?query=' + '+'.join( tags ) + '&search_in=all&scraps=-1&page=' + HydrusData.ToString( page_index + 1 ) + return 'http://www.hentai-foundry.com/search/pictures?query=' + '+'.join( tags ) + '&search_in=all&scraps=-1&page=' + str( page_index + 1 ) # scraps = 0 hide # -1 means show both # 1 means scraps only. wetf @@ -1377,9 +1379,9 @@ class GalleryPixivArtistID( GalleryPixiv ): artist_id = query - gallery_url = 'http://www.pixiv.net/member_illust.php?id=' + HydrusData.ToString( artist_id ) + gallery_url = 'http://www.pixiv.net/member_illust.php?id=' + str( artist_id ) - return gallery_url + '&p=' + HydrusData.ToString( page_index + 1 ) + return gallery_url + '&p=' + str( page_index + 1 ) class GalleryPixivTag( GalleryPixiv ): @@ -1388,9 +1390,9 @@ class GalleryPixivTag( GalleryPixiv ): tag = query - gallery_url = 'http://www.pixiv.net/search.php?word=' + urllib.quote( tag.encode( 'utf-8' ), '' ) + '&s_mode=s_tag_full&order=date_d' + gallery_url = 'http://www.pixiv.net/search.php?word=' + urllib.quote( HydrusData.ToByteString( tag ), '' ) + '&s_mode=s_tag_full&order=date_d' - return gallery_url + '&p=' + HydrusData.ToString( page_index + 1 ) + return gallery_url + '&p=' + str( page_index + 1 ) class GalleryTumblr( Gallery ): @@ -1399,7 +1401,7 @@ class GalleryTumblr( Gallery ): username = query - return 'http://' + username + '.tumblr.com/api/read/json?start=' + HydrusData.ToString( page_index * 50 ) + '&num=50' + return 'http://' + username + '.tumblr.com/api/read/json?start=' + str( page_index * 50 ) + '&num=50' def _ParseGalleryPage( self, data, url_base ): diff --git a/include/ClientFiles.py b/include/ClientFiles.py index 6d260084..562a4b3e 100644 --- a/include/ClientFiles.py +++ b/include/ClientFiles.py @@ -16,7 +16,9 @@ import stat import wx def GenerateExportFilename( media, terms ): - + + mime = media.GetMime() + filename = '' for ( term_type, term ) in terms: @@ -70,7 +72,7 @@ def GenerateExportFilename( media, terms ): filename = re.sub( '/', '_', filename, flags = re.UNICODE ) - return filename + return filename + HC.mime_ext_lookup[ mime ] def GetAllPaths( raw_paths ): @@ -86,11 +88,14 @@ def GetAllPaths( raw_paths ): if os.path.isdir( path ): - subpaths = [ path + os.path.sep + filename for filename in os.listdir( path ) ] + subpaths = [ os.path.join( path, filename ) for filename in os.listdir( path ) ] next_paths_to_process.extend( subpaths ) - else: file_paths.append( path ) + else: + + file_paths.append( path ) + paths_to_process = next_paths_to_process @@ -125,7 +130,7 @@ def GetExpectedFilePath( hash, mime ): first_two_chars = hash_encoded[:2] - return HC.CLIENT_FILES_DIR + os.path.sep + first_two_chars + os.path.sep + hash_encoded + HC.mime_ext_lookup[ mime ] + return os.path.join( HC.CLIENT_FILES_DIR, first_two_chars, hash_encoded + HC.mime_ext_lookup[ mime ] ) def GetExportPath(): @@ -135,9 +140,12 @@ def GetExportPath(): if path is None: - path = os.path.expanduser( '~' ) + os.path.sep + 'hydrus_export' + path = os.path.join( os.path.expanduser( '~' ), 'hydrus_export' ) - if not os.path.exists( path ): os.mkdir( path ) + if not os.path.exists( path ): + + os.mkdir( path ) + path = os.path.normpath( path ) # converts slashes to backslashes for windows @@ -176,9 +184,12 @@ def GetExpectedThumbnailPath( hash, full_size = True ): first_two_chars = hash_encoded[:2] - path = HC.CLIENT_THUMBNAILS_DIR + os.path.sep + first_two_chars + os.path.sep + hash_encoded + path = os.path.join( HC.CLIENT_THUMBNAILS_DIR, first_two_chars, hash_encoded ) - if not full_size: path += '_resized' + if not full_size: + + path += '_resized' + return path @@ -214,15 +225,15 @@ def GetThumbnailPath( hash, full_size = True ): def GetExpectedContentUpdatePackagePath( service_key, begin, subindex ): - return GetExpectedUpdateDir( service_key ) + os.path.sep + str( begin ) + '_' + str( subindex ) + '.json' + return os.path.join( GetExpectedUpdateDir( service_key ), str( begin ) + '_' + str( subindex ) + '.json' ) def GetExpectedServiceUpdatePackagePath( service_key, begin ): - return GetExpectedUpdateDir( service_key ) + os.path.sep + str( begin ) + '_metadata.json' + return os.path.join( GetExpectedUpdateDir( service_key ), str( begin ) + '_metadata.json' ) def GetExpectedUpdateDir( service_key ): - return HC.CLIENT_UPDATES_DIR + os.path.sep + service_key.encode( 'hex' ) + return os.path.join( HC.CLIENT_UPDATES_DIR, service_key.encode( 'hex' ) ) def IterateAllFileHashes(): @@ -248,11 +259,14 @@ def IterateAllFilePaths(): for ( one, two ) in itertools.product( hex_chars, hex_chars ): - dir = HC.CLIENT_FILES_DIR + os.path.sep + one + two + dir = os.path.join( HC.CLIENT_FILES_DIR, one + two ) next_paths = os.listdir( dir ) - for path in next_paths: yield dir + os.path.sep + path + for path in next_paths: + + yield os.path.join( dir, path ) + def IterateAllThumbnailPaths(): @@ -261,11 +275,14 @@ def IterateAllThumbnailPaths(): for ( one, two ) in itertools.product( hex_chars, hex_chars ): - dir = HC.CLIENT_THUMBNAILS_DIR + os.path.sep + one + two + dir = os.path.join( HC.CLIENT_THUMBNAILS_DIR, one + two ) next_paths = os.listdir( dir ) - for path in next_paths: yield dir + os.path.sep + path + for path in next_paths: + + yield os.path.join( dir, path ) + def ParseExportPhrase( phrase ): @@ -428,7 +445,7 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ): terms = ParseExportPhrase( self._phrase ) - previous_filenames = set( os.listdir( folder_path ) ) + previous_filenames = set( os.listdir( HydrusData.ToUnicode( folder_path ) ) ) if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' existing filenames: ' + str( len( previous_filenames ) ) ) if HydrusGlobals.special_debug_mode: @@ -436,6 +453,7 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ): print( previous_filename ) + sync_filenames = set() @@ -447,9 +465,9 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ): source_path = GetFilePath( hash, mime ) - filename = GenerateExportFilename( media_result, terms ) + HC.mime_ext_lookup[ mime ] + filename = GenerateExportFilename( media_result, terms ) - dest_path = folder_path + os.path.sep + filename + dest_path = os.path.join( folder_path, filename ) if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' dest path: ' + dest_path ) do_copy = True @@ -487,7 +505,7 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ): if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' delete filenames: ' + str( len( deletee_filenames ) ) ) for deletee_filename in deletee_filenames: - deletee_path = folder_path + os.path.sep + deletee_filename + deletee_path = os.path.join( folder_path, deletee_filename ) if HydrusGlobals.special_debug_mode: print( deletee_path ) ClientData.DeletePath( deletee_path ) diff --git a/include/ClientGUI.py b/include/ClientGUI.py index 3e6f6d9e..081947c3 100755 --- a/include/ClientGUI.py +++ b/include/ClientGUI.py @@ -15,6 +15,7 @@ import ClientSearch import HydrusData import HydrusExceptions import HydrusFileHandling +import HydrusPaths import HydrusGlobals import HydrusImageHandling import HydrusNATPunch @@ -44,9 +45,13 @@ MENU_ORDER = [ 'file', 'undo', 'view', 'search', 'download', 'database', 'pendin class FrameGUI( ClientGUICommon.FrameThatResizes ): - def __init__( self ): + def __init__( self, controller ): - ClientGUICommon.FrameThatResizes.__init__( self, None, resize_option_prefix = 'gui_', title = HydrusGlobals.client_controller.PrepStringForDisplay( 'Hydrus Client' ) ) + self._controller = controller + + title = self._controller.PrepStringForDisplay( 'Hydrus Client' ) + + ClientGUICommon.FrameThatResizes.__init__( self, None, resize_option_prefix = 'gui_', title = title ) self.SetDropTarget( ClientDragDrop.FileDropTarget( self.ImportFiles ) ) @@ -77,27 +82,27 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): self.Bind( wx.EVT_CLOSE, self.EventExit ) self.Bind( wx.EVT_SET_FOCUS, self.EventFocus ) - HydrusGlobals.client_controller.sub( self, 'ClearClosedPages', 'clear_closed_pages' ) - HydrusGlobals.client_controller.sub( self, 'NewCompose', 'new_compose_frame' ) - HydrusGlobals.client_controller.sub( self, 'NewPageImportBooru', 'new_import_booru' ) - HydrusGlobals.client_controller.sub( self, 'NewPageImportGallery', 'new_import_gallery' ) - HydrusGlobals.client_controller.sub( self, 'NewPageImportHDD', 'new_hdd_import' ) - HydrusGlobals.client_controller.sub( self, 'NewPageImportThreadWatcher', 'new_page_import_thread_watcher' ) - HydrusGlobals.client_controller.sub( self, 'NewPageImportPageOfImages', 'new_page_import_page_of_images' ) - HydrusGlobals.client_controller.sub( self, 'NewPagePetitions', 'new_page_petitions' ) - HydrusGlobals.client_controller.sub( self, 'NewPageQuery', 'new_page_query' ) - HydrusGlobals.client_controller.sub( self, 'NewPageThreadDumper', 'new_thread_dumper' ) - HydrusGlobals.client_controller.sub( self, 'NewSimilarTo', 'new_similar_to' ) - HydrusGlobals.client_controller.sub( self, 'NotifyNewOptions', 'notify_new_options' ) - HydrusGlobals.client_controller.sub( self, 'NotifyNewPending', 'notify_new_pending' ) - HydrusGlobals.client_controller.sub( self, 'NotifyNewPermissions', 'notify_new_permissions' ) - HydrusGlobals.client_controller.sub( self, 'NotifyNewServices', 'notify_new_services_gui' ) - HydrusGlobals.client_controller.sub( self, 'NotifyNewSessions', 'notify_new_sessions' ) - HydrusGlobals.client_controller.sub( self, 'NotifyNewUndo', 'notify_new_undo' ) - HydrusGlobals.client_controller.sub( self, 'RefreshStatusBar', 'refresh_status' ) - HydrusGlobals.client_controller.sub( self, 'SetDBLockedStatus', 'db_locked_status' ) - HydrusGlobals.client_controller.sub( self, 'SetMediaFocus', 'set_media_focus' ) - HydrusGlobals.client_controller.sub( self, 'ShowSeedCache', 'show_seed_cache' ) + self._controller.sub( self, 'ClearClosedPages', 'clear_closed_pages' ) + self._controller.sub( self, 'NewCompose', 'new_compose_frame' ) + self._controller.sub( self, 'NewPageImportBooru', 'new_import_booru' ) + self._controller.sub( self, 'NewPageImportGallery', 'new_import_gallery' ) + self._controller.sub( self, 'NewPageImportHDD', 'new_hdd_import' ) + self._controller.sub( self, 'NewPageImportThreadWatcher', 'new_page_import_thread_watcher' ) + self._controller.sub( self, 'NewPageImportPageOfImages', 'new_page_import_page_of_images' ) + self._controller.sub( self, 'NewPagePetitions', 'new_page_petitions' ) + self._controller.sub( self, 'NewPageQuery', 'new_page_query' ) + self._controller.sub( self, 'NewPageThreadDumper', 'new_thread_dumper' ) + self._controller.sub( self, 'NewSimilarTo', 'new_similar_to' ) + self._controller.sub( self, 'NotifyNewOptions', 'notify_new_options' ) + self._controller.sub( self, 'NotifyNewPending', 'notify_new_pending' ) + self._controller.sub( self, 'NotifyNewPermissions', 'notify_new_permissions' ) + self._controller.sub( self, 'NotifyNewServices', 'notify_new_services_gui' ) + self._controller.sub( self, 'NotifyNewSessions', 'notify_new_sessions' ) + self._controller.sub( self, 'NotifyNewUndo', 'notify_new_undo' ) + self._controller.sub( self, 'RefreshStatusBar', 'refresh_status' ) + self._controller.sub( self, 'SetDBLockedStatus', 'db_locked_status' ) + self._controller.sub( self, 'SetMediaFocus', 'set_media_focus' ) + self._controller.sub( self, 'ShowSeedCache', 'show_seed_cache' ) self._menus = {} @@ -135,12 +140,12 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): aboutinfo = wx.AboutDialogInfo() - aboutinfo.SetIcon( wx.Icon( HC.STATIC_DIR + os.path.sep + 'hydrus.ico', wx.BITMAP_TYPE_ICO ) ) + aboutinfo.SetIcon( wx.Icon( os.path.join( HC.STATIC_DIR, 'hydrus.ico' ), wx.BITMAP_TYPE_ICO ) ) aboutinfo.SetName( 'hydrus client' ) - aboutinfo.SetVersion( HydrusData.ToString( HC.SOFTWARE_VERSION ) + ', using network version ' + HydrusData.ToString( HC.NETWORK_VERSION ) ) + aboutinfo.SetVersion( str( HC.SOFTWARE_VERSION ) + ', using network version ' + str( HC.NETWORK_VERSION ) ) aboutinfo.SetDescription( CC.CLIENT_DESCRIPTION ) - with open( HC.BASE_DIR + os.path.sep + 'license.txt', 'rb' ) as f: license = f.read() + with open( os.path.join( HC.BASE_DIR, 'license.txt' ), 'rb' ) as f: license = f.read() aboutinfo.SetLicense( license ) @@ -158,13 +163,13 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): subject_account_key = dlg.GetValue().decode( 'hex' ) - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) response = service.Request( HC.GET, 'account_info', { 'subject_account_key' : subject_account_key.encode( 'hex' ) } ) account_info = response[ 'account_info' ] - wx.MessageBox( HydrusData.ToString( account_info ) ) + wx.MessageBox( HydrusData.ToUnicode( account_info ) ) @@ -199,7 +204,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): edit_log.append( HydrusData.EditLogActionAdd( ( service_key, service_type, name, info ) ) ) - HydrusGlobals.client_controller.WriteSynchronous( 'update_services', edit_log ) + self._controller.WriteSynchronous( 'update_services', edit_log ) HydrusData.ShowText( 'Auto repo setup done! Check services->review services to see your new services.' ) @@ -210,7 +215,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if dlg.ShowModal() == wx.ID_YES: - HydrusGlobals.client_controller.CallToThread( do_it ) + self._controller.CallToThread( do_it ) @@ -236,7 +241,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if already_running: - HydrusData.ShowText( 'The server appears to be already running. Either that, or something else is using port ' + HydrusData.ToString( HC.DEFAULT_SERVER_ADMIN_PORT ) + '.' ) + HydrusData.ShowText( 'The server appears to be already running. Either that, or something else is using port ' + str( HC.DEFAULT_SERVER_ADMIN_PORT ) + '.' ) return @@ -248,24 +253,24 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if HC.PLATFORM_WINDOWS: - my_exe = HC.BASE_DIR + os.path.sep + 'client.exe' + my_exe = os.path.join( HC.BASE_DIR, 'client.exe' ) else: - my_exe = HC.BASE_DIR + os.path.sep + 'client' + my_exe = os.path.join( HC.BASE_DIR, 'client' ) if sys.executable == my_exe: - if HC.PLATFORM_WINDOWS: subprocess.Popen( [ HC.BASE_DIR + os.path.sep + 'server.exe' ] ) - else: subprocess.Popen( [ '.' + HC.BASE_DIR + os.path.sep + 'server' ] ) + if HC.PLATFORM_WINDOWS: subprocess.Popen( [ os.path.join( HC.BASE_DIR, 'server.exe' ) ] ) + else: subprocess.Popen( [ os.path.join( '.', HC.BASE_DIR, 'server' ) ] ) else: if HC.PLATFORM_WINDOWS or HC.PLATFORM_OSX: python_bin = 'pythonw' else: python_bin = 'python' - subprocess.Popen( [ python_bin, HC.BASE_DIR + os.path.sep + 'server.py' ] ) + subprocess.Popen( [ python_bin, os.path.join( HC.BASE_DIR, 'server.py' ) ] ) time_waited = 0 @@ -324,7 +329,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): edit_log = [ HydrusData.EditLogActionAdd( ( admin_service_key, service_type, name, info ) ) ] - HydrusGlobals.client_controller.WriteSynchronous( 'update_services', edit_log ) + self._controller.WriteSynchronous( 'update_services', edit_log ) time.sleep( 2 ) @@ -332,7 +337,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): wx.CallAfter( ClientGUICommon.ShowKeys, 'access', ( access_key, ) ) - admin_service = HydrusGlobals.client_controller.GetServicesManager().GetService( admin_service_key ) + admin_service = self._controller.GetServicesManager().GetService( admin_service_key ) # @@ -353,7 +358,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): service_keys_to_access_keys = dict( response[ 'service_keys_to_access_keys' ] ) - HydrusGlobals.client_controller.WriteSynchronous( 'update_server_services', admin_service_key, [], edit_log, service_keys_to_access_keys ) + self._controller.WriteSynchronous( 'update_server_services', admin_service_key, [], edit_log, service_keys_to_access_keys ) HydrusData.ShowText( 'Done! Check services->review services to see your new server and its services.' ) @@ -364,7 +369,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if dlg.ShowModal() == wx.ID_YES: - HydrusGlobals.client_controller.CallToThread( do_it ) + self._controller.CallToThread( do_it ) @@ -373,7 +378,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): def do_it(): - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) service.Request( HC.POST, 'backup' ) @@ -385,7 +390,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): while result == '1': - if HydrusGlobals.view_shutdown: + if self._controller.ViewIsShutdown(): return @@ -404,7 +409,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if dlg.ShowModal() == wx.ID_YES: - HydrusGlobals.client_controller.CallToThread( do_it ) + self._controller.CallToThread( do_it ) @@ -417,7 +422,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if dlg.ShowModal() == wx.ID_YES: - HydrusGlobals.client_controller.Write( 'db_integrity' ) + self._controller.Write( 'db_integrity' ) @@ -434,7 +439,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): result = dlg.ShowModal() - if result == wx.ID_YES: HydrusGlobals.client_controller.Write( 'file_integrity', 'quick' ) + if result == wx.ID_YES: self._controller.Write( 'file_integrity', 'quick' ) elif result == wx.ID_NO: text = 'If an existing file is found to be corrupt/incorrect, would you like to move it or delete it?' @@ -449,15 +454,15 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if dlg_3.ShowModal() == wx.ID_OK: - path = dlg_3.GetPath() + path = HydrusData.ToUnicode( dlg_3.GetPath() ) - HydrusGlobals.client_controller.Write( 'file_integrity', 'thorough', path ) + self._controller.Write( 'file_integrity', 'thorough', path ) elif result == wx.ID_NO: - HydrusGlobals.client_controller.Write( 'file_integrity', 'thorough' ) + self._controller.Write( 'file_integrity', 'thorough' ) @@ -473,8 +478,8 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): def _ClosePage( self, selection, polite = True ): - HydrusGlobals.client_controller.ResetIdleTimer() - HydrusGlobals.client_controller.ResetPageChangeTimer() + self._controller.ResetIdleTimer() + self._controller.ResetPageChangeTimer() if selection == -1 or selection > self._notebook.GetPageCount() - 1: @@ -513,7 +518,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if self._notebook.GetPageCount() == 0: self._focus_holder.SetFocus() - HydrusGlobals.client_controller.pub( 'notify_new_undo' ) + self._controller.pub( 'notify_new_undo' ) def _DeleteAllClosedPages( self ): @@ -529,7 +534,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): self._focus_holder.SetFocus() - HydrusGlobals.client_controller.pub( 'notify_new_undo' ) + self._controller.pub( 'notify_new_undo' ) def _DeleteOrphans( self ): @@ -538,17 +543,17 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): with ClientGUIDialogs.DialogYesNo( self, text ) as dlg: - if dlg.ShowModal() == wx.ID_YES: HydrusGlobals.client_controller.Write( 'delete_orphans' ) + if dlg.ShowModal() == wx.ID_YES: self._controller.Write( 'delete_orphans' ) def _DeletePending( self, service_key ): - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) with ClientGUIDialogs.DialogYesNo( self, 'Are you sure you want to delete the pending data for ' + service.GetName() + '?' ) as dlg: - if dlg.ShowModal() == wx.ID_YES: HydrusGlobals.client_controller.Write( 'delete_pending', service_key ) + if dlg.ShowModal() == wx.ID_YES: self._controller.Write( 'delete_pending', service_key ) @@ -556,7 +561,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): with ClientGUIDialogs.DialogYesNo( self, 'Are you sure you want to clear the cached service info? Rebuilding it may slow some GUI elements for a little while.' ) as dlg: - if dlg.ShowModal() == wx.ID_YES: HydrusGlobals.client_controller.Write( 'delete_service_info' ) + if dlg.ShowModal() == wx.ID_YES: self._controller.Write( 'delete_service_info' ) @@ -586,7 +591,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): hash = dlg.GetValue().decode( 'hex' ) - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) with wx.BusyCursor(): response = service.Request( HC.GET, 'ip', { 'hash' : hash.encode( 'hex' ) } ) @@ -606,7 +611,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): menu = wx.Menu() - p = HydrusGlobals.client_controller.PrepStringForDisplay + p = self._controller.PrepStringForDisplay def file(): @@ -627,7 +632,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): menu.AppendSeparator() - gui_session_names = HydrusGlobals.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION ) + gui_session_names = self._controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION ) sessions = wx.Menu() @@ -674,7 +679,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): have_closed_pages = len( self._closed_pages ) > 0 - undo_manager = HydrusGlobals.client_controller.GetManager( 'undo' ) + undo_manager = self._controller.GetManager( 'undo' ) ( undo_string, redo_string ) = undo_manager.GetUndoRedoStrings() @@ -744,7 +749,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): def search(): - services = HydrusGlobals.client_controller.GetServicesManager().GetServices() + services = self._controller.GetServicesManager().GetServices() tag_repositories = [ service for service in services if service.GetServiceType() == HC.TAG_REPOSITORY ] @@ -784,7 +789,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): submenu.AppendMenu( CC.ID_NULL, p( '&Hentai Foundry' ), hf_submenu ) submenu.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'new_import_gallery', HC.SITE_TYPE_NEWGROUNDS ), p( 'Newgrounds' ), p( 'Open a new tab to download files from Newgrounds.' ) ) - ( id, password ) = HydrusGlobals.client_controller.Read( 'pixiv_account' ) + ( id, password ) = self._controller.Read( 'pixiv_account' ) if id != '' and password != '': @@ -828,13 +833,13 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): def pending(): - nums_pending = HydrusGlobals.client_controller.Read( 'nums_pending' ) + nums_pending = self._controller.Read( 'nums_pending' ) total_num_pending = 0 for ( service_key, info ) in nums_pending.items(): - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) service_type = service.GetServiceType() name = service.GetName() @@ -870,8 +875,8 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): def services(): - tag_services = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, ) ) - file_services = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.FILE_REPOSITORY, ) ) + tag_services = self._controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, ) ) + file_services = self._controller.GetServicesManager().GetServices( ( HC.FILE_REPOSITORY, ) ) submenu = wx.Menu() @@ -922,13 +927,13 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): def admin(): - tag_repositories = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, ) ) + tag_repositories = self._controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, ) ) admin_tag_services = [ repository for repository in tag_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ] - file_repositories = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.FILE_REPOSITORY, ) ) + file_repositories = self._controller.GetServicesManager().GetServices( ( HC.FILE_REPOSITORY, ) ) admin_file_services = [ repository for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ] - servers_admin = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.SERVER_ADMIN, ) ) + servers_admin = self._controller.GetServicesManager().GetServices( ( HC.SERVER_ADMIN, ) ) server_admins = [ service for service in servers_admin if service.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ] if len( admin_tag_services ) > 0 or len( admin_file_services ) > 0 or len( server_admins ) > 0: @@ -1065,9 +1070,9 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if dlg.ShowModal() == wx.ID_OK: - paths = dlg.GetPaths() + paths = [ HydrusData.ToUnicode( path ) for path in dlg.GetPaths() ] - services = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.LOCAL_TAG, HC.TAG_REPOSITORY ) ) + services = self._controller.GetServicesManager().GetServices( ( HC.LOCAL_TAG, HC.TAG_REPOSITORY ) ) service_keys = [ service.GetServiceKey() for service in services ] @@ -1100,7 +1105,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): try: - session = HydrusGlobals.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION, name ) + session = self._controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION, name ) except Exception as e: @@ -1134,7 +1139,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): file_service_key = management_controller.GetKey( 'file_service' ) - initial_media_results = HydrusGlobals.client_controller.Read( 'media_results', file_service_key, initial_hashes ) + initial_media_results = self._controller.Read( 'media_results', file_service_key, initial_hashes ) else: @@ -1248,7 +1253,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): def _ModifyAccount( self, service_key ): - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) with ClientGUIDialogs.DialogTextEntry( self, 'Enter the account key for the account to be modified.' ) as dlg: @@ -1271,8 +1276,8 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): def _NewPage( self, page_name, management_controller, initial_media_results = None ): - HydrusGlobals.client_controller.ResetIdleTimer() - HydrusGlobals.client_controller.ResetPageChangeTimer() + self._controller.ResetIdleTimer() + self._controller.ResetPageChangeTimer() if initial_media_results is None: @@ -1330,7 +1335,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): management_controller = ClientGUIManagement.CreateManagementControllerPetitions( service_key ) - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) page_name = service.GetName() + ' petitions' @@ -1361,12 +1366,12 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): export_path = ClientFiles.GetExportPath() - HydrusFileHandling.LaunchDirectory( export_path ) + HydrusPaths.LaunchDirectory( export_path ) def _OpenInstallFolder( self ): - HydrusFileHandling.LaunchDirectory( HC.BASE_DIR ) + HydrusPaths.LaunchDirectory( HC.BASE_DIR ) def _PauseSync( self, sync_type ): @@ -1375,28 +1380,28 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): HC.options[ 'pause_repo_sync' ] = not HC.options[ 'pause_repo_sync' ] - HydrusGlobals.client_controller.pub( 'notify_restart_repo_sync_daemon' ) + self._controller.pub( 'notify_restart_repo_sync_daemon' ) elif sync_type == 'subs': HC.options[ 'pause_subs_sync' ] = not HC.options[ 'pause_subs_sync' ] - HydrusGlobals.client_controller.pub( 'notify_restart_subs_sync_daemon' ) + self._controller.pub( 'notify_restart_subs_sync_daemon' ) elif sync_type == 'export_folders': HC.options[ 'pause_export_folders_sync' ] = not HC.options[ 'pause_export_folders_sync' ] - HydrusGlobals.client_controller.pub( 'notify_restart_export_folders_daemon' ) + self._controller.pub( 'notify_restart_export_folders_daemon' ) elif sync_type == 'import_folders': HC.options[ 'pause_import_folders_sync' ] = not HC.options[ 'pause_import_folders_sync' ] - HydrusGlobals.client_controller.pub( 'notify_restart_import_folders_daemon' ) + self._controller.pub( 'notify_restart_import_folders_daemon' ) - HydrusGlobals.client_controller.Write( 'save_options', HC.options ) + self._controller.Write( 'save_options', HC.options ) def _PostNews( self, service_key ): @@ -1407,7 +1412,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): news = dlg.GetValue() - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) with wx.BusyCursor(): service.Request( HC.POST, 'news', { 'news' : news } ) @@ -1421,7 +1426,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): if page is None: media_status = '' else: media_status = page.GetPrettyStatus() - if HydrusGlobals.client_controller.CurrentlyIdle(): + if self._controller.CurrentlyIdle(): idle_status = 'idle' @@ -1430,7 +1435,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): idle_status = '' - if HydrusGlobals.client_controller.SystemBusy(): + if self._controller.SystemBusy(): busy_status = 'busy' @@ -1439,7 +1444,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): busy_status = '' - if HydrusGlobals.client_controller.GetDB().CurrentlyDoingJob(): + if self._controller.GetDB().CurrentlyDoingJob(): db_status = 'db locked' @@ -1470,7 +1475,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): job_key.SetVariable( 'popup_text_1', prefix + 'creating directories' ) - HydrusGlobals.client_controller.pub( 'message', job_key ) + self._controller.pub( 'message', job_key ) if not os.path.exists( HC.CLIENT_THUMBNAILS_DIR ): os.mkdir( HC.CLIENT_THUMBNAILS_DIR ) @@ -1478,9 +1483,12 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): for ( one, two ) in itertools.product( hex_chars, hex_chars ): - dir = HC.CLIENT_THUMBNAILS_DIR + os.path.sep + one + two + dir = os.path.join( HC.CLIENT_THUMBNAILS_DIR, one + two ) - if not os.path.exists( dir ): os.mkdir( dir ) + if not os.path.exists( dir ): + + os.mkdir( dir ) + num_broken = 0 @@ -1551,7 +1559,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): job_key.Finish() - HydrusGlobals.client_controller.CallToThread( THREADRegenerateThumbnails ) + self._controller.CallToThread( THREADRegenerateThumbnails ) @@ -1576,7 +1584,10 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): - def _ReviewServices( self ): FrameReviewServices() + def _ReviewServices( self ): + + FrameReviewServices( self._controller ) + def _SaveGUISession( self, name = None ): @@ -1629,9 +1640,9 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ): session.AddPage( page_name, management_controller, hashes ) - HydrusGlobals.client_controller.Write( 'serialisable', session ) + self._controller.Write( 'serialisable', session ) - HydrusGlobals.client_controller.pub( 'notify_new_sessions' ) + self._controller.pub( 'notify_new_sessions' ) def _SetPassword( self ): @@ -1652,7 +1663,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p if password == '': password = None - HydrusGlobals.client_controller.Write( 'set_password', password ) + self._controller.Write( 'set_password', password ) @@ -1692,9 +1703,9 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p job_key = HydrusThreading.JobKey( pausable = True, cancellable = True ) - HydrusGlobals.client_controller.pub( 'message', job_key ) + self._controller.pub( 'message', job_key ) - HydrusGlobals.client_controller.CallToThread( ClientDownloading.THREADDownloadURL, job_key, url, url_string ) + self._controller.CallToThread( ClientDownloading.THREADDownloadURL, job_key, url, url_string ) @@ -1718,13 +1729,13 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p def _Stats( self, service_key ): - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) response = service.Request( HC.GET, 'stats' ) stats = response[ 'stats' ] - wx.MessageBox( HydrusData.ToString( stats ) ) + wx.MessageBox( HydrusData.ToUnicode( stats ) ) def _UnclosePage( self, closed_page_index ): @@ -1740,12 +1751,12 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p self._notebook.InsertPage( index, page, name, True ) - HydrusGlobals.client_controller.pub( 'notify_new_undo' ) + self._controller.pub( 'notify_new_undo' ) def _UploadPending( self, service_key ): - HydrusGlobals.client_controller.CallToThread( self._THREADUploadPending, service_key ) + self._controller.CallToThread( self._THREADUploadPending, service_key ) def _VacuumDatabase( self ): @@ -1754,13 +1765,13 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p with ClientGUIDialogs.DialogYesNo( self, text ) as dlg: - if dlg.ShowModal() == wx.ID_YES: HydrusGlobals.client_controller.Write( 'vacuum' ) + if dlg.ShowModal() == wx.ID_YES: self._controller.Write( 'vacuum' ) def _THREADUploadPending( self, service_key ): - service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + service = self._controller.GetServicesManager().GetService( service_key ) service_name = service.GetName() service_type = service.GetServiceType() @@ -1773,15 +1784,15 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p job_key.SetVariable( 'popup_text_1', prefix + 'gathering pending content' ) - HydrusGlobals.client_controller.pub( 'message', job_key ) + self._controller.pub( 'message', job_key ) - result = HydrusGlobals.client_controller.Read( 'pending', service_key ) + result = self._controller.Read( 'pending', service_key ) if service_type == HC.FILE_REPOSITORY: ( upload_hashes, update ) = result - media_results = HydrusGlobals.client_controller.Read( 'media_results', CC.LOCAL_FILE_SERVICE_KEY, upload_hashes ) + media_results = self._controller.Read( 'media_results', CC.LOCAL_FILE_SERVICE_KEY, upload_hashes ) job_key.SetVariable( 'popup_text_1', prefix + 'connecting to repository' ) @@ -1834,7 +1845,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ADD, content_update_row ) ] - HydrusGlobals.client_controller.Write( 'content_updates', { service_key : content_updates } ) + self._controller.Write( 'content_updates', { service_key : content_updates } ) except HydrusExceptions.ServerBusyException: @@ -1845,7 +1856,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p time.sleep( 0.1 ) - HydrusGlobals.client_controller.WaitUntilPubSubsEmpty() + self._controller.WaitUntilPubSubsEmpty() if not update.IsEmpty(): @@ -1856,7 +1867,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p content_updates = update.GetContentUpdates( for_client = True ) - HydrusGlobals.client_controller.Write( 'content_updates', { service_key : content_updates } ) + self._controller.Write( 'content_updates', { service_key : content_updates } ) elif service_type == HC.TAG_REPOSITORY: @@ -1895,7 +1906,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p content_updates = update.GetContentUpdates( for_client = True ) - HydrusGlobals.client_controller.Write( 'content_updates', { service_key : content_updates } ) + self._controller.Write( 'content_updates', { service_key : content_updates } ) except HydrusExceptions.ServerBusyException: @@ -1906,7 +1917,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p time.sleep( 0.1 ) - HydrusGlobals.client_controller.WaitUntilPubSubsEmpty() + self._controller.WaitUntilPubSubsEmpty() @@ -1926,7 +1937,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p wx.CallLater( 1000 * 5, job_key.Delete ) - HydrusGlobals.client_controller.pub( 'notify_new_pending' ) + self._controller.pub( 'notify_new_pending' ) def ClearClosedPages( self ): @@ -1951,7 +1962,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p else: self._closed_pages.append( ( time_closed, index, name, page ) ) - if len( old_closed_pages ) != len( self._closed_pages ): HydrusGlobals.client_controller.pub( 'notify_new_undo' ) + if len( old_closed_pages ) != len( self._closed_pages ): self._controller.pub( 'notify_new_undo' ) self._DestroyPages( deletee_pages ) @@ -1983,7 +1994,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p - HydrusGlobals.client_controller.Exit() + self._controller.Exit() def EventFocus( self, event ): @@ -2004,10 +2015,10 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p if command == 'account_info': self._AccountInfo( data ) elif command == 'auto_repo_setup': self._AutoRepoSetup() elif command == 'auto_server_setup': self._AutoServerSetup() - elif command == 'backup_database': HydrusGlobals.client_controller.BackupDatabase() + elif command == 'backup_database': self._controller.BackupDatabase() elif command == 'backup_service': self._BackupService( data ) elif command == 'check_db_integrity': self._CheckDBIntegrity() - elif command == 'clear_caches': HydrusGlobals.client_controller.ClearCaches() + elif command == 'clear_caches': self._controller.ClearCaches() elif command == 'close_page': self._CloseCurrentPage() elif command == 'db_profile_mode': @@ -2048,14 +2059,14 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p if v > 100: print ( k, v ) - print( 'garbage: ' + HydrusData.ToString( gc.garbage ) ) + print( 'garbage: ' + HydrusData.ToUnicode( gc.garbage ) ) elif command == 'delete_all_closed_pages': self._DeleteAllClosedPages() elif command == 'delete_gui_session': - HydrusGlobals.client_controller.Write( 'delete_serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION, data ) + self._controller.Write( 'delete_serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION, data ) - HydrusGlobals.client_controller.pub( 'notify_new_sessions' ) + self._controller.pub( 'notify_new_sessions' ) elif command == 'delete_orphans': self._DeleteOrphans() elif command == 'delete_pending': self._DeletePending( data ) @@ -2064,10 +2075,11 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p elif command == 'fetch_ip': self._FetchIP( data ) elif command == 'force_idle': - HydrusGlobals.client_controller.ForceIdle() + self._controller.ForceIdle() + elif command == 'force_unbusy': - HydrusGlobals.client_controller.ForceUnbusy() + self._controller.ForceUnbusy() elif command == '8chan_board': webbrowser.open( 'https://8ch.net/hydrus/index.html' ) elif command == 'file_integrity': self._CheckFileIntegrity() @@ -2119,7 +2131,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p elif command == 'pause_subs_sync': self._PauseSync( 'subs' ) elif command == 'petitions': self._NewPagePetitions( data ) elif command == 'post_news': self._PostNews( data ) - elif command == 'redo': HydrusGlobals.client_controller.pub( 'redo' ) + elif command == 'redo': self._controller.pub( 'redo' ) elif command == 'refresh': page = self._notebook.GetCurrentPage() @@ -2127,7 +2139,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p if page is not None: page.RefreshQuery() elif command == 'regenerate_thumbnails': self._RegenerateThumbnails() - elif command == 'restore_database': HydrusGlobals.client_controller.RestoreDatabase() + elif command == 'restore_database': self._controller.RestoreDatabase() elif command == 'review_services': self._ReviewServices() elif command == 'save_gui_session': self._SaveGUISession() elif command == 'set_password': self._SetPassword() @@ -2153,7 +2165,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p elif command == 'tumblr': webbrowser.open( 'http://hydrus.tumblr.com/' ) elif command == 'twitter': webbrowser.open( 'https://twitter.com/#!/hydrusnetwork' ) elif command == 'unclose_page': self._UnclosePage( data ) - elif command == 'undo': HydrusGlobals.client_controller.pub( 'undo' ) + elif command == 'undo': self._controller.pub( 'undo' ) elif command == 'upload_pending': self._UploadPending( data ) elif command == 'vacuum_db': self._VacuumDatabase() else: event.Skip() @@ -2381,7 +2393,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p def ShowSeedCache( self, seed_cache ): - FrameSeedCache( seed_cache ) + FrameSeedCache( self._controller, seed_cache ) def Shutdown( self ): @@ -2407,7 +2419,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p ( HC.options[ 'hpos' ], HC.options[ 'vpos' ] ) = page.GetSashPositions() - HydrusGlobals.client_controller.Write( 'save_options', HC.options ) + self._controller.Write( 'save_options', HC.options ) wx.CallAfter( self.Destroy ) @@ -2451,15 +2463,17 @@ class FrameComposeMessage( ClientGUICommon.Frame ): ''' class FrameReviewServices( ClientGUICommon.Frame ): - def __init__( self ): + def __init__( self, controller ): - ( pos_x, pos_y ) = HydrusGlobals.client_controller.GetGUI().GetPositionTuple() + self._controller = controller + + ( pos_x, pos_y ) = self._controller.GetGUI().GetPositionTuple() pos = ( pos_x + 25, pos_y + 50 ) tlp = wx.GetApp().GetTopWindow() - ClientGUICommon.Frame.__init__( self, tlp, title = HydrusGlobals.client_controller.PrepStringForDisplay( 'Review Services' ), pos = pos ) + ClientGUICommon.Frame.__init__( self, tlp, title = self._controller.PrepStringForDisplay( 'Review Services' ), pos = pos ) self._notebook = wx.Notebook( self ) @@ -2491,7 +2505,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): self.Show( True ) - HydrusGlobals.client_controller.sub( self, 'RefreshServices', 'notify_new_services_gui' ) + self._controller.sub( self, 'RefreshServices', 'notify_new_services_gui' ) wx.CallAfter( self.Raise ) @@ -2505,7 +2519,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): listbook_dict = {} - services = HydrusGlobals.client_controller.GetServicesManager().GetServices() + services = self._controller.GetServicesManager().GetServices() for service in services: @@ -2538,7 +2552,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): name = service.GetName() - listbook.AddPageArgs( name, self._Panel, ( listbook, service.GetServiceKey() ), {} ) + listbook.AddPageArgs( name, self._Panel, ( listbook, self._controller, service.GetServiceKey() ), {} ) wx.CallAfter( self._local_listbook.Layout ) @@ -2566,15 +2580,16 @@ class FrameReviewServices( ClientGUICommon.Frame ): class _Panel( wx.ScrolledWindow ): - def __init__( self, parent, service_key ): + def __init__( self, parent, controller, service_key ): wx.ScrolledWindow.__init__( self, parent ) self.SetScrollRate( 0, 20 ) + self._controller = controller self._service_key = service_key - self._service = HydrusGlobals.client_controller.GetServicesManager().GetService( service_key ) + self._service = self._controller.GetServicesManager().GetService( service_key ) service_type = self._service.GetServiceType() @@ -2814,9 +2829,9 @@ class FrameReviewServices( ClientGUICommon.Frame ): self._timer_updates.Start( 1000, wx.TIMER_CONTINUOUS ) - HydrusGlobals.client_controller.sub( self, 'ProcessServiceUpdates', 'service_updates_gui' ) - HydrusGlobals.client_controller.sub( self, 'AddThumbnailCount', 'add_thumbnail_count' ) - if service_type == HC.LOCAL_BOORU: HydrusGlobals.client_controller.sub( self, 'RefreshLocalBooruShares', 'refresh_local_booru_shares' ) + self._controller.sub( self, 'ProcessServiceUpdates', 'service_updates_gui' ) + self._controller.sub( self, 'AddThumbnailCount', 'add_thumbnail_count' ) + if service_type == HC.LOCAL_BOORU: self._controller.sub( self, 'RefreshLocalBooruShares', 'refresh_local_booru_shares' ) def _DisplayAccountInfo( self ): @@ -2965,7 +2980,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): if service_type in HC.REPOSITORIES + HC.LOCAL_SERVICES: - service_info = HydrusGlobals.client_controller.Read( 'service_info', self._service_key ) + service_info = self._controller.Read( 'service_info', self._service_key ) if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ): @@ -3006,7 +3021,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): num_ratings = service_info[ HC.SERVICE_INFO_NUM_FILES ] - self._ratings_text.SetLabel( HydrusData.ToString( num_ratings ) + ' files rated' ) + self._ratings_text.SetLabel( str( num_ratings ) + ' files rated' ) elif service_type == HC.LOCAL_BOORU: @@ -3018,7 +3033,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): if service_type == HC.LOCAL_BOORU: - booru_shares = HydrusGlobals.client_controller.Read( 'local_booru_shares' ) + booru_shares = self._controller.Read( 'local_booru_shares' ) self._booru_shares.DeleteAllItems() @@ -3062,7 +3077,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): for ( name, text, timeout, ( num_hashes, hashes, share_key ) ) in self._booru_shares.GetSelectedClientData(): - HydrusGlobals.client_controller.Write( 'delete_local_booru_share', share_key ) + self._controller.Write( 'delete_local_booru_share', share_key ) @@ -3092,16 +3107,16 @@ class FrameReviewServices( ClientGUICommon.Frame ): - for ( share_key, info ) in writes: HydrusGlobals.client_controller.Write( 'local_booru_share', share_key, info ) + for ( share_key, info ) in writes: self._controller.Write( 'local_booru_share', share_key, info ) def EventBooruOpenSearch( self, event ): for ( name, text, timeout, ( num_hashes, hashes, share_key ) ) in self._booru_shares.GetSelectedClientData(): - media_results = HydrusGlobals.client_controller.Read( 'media_results', CC.LOCAL_FILE_SERVICE_KEY, hashes ) + media_results = self._controller.Read( 'media_results', CC.LOCAL_FILE_SERVICE_KEY, hashes ) - HydrusGlobals.client_controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_media_results = media_results ) + self._controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_media_results = media_results ) @@ -3111,7 +3126,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): account_key_hex = account_key.encode( 'hex' ) - HydrusGlobals.client_controller.pub( 'clipboard', 'text', account_key_hex ) + self._controller.pub( 'clipboard', 'text', account_key_hex ) def EventCopyExternalShareURL( self, event ): @@ -3122,7 +3137,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): ( name, text, timeout, ( num_hashes, hashes, share_key ) ) = shares[0] - self._service = HydrusGlobals.client_controller.GetServicesManager().GetService( CC.LOCAL_BOORU_SERVICE_KEY ) + self._service = self._controller.GetServicesManager().GetService( CC.LOCAL_BOORU_SERVICE_KEY ) info = self._service.GetInfo() @@ -3134,7 +3149,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): url = 'http://' + external_ip + ':' + str( external_port ) + '/gallery?share_key=' + share_key.encode( 'hex' ) - HydrusGlobals.client_controller.pub( 'clipboard', 'text', url ) + self._controller.pub( 'clipboard', 'text', url ) @@ -3146,7 +3161,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): ( name, text, timeout, ( num_hashes, hashes, share_key ) ) = shares[0] - self._service = HydrusGlobals.client_controller.GetServicesManager().GetService( CC.LOCAL_BOORU_SERVICE_KEY ) + self._service = self._controller.GetServicesManager().GetService( CC.LOCAL_BOORU_SERVICE_KEY ) info = self._service.GetInfo() @@ -3156,7 +3171,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): url = 'http://' + internal_ip + ':' + str( internal_port ) + '/gallery?share_key=' + share_key.encode( 'hex' ) - HydrusGlobals.client_controller.pub( 'clipboard', 'text', url ) + self._controller.pub( 'clipboard', 'text', url ) @@ -3169,7 +3184,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): job_key.SetVariable( 'popup_title', self._service.GetName() + ': immediate sync' ) job_key.SetVariable( 'popup_text_1', 'downloading' ) - HydrusGlobals.client_controller.pub( 'message', job_key ) + self._controller.pub( 'message', job_key ) content_update_package = self._service.Request( HC.GET, 'immediate_content_update_package' ) @@ -3214,7 +3229,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): precise_timestamp = HydrusData.GetNowPrecise() - HydrusGlobals.client_controller.WriteSynchronous( 'content_updates', { self._service_key : pending_content_updates } ) + self._controller.WriteSynchronous( 'content_updates', { self._service_key : pending_content_updates } ) it_took = HydrusData.GetNowPrecise() - precise_timestamp @@ -3231,7 +3246,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): if len( pending_content_updates ) > 0: - HydrusGlobals.client_controller.WriteSynchronous( 'content_updates', { self._service_key : pending_content_updates } ) + self._controller.WriteSynchronous( 'content_updates', { self._service_key : pending_content_updates } ) c_u_p_total_weight_processed += pending_weight @@ -3242,7 +3257,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): job_key.Finish() - HydrusGlobals.client_controller.CallToThread( do_it ) + self._controller.CallToThread( do_it ) def EventServiceWideUpdate( self, event ): @@ -3267,7 +3282,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): edit_log = [ HydrusData.EditLogActionEdit( service_key, ( service_key, service_type, name, info_update ) ) ] - HydrusGlobals.client_controller.Write( 'update_services', edit_log ) + self._controller.Write( 'update_services', edit_log ) ClientGUICommon.ShowKeys( 'access', ( access_key, ) ) @@ -3282,7 +3297,7 @@ class FrameReviewServices( ClientGUICommon.Frame ): account.MakeFresh() - HydrusGlobals.client_controller.Write( 'service_updates', { self._service_key : [ HydrusData.ServiceUpdate( HC.SERVICE_UPDATE_ACCOUNT, account ) ] } ) + self._controller.Write( 'service_updates', { self._service_key : [ HydrusData.ServiceUpdate( HC.SERVICE_UPDATE_ACCOUNT, account ) ] } ) def ProcessServiceUpdates( self, service_keys_to_service_updates ): @@ -3321,15 +3336,17 @@ class FrameReviewServices( ClientGUICommon.Frame ): class FrameSeedCache( ClientGUICommon.Frame ): - def __init__( self, seed_cache ): + def __init__( self, controller, seed_cache ): - ( pos_x, pos_y ) = HydrusGlobals.client_controller.GetGUI().GetPositionTuple() + self._controller = controller + + ( pos_x, pos_y ) = self._controller.GetGUI().GetPositionTuple() pos = ( pos_x + 25, pos_y + 50 ) tlp = wx.GetApp().GetTopWindow() - ClientGUICommon.Frame.__init__( self, tlp, title = HydrusGlobals.client_controller.PrepStringForDisplay( 'File Import Status' ), pos = pos ) + ClientGUICommon.Frame.__init__( self, tlp, title = self._controller.PrepStringForDisplay( 'File Import Status' ), pos = pos ) self._seed_cache = seed_cache @@ -3347,7 +3364,7 @@ class FrameSeedCache( ClientGUICommon.Frame ): self.Show( True ) - HydrusGlobals.client_controller.sub( self, 'NotifySeedUpdated', 'seed_cache_seed_updated' ) + self._controller.sub( self, 'NotifySeedUpdated', 'seed_cache_seed_updated' ) wx.CallAfter( self._UpdateText ) @@ -3373,7 +3390,9 @@ class FrameSplash( ClientGUICommon.Frame ): WIDTH = 300 HEIGHT = 250 - def __init__( self ): + def __init__( self, controller ): + + self._controller = controller style = wx.FRAME_NO_TASKBAR @@ -3394,7 +3413,7 @@ class FrameSplash( ClientGUICommon.Frame ): self._initial_position = self.GetPosition() # this is 124 x 166 - self._hydrus = wx.Bitmap( HC.STATIC_DIR + os.path.sep + 'hydrus_splash.png' ) + self._hydrus = wx.Bitmap( os.path.join( HC.STATIC_DIR, 'hydrus_splash.png' ) ) self.Bind( wx.EVT_PAINT, self.EventPaint ) self.Bind( wx.EVT_MOTION, self.EventDrag ) @@ -3404,9 +3423,11 @@ class FrameSplash( ClientGUICommon.Frame ): self.Show( True ) - HydrusGlobals.client_controller.sub( self, 'SetTitleText', 'splash_set_title_text' ) - HydrusGlobals.client_controller.sub( self, 'SetStatusText', 'splash_set_status_text' ) - HydrusGlobals.client_controller.sub( self, 'Destroy', 'splash_destroy' ) + self._controller.sub( self, 'SetTitleText', 'splash_set_title_text' ) + self._controller.sub( self, 'SetStatusText', 'splash_set_status_text' ) + self._controller.sub( self, 'Destroy', 'splash_destroy' ) + + self.Raise() def _Redraw( self ): diff --git a/include/ClientGUICanvas.py b/include/ClientGUICanvas.py index 858773e1..43171ab1 100755 --- a/include/ClientGUICanvas.py +++ b/include/ClientGUICanvas.py @@ -12,6 +12,7 @@ import ClientRatings import collections import gc import HydrusImageHandling +import HydrusPaths import HydrusTags import HydrusVideoHandling import os @@ -25,7 +26,6 @@ import wx import wx.media import ClientRendering import HydrusData -import HydrusFileHandling import HydrusGlobals if HC.PLATFORM_WINDOWS: import wx.lib.flashwin @@ -131,7 +131,7 @@ class Animation( wx.Window ): self._paused = start_paused - self._canvas_bmp = wx.EmptyBitmap( 0, 0, 24 ) + self._canvas_bmp = wx.EmptyBitmap( 20, 20, 24 ) self._timer_video = wx.Timer( self, id = ID_TIMER_VIDEO ) @@ -287,6 +287,14 @@ class Animation( wx.Window ): self._canvas_bmp = wx.EmptyBitmap( my_width, my_height, 24 ) + dc = wx.MemoryDC( self._canvas_bmp ) + + dc.SetBackground( wx.Brush( wx.Colour( *HC.options[ 'gui_colours' ][ 'media_background' ] ) ) ) + + dc.Clear() + + del dc + self._a_frame_has_been_drawn = False if self._video_container.HasFrame( self._current_frame_index ): self._DrawFrame() @@ -342,7 +350,7 @@ class Animation( wx.Window ): def TIMEREventVideo( self, event ): - if self.IsShown(): + if self.IsShownOnScreen(): if self._current_frame_drawn: @@ -514,7 +522,7 @@ class AnimationBar( wx.Window ): def TIMEREventUpdate( self, event ): - if self.IsShown(): + if self.IsShownOnScreen(): if self._media.GetMime() == HC.APPLICATION_FLASH: @@ -577,7 +585,7 @@ class Canvas( object ): self.SetBackgroundColour( wx.Colour( *HC.options[ 'gui_colours' ][ 'media_background' ] ) ) - self._canvas_bmp = wx.EmptyBitmap( 0, 0, 24 ) + self._canvas_bmp = wx.EmptyBitmap( 20, 20, 24 ) self.Bind( wx.EVT_SIZE, self.EventResize ) @@ -786,7 +794,7 @@ class Canvas( object ): path = ClientFiles.GetFilePath( hash, mime ) - HydrusFileHandling.LaunchFile( path ) + HydrusPaths.LaunchFile( path ) if self._current_display_media.HasDuration() and mime != HC.APPLICATION_FLASH: @@ -1062,15 +1070,22 @@ class Canvas( object ): if media is not None: - locations_manager = media.GetLocationsManager() - - if not locations_manager.HasLocal(): + if not self.IsShownOnScreen(): media = None - elif HC.options[ 'mime_media_viewer_actions' ][ media.GetDisplayMedia().GetMime() ] == CC.MEDIA_VIEWER_DO_NOT_SHOW: + else: - media = None + locations_manager = media.GetLocationsManager() + + if not locations_manager.HasLocal(): + + media = None + + elif HC.options[ 'mime_media_viewer_actions' ][ media.GetDisplayMedia().GetMime() ] == CC.MEDIA_VIEWER_DO_NOT_SHOW: + + media = None + @@ -3155,7 +3170,7 @@ class EmbedButton( wx.Window ): self._dirty = True - self._canvas_bmp = wx.EmptyBitmap( 0, 0, 24 ) + self._canvas_bmp = wx.EmptyBitmap( 20, 20, 24 ) self.Bind( wx.EVT_PAINT, self.EventPaint ) self.Bind( wx.EVT_SIZE, self.EventResize ) @@ -3262,7 +3277,7 @@ class OpenExternallyButton( wx.Button ): path = ClientFiles.GetFilePath( hash, mime ) - HydrusFileHandling.LaunchFile( path ) + HydrusPaths.LaunchFile( path ) class StaticImage( wx.Window ): @@ -3277,7 +3292,7 @@ class StaticImage( wx.Window ): self._image_container = None self._image_cache = image_cache - self._canvas_bmp = wx.EmptyBitmap( 0, 0, 24 ) + self._canvas_bmp = wx.EmptyBitmap( 20, 20, 24 ) self._timer_render_wait = wx.Timer( self, id = ID_TIMER_RENDER_WAIT ) @@ -3295,7 +3310,7 @@ class StaticImage( wx.Window ): def _Redraw( self ): dc = wx.MemoryDC( self._canvas_bmp ) - + dc.SetBackground( wx.Brush( wx.Colour( *HC.options[ 'gui_colours' ][ 'media_background' ] ) ) ) dc.Clear() diff --git a/include/ClientGUICommon.py b/include/ClientGUICommon.py index e8482cfd..cd056c1c 100755 --- a/include/ClientGUICommon.py +++ b/include/ClientGUICommon.py @@ -32,6 +32,22 @@ ID_TIMER_DROPDOWN_HIDE = wx.NewId() ID_TIMER_AC_LAG = wx.NewId() ID_TIMER_POPUP = wx.NewId() +def IsWXAncestor( child, ancestor ): + + parent = child + + while not isinstance( parent, wx.TopLevelWindow ): + + if parent == ancestor: + + return True + + + parent = parent.GetParent() + + + return False + class AnimatedStaticTextTimestamp( wx.StaticText ): def __init__( self, parent, prefix, rendering_function, timestamp, suffix ): @@ -239,7 +255,7 @@ class AutoCompleteDropdown( wx.Panel ): current_page = gui.GetCurrentPage() - visible = ClientData.IsWXAncestor( self, current_page ) + visible = IsWXAncestor( self, current_page ) else: @@ -639,7 +655,41 @@ class AutoCompleteDropdownTagsRead( AutoCompleteDropdownTags ): self._text_ctrl.SetValue( '' ) - HydrusGlobals.client_controller.pub( 'enter_predicates', self._page_key, predicates ) + entry_predicates = [] + + for predicate in predicates: + + predicate = predicate.GetCountlessCopy() + + ( predicate_type, value, inclusive ) = predicate.GetInfo() + + if predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_SIZE, HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS, HC.PREDICATE_TYPE_SYSTEM_AGE, HC.PREDICATE_TYPE_SYSTEM_HASH, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, HC.PREDICATE_TYPE_SYSTEM_MIME, HC.PREDICATE_TYPE_SYSTEM_RATING, HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ]: + + import ClientGUIDialogs + + with ClientGUIDialogs.DialogInputFileSystemPredicates( self, predicate_type ) as dlg: + + if dlg.ShowModal() == wx.ID_OK: + + entry_predicates.extend( dlg.GetPredicates() ) + + else: + + return + + + + elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_UNTAGGED: + + entry_predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '=', 0 ) ) ) + + else: + + entry_predicates.append( predicate ) + + + + HydrusGlobals.client_controller.pub( 'enter_predicates', self._page_key, entry_predicates ) def _BroadcastCurrentText( self ): @@ -1160,7 +1210,7 @@ class BufferedWindow( wx.Window ): self._canvas_bmp = wx.EmptyBitmap( x, y, 24 ) - else: self._canvas_bmp = wx.EmptyBitmap( 0, 0, 24 ) + else: self._canvas_bmp = wx.EmptyBitmap( 20, 20, 24 ) self.Bind( wx.EVT_PAINT, self.EventPaint ) self.Bind( wx.EVT_SIZE, self.EventResize ) @@ -1544,7 +1594,7 @@ class Frame( wx.Frame ): self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) ) - self.SetIcon( wx.Icon( HC.STATIC_DIR + os.path.sep + 'hydrus.ico', wx.BITMAP_TYPE_ICO ) ) + self.SetIcon( wx.Icon( os.path.join( HC.STATIC_DIR, 'hydrus.ico' ), wx.BITMAP_TYPE_ICO ) ) def SetInitialSize( self, ( width, height ) ): @@ -1996,7 +2046,7 @@ class ListBox( wx.ScrolledWindow ): self._ordered_strings = [] self._strings_to_terms = {} - self._client_bmp = wx.EmptyBitmap( 0, 0, 24 ) + self._client_bmp = wx.EmptyBitmap( 20, 20, 24 ) self._selected_indices = set() self._selected_terms = set() @@ -2321,7 +2371,7 @@ class ListBox( wx.ScrolledWindow ): elif key_code in ( wx.WXK_PAGEUP, wx.WXK_NUMPAD_PAGEUP ): - hit_index = self._last_hit_index - self._num_rows_per_page + hit_index = max( 0, self._last_hit_index - self._num_rows_per_page ) elif key_code in ( wx.WXK_PAGEDOWN, wx.WXK_NUMPAD_PAGEDOWN ): @@ -2418,6 +2468,7 @@ class ListBoxTags( ListBox ): self._background_colour = wx.Colour( *HC.options[ 'gui_colours' ][ 'tags_box' ] ) self.Bind( wx.EVT_RIGHT_DOWN, self.EventMouseRightClick ) + self.Bind( wx.EVT_MIDDLE_DOWN, self.EventMouseMiddleClick ) self.Bind( wx.EVT_MENU, self.EventMenu ) @@ -2450,6 +2501,28 @@ class ListBoxTags( ListBox ): return ( r, g, b ) + def _NewSearchPage( self ): + + predicates = [] + + for term in self._selected_terms: + + if isinstance( term, ClientData.Predicate ): + + predicates.append( term ) + + else: + + predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, term ) ) + + + + if len( predicates ) > 0: + + HydrusGlobals.client_controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_predicates = predicates ) + + + def EventMenu( self, event ): action = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetAction( event.GetId() ) @@ -2501,21 +2574,7 @@ class ListBoxTags( ListBox ): elif command == 'new_search_page': - predicates = [] - - for term in self._selected_terms: - - if isinstance( term, ClientData.Predicate ): - - predicates.append( term ) - - else: - - predicates.append( ClientData.Predicate( HC.PREDICATE_TYPE_TAG, term ) ) - - - - HydrusGlobals.client_controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_predicates = predicates ) + self._NewSearchPage() elif command in ( 'parent', 'sibling' ): @@ -2539,6 +2598,18 @@ class ListBoxTags( ListBox ): + def EventMouseMiddleClick( self, event ): + + hit_index = self._GetIndexUnderMouse( event ) + + shift = event.ShiftDown() + ctrl = event.CmdDown() or event.ControlDown() + + self._Hit( shift, ctrl, hit_index ) + + self._NewSearchPage() + + def EventMouseRightClick( self, event ): hit_index = self._GetIndexUnderMouse( event ) @@ -2707,10 +2778,19 @@ class ListBoxTagsAutocompleteDropdown( ListBoxTags ): def _Hit( self, shift, ctrl, hit_index ): - # this realigns the hit index in the up direction - if hit_index is not None: + if hit_index == -1 or hit_index > len( self._ordered_strings ): + + hit_index = len( self._ordered_strings ) - 1 + + elif hit_index == len( self._ordered_strings ) or hit_index < -1: + + hit_index = 0 + + + # this realigns the hit index in the up direction + hit_term = self._strings_to_terms[ self._ordered_strings[ hit_index ] ] while hit_term.GetType() == HC.PREDICATE_TYPE_PARENT: @@ -3191,84 +3271,62 @@ class ListBoxTagsPredicates( ListBoxTags ): local_predicate = ClientSearch.SYSTEM_PREDICATE_LOCAL not_local_predicate = ClientSearch.SYSTEM_PREDICATE_NOT_LOCAL - for proto_predicate in predicates: + predicates_to_be_added = set() + predicates_to_be_removed = set() + + for predicate in predicates: - predicates_to_be_added = set() - predicates_to_be_removed = set() + predicate = predicate.GetCountlessCopy() - proto_predicate = proto_predicate.GetCountlessCopy() - - ( predicate_type, value, inclusive ) = proto_predicate.GetInfo() - - if predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_SIZE, HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS, HC.PREDICATE_TYPE_SYSTEM_AGE, HC.PREDICATE_TYPE_SYSTEM_HASH, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, HC.PREDICATE_TYPE_SYSTEM_MIME, HC.PREDICATE_TYPE_SYSTEM_RATING, HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ]: + if self._HasPredicate( predicate ): - import ClientGUIDialogs + predicates_to_be_removed.add( predicate ) - with ClientGUIDialogs.DialogInputFileSystemPredicates( self, predicate_type ) as dlg: - - if dlg.ShowModal() == wx.ID_OK: entry_predicates = dlg.GetPredicates() - else: return - - - elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_UNTAGGED: entry_predicates = ( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '=', 0 ) ), ) else: - entry_predicates = ( proto_predicate, ) + predicates_to_be_added.add( predicate ) - - for predicate in entry_predicates: + if predicate == inbox_predicate and self._HasPredicate( archive_predicate ): + + predicates_to_be_removed.add( archive_predicate ) + + elif predicate == archive_predicate and self._HasPredicate( inbox_predicate ): + + predicates_to_be_removed.add( inbox_predicate ) + - if self._HasPredicate( predicate ): + if predicate == local_predicate and self._HasPredicate( not_local_predicate ): - predicates_to_be_removed.add( predicate ) + predicates_to_be_removed.add( not_local_predicate ) - else: + elif predicate == not_local_predicate and self._HasPredicate( local_predicate ): - predicates_to_be_added.add( predicate ) - - if predicate == inbox_predicate and self._HasPredicate( archive_predicate ): - - predicates_to_be_removed.add( archive_predicate ) - - elif predicate == archive_predicate and self._HasPredicate( inbox_predicate ): - - predicates_to_be_removed.add( inbox_predicate ) - - - if predicate == local_predicate and self._HasPredicate( not_local_predicate ): - - predicates_to_be_removed.add( not_local_predicate ) - - elif predicate == not_local_predicate and self._HasPredicate( local_predicate ): - - predicates_to_be_removed.add( local_predicate ) - + predicates_to_be_removed.add( local_predicate ) - for predicate in predicates_to_be_added: - - predicate_string = predicate.GetUnicode() - - self._ordered_strings.append( predicate_string ) - self._strings_to_terms[ predicate_string ] = predicate - + + for predicate in predicates_to_be_added: - for predicate in predicates_to_be_removed: + predicate_string = predicate.GetUnicode() + + self._ordered_strings.append( predicate_string ) + self._strings_to_terms[ predicate_string ] = predicate + + + for predicate in predicates_to_be_removed: + + for ( s, existing_predicate ) in self._strings_to_terms.items(): - for ( s, existing_predicate ) in self._strings_to_terms.items(): + if existing_predicate == predicate: - if existing_predicate == predicate: - - self._ordered_strings.remove( s ) - del self._strings_to_terms[ s ] - - break - + self._ordered_strings.remove( s ) + del self._strings_to_terms[ s ] + + break - self._ordered_strings.sort() @@ -4023,7 +4081,7 @@ class PopupMessage( PopupWindow ): text = self._job_key.GetVariable( 'popup_text_1' ) - if self._text_1.GetLabel() != text: self._text_1.SetLabel( self._ProcessText( HydrusData.ToString( text ) ) ) + if self._text_1.GetLabel() != text: self._text_1.SetLabel( self._ProcessText( HydrusData.ToUnicode( text ) ) ) self._text_1.Show() @@ -4048,7 +4106,7 @@ class PopupMessage( PopupWindow ): text = self._job_key.GetVariable( 'popup_text_2' ) - if self._text_2.GetLabel() != text: self._text_2.SetLabel( self._ProcessText( HydrusData.ToString( text ) ) ) + if self._text_2.GetLabel() != text: self._text_2.SetLabel( self._ProcessText( HydrusData.ToUnicode( text ) ) ) self._text_2.Show() @@ -4088,7 +4146,7 @@ class PopupMessage( PopupWindow ): text = self._job_key.GetVariable( 'popup_traceback' ) - if self._tb_text.GetLabel() != text: self._tb_text.SetLabel( self._ProcessText( HydrusData.ToString( text ) ) ) + if self._tb_text.GetLabel() != text: self._tb_text.SetLabel( self._ProcessText( HydrusData.ToUnicode( text ) ) ) self._show_tb_button.Show() @@ -4102,7 +4160,7 @@ class PopupMessage( PopupWindow ): text = self._job_key.GetVariable( 'popup_caller_traceback' ) - if self._caller_tb_text.GetLabel() != text: self._caller_tb_text.SetLabel( self._ProcessText( HydrusData.ToString( text ) ) ) + if self._caller_tb_text.GetLabel() != text: self._caller_tb_text.SetLabel( self._ProcessText( HydrusData.ToUnicode( text ) ) ) self._show_caller_tb_button.Show() @@ -4116,7 +4174,7 @@ class PopupMessage( PopupWindow ): text = self._job_key.GetVariable( 'popup_db_traceback' ) - if self._db_tb_text.GetLabel() != text: self._db_tb_text.SetLabel( self._ProcessText( HydrusData.ToString( text ) ) ) + if self._db_tb_text.GetLabel() != text: self._db_tb_text.SetLabel( self._ProcessText( HydrusData.ToUnicode( text ) ) ) self._show_db_tb_button.Show() @@ -5233,7 +5291,7 @@ class SeedCacheControl( SaneListCtrl ): ( seed, status, added_timestamp, last_modified_timestamp, note ) = info_tuple - pretty_seed = HydrusData.ToString( seed ) + pretty_seed = HydrusData.ToUnicode( seed ) pretty_status = CC.status_string_lookup[ status ] pretty_added = HydrusData.ConvertTimestampToPrettyAgo( added_timestamp ) pretty_modified = HydrusData.ConvertTimestampToPrettyAgo( last_modified_timestamp ) @@ -5580,7 +5638,9 @@ class ShowKeys( Frame ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( self._text ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( self._text ) diff --git a/include/ClientGUIDialogs.py b/include/ClientGUIDialogs.py index 0d530b60..8c9e1a01 100755 --- a/include/ClientGUIDialogs.py +++ b/include/ClientGUIDialogs.py @@ -5,6 +5,7 @@ import ClientDownloading import HydrusExceptions import HydrusFileHandling import HydrusNATPunch +import HydrusPaths import HydrusSerialisable import HydrusTagArchive import HydrusTags @@ -52,8 +53,14 @@ def ExportToHTA( parent, service_key, hashes ): with wx.FileDialog( parent, style = wx.FD_SAVE, defaultFile = 'archive.db' ) as dlg: - if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() - else: return + if dlg.ShowModal() == wx.ID_OK: + + path = HydrusData.ToUnicode( dlg.GetPath() ) + + else: + + return + message = 'Would you like to use hydrus\'s normal hash type, or an alternative?' @@ -238,7 +245,7 @@ class Dialog( wx.Dialog ): self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) ) - self.SetIcon( wx.Icon( HC.STATIC_DIR + os.path.sep + 'hydrus.ico', wx.BITMAP_TYPE_ICO ) ) + self.SetIcon( wx.Icon( os.path.join( HC.STATIC_DIR, 'hydrus.ico' ), wx.BITMAP_TYPE_ICO ) ) self.Bind( wx.EVT_BUTTON, self.EventDialogButton ) @@ -473,7 +480,7 @@ class DialogAdvancedContentUpdate( Dialog ): if dlg_file.ShowModal() == wx.ID_OK: - path = dlg_file.GetPath() + path = HydrusData.ToUnicode( dlg_file.GetPath() ) ImportFromHTA( self, path, self._service_key ) @@ -1129,7 +1136,7 @@ class DialogInputCustomFilterAction( Dialog ): value = self._ratings_numerical_slider.GetValue() - self._pretty_action = HydrusData.ToString( value ) + self._pretty_action = HydrusData.ToUnicode( value ) num_stars = self._current_ratings_numerical_service.GetInfo( 'num_stars' ) allow_zero = self._current_ratings_numerical_service.GetInfo( 'allow_zero' ) @@ -1554,6 +1561,8 @@ class DialogInputLocalFiles( Dialog ): def _AddPathsToList( self, paths ): + paths = [ HydrusData.ToUnicode( path ) for path in paths ] + self._processing_queue.append( paths ) self._ProcessQueue() @@ -1621,7 +1630,7 @@ class DialogInputLocalFiles( Dialog ): if dlg.ShowModal() == wx.ID_OK: - paths = dlg.GetPaths() + paths = [ HydrusData.ToUnicode( path ) for path in dlg.GetPaths() ] self._AddPathsToList( paths ) @@ -1634,7 +1643,7 @@ class DialogInputLocalFiles( Dialog ): if dlg.ShowModal() == wx.ID_OK: - path = dlg.GetPath() + path = HydrusData.ToUnicode( dlg.GetPath() ) self._AddPathsToList( ( path, ) ) @@ -1753,7 +1762,10 @@ 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 path.endswith( os.path.sep + 'Thumbs.db' ) or path.endswith( os.path.sep + 'thumbs.db' ): + + continue + if i % 500 == 0: gc.collect() @@ -1802,14 +1814,14 @@ class DialogInputLocalFiles( Dialog ): if num_good_files > 0: if num_good_files == 1: message = '1 file was parsed successfully' - else: message = HydrusData.ToString( num_good_files ) + ' files were parsed successfully' + else: message = str( num_good_files ) + ' files were parsed successfully' - if num_odd_files > 0: message += ', but ' + HydrusData.ToString( num_odd_files ) + ' failed.' + if num_odd_files > 0: message += ', but ' + str( num_odd_files ) + ' failed.' else: message += '.' else: - message = HydrusData.ToString( num_odd_files ) + ' files could not be parsed.' + message = str( num_odd_files ) + ' files could not be parsed.' wx.CallAfter( self.SetGaugeInfo, num_file_paths, num_file_paths, message ) @@ -2065,11 +2077,11 @@ class DialogInputMessageSystemPredicate( Dialog ): def GetString( self ): - if self._type == 'system:age': return 'system:age' + self._sign.GetStringSelection() + HydrusData.ToString( self._years.GetValue() ) + 'y' + HydrusData.ToString( self._months.GetValue() ) + 'm' + HydrusData.ToString( self._days.GetValue() ) + 'd' + if self._type == 'system:age': return 'system:age' + self._sign.GetStringSelection() + str( self._years.GetValue() ) + 'y' + str( self._months.GetValue() ) + 'm' + str( self._days.GetValue() ) + 'd' elif self._type == 'system:started_by': return 'system:started_by=' + self._contact.GetStringSelection() elif self._type == 'system:from': return 'system:from=' + self._contact.GetStringSelection() elif self._type == 'system:to': return 'system:to=' + self._contact.GetStringSelection() - elif self._type == 'system:numattachments': return 'system:numattachments' + self._sign.GetStringSelection() + HydrusData.ToString( self._num_attachments.GetValue() ) + elif self._type == 'system:numattachments': return 'system:numattachments' + self._sign.GetStringSelection() + str( self._num_attachments.GetValue() ) class DialogInputNamespaceRegex( Dialog ): @@ -2148,7 +2160,7 @@ class DialogInputNamespaceRegex( Dialog ): text = 'That regex would not compile!' text += os.linesep * 2 - text += HydrusData.ToString( e ) + text += HydrusData.ToUnicode( e ) wx.MessageBox( text ) @@ -2688,7 +2700,7 @@ class DialogModifyAccounts( Dialog ): response = self._service.Request( HC.GET, 'account_info', { 'subject_identifier' : subject_identifier } ) - subject_string = HydrusData.ToString( response[ 'account_info' ] ) + subject_string = HydrusData.ToUnicode( response[ 'account_info' ] ) else: subject_string = 'modifying ' + HydrusData.ConvertIntToPrettyString( len( self._subject_identifiers ) ) + ' accounts' @@ -2805,7 +2817,7 @@ class DialogModifyAccounts( Dialog ): account_info = response[ 'account_info' ] - self._subject_text.SetLabel( HydrusData.ToString( account_info ) ) + self._subject_text.SetLabel( HydrusData.ToUnicode( account_info ) ) if len( self._subject_identifiers ) > 1: wx.MessageBox( 'Done!' ) @@ -3578,7 +3590,7 @@ class DialogPathsToTags( Dialog ): if num_namespace != '': - tags.append( num_namespace + ':' + HydrusData.ToString( num ) ) + tags.append( num_namespace + ':' + str( num ) ) tags = HydrusTags.CleanTags( tags ) @@ -3685,7 +3697,7 @@ class DialogPathsToTags( Dialog ): text = 'That regex would not compile!' text += os.linesep * 2 - text += HydrusData.ToString( e ) + text += HydrusData.ToUnicode( e ) wx.MessageBox( text ) @@ -4333,7 +4345,7 @@ class DialogSetupExport( Dialog ): mime = media.GetMime() - pretty_tuple = ( HydrusData.ToString( i + 1 ), HC.mime_string_lookup[ mime ], '' ) + pretty_tuple = ( str( i + 1 ), HC.mime_string_lookup[ mime ], '' ) data_tuple = ( ( i, media ), mime, '' ) self._paths.Append( pretty_tuple, data_tuple ) @@ -4393,15 +4405,11 @@ class DialogSetupExport( Dialog ): def _GetPath( self, media, terms ): - directory = self._directory_picker.GetPath() + directory = HydrusData.ToUnicode( self._directory_picker.GetPath() ) filename = ClientFiles.GenerateExportFilename( media, terms ) - mime = media.GetMime() - - ext = HC.mime_ext_lookup[ mime ] - - return directory + os.path.sep + filename + ext + return os.path.join( directory, filename ) def _RecalcPaths( self ): @@ -4420,9 +4428,9 @@ class DialogSetupExport( Dialog ): i = 1 - while self._GetPath( media, terms + [ ( 'string', HydrusData.ToString( i ) ) ] ) in all_paths: i += 1 + while self._GetPath( media, terms + [ ( 'string', str( i ) ) ] ) in all_paths: i += 1 - path = self._GetPath( media, terms + [ ( 'string', HydrusData.ToString( i ) ) ] ) + path = self._GetPath( media, terms + [ ( 'string', str( i ) ) ] ) all_paths.add( path ) @@ -4431,7 +4439,7 @@ class DialogSetupExport( Dialog ): mime = media.GetMime() - self._paths.UpdateRow( index, ( HydrusData.ToString( ordering_index + 1 ), HC.mime_string_lookup[ mime ], path ), ( ( ordering_index, media ), mime, path ) ) + self._paths.UpdateRow( index, ( str( ordering_index + 1 ), HC.mime_string_lookup[ mime ], path ), ( ( ordering_index, media ), mime, path ) ) @@ -4469,7 +4477,7 @@ class DialogSetupExport( Dialog ): filename = ClientFiles.GenerateExportFilename( media, terms ) - txt_path = directory + os.path.sep + filename + '.txt' + txt_path = os.path.join( directory, filename + '.txt' ) with open( txt_path, 'wb' ) as f: @@ -4486,7 +4494,7 @@ class DialogSetupExport( Dialog ): except: - wx.MessageBox( 'Encountered a problem while attempting to export file with index ' + HydrusData.ToString( ordering_index + 1 ) + ':' + os.linesep * 2 + traceback.format_exc() ) + wx.MessageBox( 'Encountered a problem while attempting to export file with index ' + str( ordering_index + 1 ) + ':' + os.linesep * 2 + traceback.format_exc() ) break @@ -4501,7 +4509,7 @@ class DialogSetupExport( Dialog ): try: - HydrusFileHandling.LaunchDirectory( directory ) + HydrusPaths.LaunchDirectory( directory ) except: wx.MessageBox( 'Could not open that location!' ) @@ -4690,7 +4698,7 @@ class DialogShortcuts( Dialog ): if name == '': return - while self._shortcuts.NameExists( name ): name += HydrusData.ToString( random.randint( 0, 9 ) ) + while self._shortcuts.NameExists( name ): name += str( random.randint( 0, 9 ) ) shortcuts = ClientData.Shortcuts( name ) diff --git a/include/ClientGUIDialogsManage.py b/include/ClientGUIDialogsManage.py index 60cdd25b..cc69a417 100644 --- a/include/ClientGUIDialogsManage.py +++ b/include/ClientGUIDialogsManage.py @@ -18,9 +18,9 @@ import collections import HydrusConstants as HC import HydrusData import HydrusExceptions -import HydrusFileHandling import HydrusGlobals import HydrusNATPunch +import HydrusPaths import HydrusSerialisable import HydrusTags import itertools @@ -51,7 +51,7 @@ def GenerateMultipartFormDataCTAndBodyFromDict( fields ): m = multipart.Multipart() - for ( name, value ) in fields.items(): m.field( name, HydrusData.ToBytes( value ) ) + for ( name, value ) in fields.items(): m.field( name, HydrusData.ToByteString( value ) ) return m.get() @@ -488,7 +488,9 @@ class DialogManageBoorus( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( yaml.safe_dump( booru ) ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( yaml.safe_dump( booru ) ) @@ -976,7 +978,7 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): try: self._CheckCurrentContactIsValid() except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) return @@ -1029,7 +1031,7 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): try: self._CheckCurrentContactIsValid() except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) return @@ -1079,7 +1081,7 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): try: self._CheckCurrentContactIsValid() except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) event.Veto() @@ -1101,7 +1103,9 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( yaml.safe_dump( contact ) ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( yaml.safe_dump( contact ) ) @@ -1111,7 +1115,9 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( yaml.safe_dump( contact ) ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( yaml.safe_dump( contact ) ) @@ -1123,7 +1129,7 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): try: self._CheckCurrentContactIsValid() except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) return @@ -1162,7 +1168,7 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): try: self._CheckCurrentContactIsValid() except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) return @@ -1198,7 +1204,7 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): else: - while self._contacts.NameExists( name ) or self._contacts.NameExists( ' identities - ' + name ) or name == 'Anonymous': name = name + HydrusData.ToString( random.randint( 0, 9 ) ) + while self._contacts.NameExists( name ) or self._contacts.NameExists( ' identities - ' + name ) or name == 'Anonymous': name = name + str( random.randint( 0, 9 ) ) ( public_key, old_name, host, port ) = contact.GetInfo() @@ -1265,7 +1271,7 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): self._name.SetValue( name ) - contact_address = host + ':' + HydrusData.ToString( port ) + contact_address = host + ':' + str( port ) if contact_key is not None: contact_address = contact_key.encode( 'hex' ) + '@' + contact_address @@ -1375,7 +1381,7 @@ class DialogManageContacts( ClientGUIDialogs.Dialog ): self._name.SetValue( name ) - contact_address = host + ':' + HydrusData.ToString( port ) + contact_address = host + ':' + str( port ) if contact_key is not None: contact_address = contact_key.encode( 'hex' ) + '@' + contact_address @@ -1466,8 +1472,8 @@ class DialogManageExportFolders( ClientGUIDialogs.Dialog ): existing_path = export_folder.GetName() - test_path = path + os.path.sep - test_existing_path = existing_path + os.path.sep + test_path = os.path.join( path, '' ) + test_existing_path = os.path.join( existing_path, '' ) if test_path == test_existing_path: @@ -1532,7 +1538,7 @@ class DialogManageExportFolders( ClientGUIDialogs.Dialog ): pretty_file_search_context = ', '.join( predicate.GetUnicode( with_count = False ) for predicate in file_search_context.GetPredicates() ) - pretty_period = HydrusData.ToString( period / 60 ) + ' minutes' + pretty_period = str( period / 60 ) + ' minutes' pretty_phrase = phrase @@ -1547,7 +1553,7 @@ class DialogManageExportFolders( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - path = dlg.GetPath() + path = HydrusData.ToUnicode( dlg.GetPath() ) self._AddFolder( path ) @@ -1748,7 +1754,7 @@ If you select synchronise, be careful!''' def GetInfo( self ): - path = self._path.GetPath() + path = HydrusData.ToUnicode( self._path.GetPath() ) export_type = self._type.GetChoice() @@ -1886,7 +1892,9 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( yaml.safe_dump( dict ) ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( yaml.safe_dump( dict ) ) @@ -2062,7 +2070,7 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ): except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) self.EventAdd( event ) @@ -2082,7 +2090,9 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( yaml.safe_dump( imageboard ) ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( yaml.safe_dump( imageboard ) ) @@ -2217,7 +2227,7 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ): for ( name, field_type, default, editable ) in form_fields: - self._form_fields.Append( ( name, CC.field_string_lookup[ field_type ], HydrusData.ToString( default ), HydrusData.ToString( editable ) ), ( name, field_type, default, editable ) ) + self._form_fields.Append( ( name, CC.field_string_lookup[ field_type ], HydrusData.ToUnicode( default ), HydrusData.ToUnicode( editable ) ), ( name, field_type, default, editable ) ) # @@ -2356,7 +2366,7 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ): return - self._form_fields.Append( ( name, CC.field_string_lookup[ field_type ], HydrusData.ToString( default ), HydrusData.ToString( editable ) ), ( name, field_type, default, editable ) ) + self._form_fields.Append( ( name, CC.field_string_lookup[ field_type ], HydrusData.ToUnicode( default ), HydrusData.ToUnicode( editable ) ), ( name, field_type, default, editable ) ) @@ -2407,7 +2417,7 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ): if name in [ form_field[0] for form_field in self._form_fields.GetClientData() ]: raise Exception( 'You already have a form field called ' + name + '; delete or edit that one first' ) - self._form_fields.UpdateRow( index, ( name, CC.field_string_lookup[ field_type ], HydrusData.ToString( default ), HydrusData.ToString( editable ) ), ( name, field_type, default, editable ) ) + self._form_fields.UpdateRow( index, ( name, CC.field_string_lookup[ field_type ], HydrusData.ToUnicode( default ), HydrusData.ToUnicode( editable ) ), ( name, field_type, default, editable ) ) @@ -2457,7 +2467,7 @@ class DialogManageImageboards( ClientGUIDialogs.Dialog ): for ( name, field_type, default, editable ) in form_fields: - self._form_fields.Append( ( name, CC.field_string_lookup[ field_type ], HydrusData.ToString( default ), HydrusData.ToString( editable ) ), ( name, field_type, default, editable ) ) + self._form_fields.Append( ( name, CC.field_string_lookup[ field_type ], HydrusData.ToUnicode( default ), HydrusData.ToUnicode( editable ) ), ( name, field_type, default, editable ) ) if CC.RESTRICTION_MIN_RESOLUTION in restrictions: value = restrictions[ CC.RESTRICTION_MIN_RESOLUTION ] @@ -2588,7 +2598,7 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ): def _GetPrettyVariables( self, check_period ): - pretty_check_period = HydrusData.ToString( check_period / 60 ) + ' minutes' + pretty_check_period = str( check_period / 60 ) + ' minutes' return pretty_check_period @@ -2981,7 +2991,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ): def GetInfo( self ): name = self._name.GetValue() - path = self._path.GetPath() + path = HydrusData.ToUnicode( self._path.GetPath() ) mimes = self._mimes.GetInfo() import_file_options = self._import_file_options.GetOptions() import_tag_options = self._import_tag_options.GetOptions() @@ -2992,25 +3002,25 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ): actions[ CC.STATUS_SUCCESSFUL ] = self._action_successful.GetChoice() if actions[ CC.STATUS_SUCCESSFUL ] == CC.IMPORT_FOLDER_MOVE: - action_locations[ CC.STATUS_SUCCESSFUL ] = self._location_successful.GetPath() + action_locations[ CC.STATUS_SUCCESSFUL ] = HydrusData.ToUnicode( self._location_successful.GetPath() ) actions[ CC.STATUS_REDUNDANT ] = self._action_redundant.GetChoice() if actions[ CC.STATUS_REDUNDANT ] == CC.IMPORT_FOLDER_MOVE: - action_locations[ CC.STATUS_REDUNDANT ] = self._location_redundant.GetPath() + action_locations[ CC.STATUS_REDUNDANT ] = HydrusData.ToUnicode( self._location_redundant.GetPath() ) actions[ CC.STATUS_DELETED ] = self._action_deleted.GetChoice() if actions[ CC.STATUS_DELETED] == CC.IMPORT_FOLDER_MOVE: - action_locations[ CC.STATUS_DELETED ] = self._location_deleted.GetPath() + action_locations[ CC.STATUS_DELETED ] = HydrusData.ToUnicode( self._location_deleted.GetPath() ) actions[ CC.STATUS_FAILED ] = self._action_failed.GetChoice() if actions[ CC.STATUS_FAILED ] == CC.IMPORT_FOLDER_MOVE: - action_locations[ CC.STATUS_FAILED ] = self._location_failed.GetPath() + action_locations[ CC.STATUS_FAILED ] = HydrusData.ToUnicode( self._location_failed.GetPath() ) period = self._period.GetValue() * 60 @@ -3450,8 +3460,8 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ): self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) ) - self._idle_panel = ClientGUICommon.StaticBox( self, 'idle' ) - self._maintenance_panel = ClientGUICommon.StaticBox( self, 'maintenance' ) + self._idle_panel = ClientGUICommon.StaticBox( self, 'when to run big jobs' ) + self._maintenance_panel = ClientGUICommon.StaticBox( self, 'maintenance period' ) self._processing_panel = ClientGUICommon.StaticBox( self, 'processing' ) self._idle_period = wx.SpinCtrl( self._idle_panel, min = 0, max = 1000 ) @@ -3490,10 +3500,10 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ): gridbox.AddGrowableCol( 1, 1 ) - gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Minutes of general client inactivity until client is considered idle (0 for never): ' ), CC.FLAGS_MIXED ) + gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Minutes of general client inactivity until client can be considered idle: ' ), CC.FLAGS_MIXED ) gridbox.AddF( self._idle_period, CC.FLAGS_MIXED ) - gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Minutes of unmoving mouse until client is considered idle (0 for never): ' ), CC.FLAGS_MIXED ) + gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Minutes of unmoving mouse until client can be considered idle: ' ), CC.FLAGS_MIXED ) gridbox.AddF( self._idle_mouse_period, CC.FLAGS_MIXED ) gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Do not start a job if any CPU core has more than this percent usage: ' ), CC.FLAGS_MIXED ) @@ -3506,6 +3516,8 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ): gridbox.AddF( self._idle_shutdown_max_minutes, CC.FLAGS_MIXED ) text = 'CPU-heavy jobs like maintenance routines and repository synchronisation processing will only start by themselves when you are not using the client.' + text += os.linesep * 2 + text += 'If you set both client inactivy and unmoving mouse to 0, the client will never consider itself idle and you should set up shutdown processing.' st = wx.StaticText( self._idle_panel, label = text ) @@ -3838,7 +3850,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ): def UpdateOptions( self ): - HC.options[ 'export_path' ] = HydrusFileHandling.ConvertAbsPathToPortablePath( self._export_location.GetPath() ) + HC.options[ 'export_path' ] = HydrusPaths.ConvertAbsPathToPortablePath( HydrusData.ToUnicode( self._export_location.GetPath() ) ) HC.options[ 'delete_to_recycle_bin' ] = self._delete_to_recycle_bin.GetValue() HC.options[ 'exclude_deleted_files' ] = self._exclude_deleted_files.GetValue() @@ -3881,6 +3893,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ): self._tag_dialog_size = wx.CheckBox( self ) self._tag_dialog_position = wx.CheckBox( self ) self._rating_dialog_position = wx.CheckBox( self ) + self._hide_preview = wx.CheckBox( self ) # @@ -3932,6 +3945,8 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ): self._rating_dialog_position.SetValue( remember ) + self._hide_preview.SetValue( HC.options[ 'hide_preview' ] ) + # gridbox = wx.FlexGridSizer( 0, 2 ) @@ -3974,6 +3989,9 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ): gridbox.AddF( wx.StaticText( self, label = 'Remember manage ratings dialog position: ' ), CC.FLAGS_MIXED ) gridbox.AddF( self._rating_dialog_position, CC.FLAGS_MIXED ) + gridbox.AddF( wx.StaticText( self, label = 'Hide the preview window: ' ), CC.FLAGS_MIXED ) + gridbox.AddF( self._hide_preview, CC.FLAGS_MIXED ) + self.SetSizer( gridbox ) @@ -4028,6 +4046,8 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ): HC.options[ 'rating_dialog_position' ] = ( remember, None ) + HC.options[ 'hide_preview' ] = self._hide_preview.GetValue() + class _MediaPanel( wx.Panel ): @@ -5170,7 +5190,7 @@ class DialogManageServer( ClientGUIDialogs.Dialog ): for ( service_key, service_type, options ) in self._services_info: - name = HC.service_string_lookup[ service_type ] + '@' + HydrusData.ToString( options[ 'port' ] ) + name = HC.service_string_lookup[ service_type ] + '@' + str( options[ 'port' ] ) page = self._Panel( self._services_listbook, service_key, service_type, options ) @@ -5233,7 +5253,7 @@ class DialogManageServer( ClientGUIDialogs.Dialog ): name = self._services_listbook.GetCurrentName() - new_name = HC.service_string_lookup[ service_type ] + '@' + HydrusData.ToString( options[ 'port' ] ) + new_name = HC.service_string_lookup[ service_type ] + '@' + str( options[ 'port' ] ) if name != new_name: self._services_listbook.RenamePage( name, new_name ) @@ -5263,7 +5283,7 @@ class DialogManageServer( ClientGUIDialogs.Dialog ): page = self._Panel( self._services_listbook, service_key, service_type, options ) - name = HC.service_string_lookup[ service_type ] + '@' + HydrusData.ToString( port ) + name = HC.service_string_lookup[ service_type ] + '@' + str( port ) self._services_listbook.AddPage( name, page, select = True ) @@ -5273,7 +5293,7 @@ class DialogManageServer( ClientGUIDialogs.Dialog ): try: self._CheckCurrentServiceIsValid() except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) return @@ -5333,7 +5353,7 @@ class DialogManageServer( ClientGUIDialogs.Dialog ): try: self._CheckCurrentServiceIsValid() except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) event.Veto() @@ -5749,7 +5769,9 @@ class DialogManageServices( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( yaml.safe_dump( ( service_key, service_type, name, info ) ) ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( yaml.safe_dump( ( service_key, service_type, name, info ) ) ) @@ -5759,7 +5781,9 @@ class DialogManageServices( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( yaml.safe_dump( ( service_key, service_type, name, info ) ) ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( yaml.safe_dump( ( service_key, service_type, name, info ) ) ) @@ -5886,7 +5910,7 @@ class DialogManageServices( ClientGUIDialogs.Dialog ): try: self._CheckCurrentServiceIsValid() except Exception as e: - wx.MessageBox( HydrusData.ToString( e ) ) + wx.MessageBox( HydrusData.ToUnicode( e ) ) return @@ -6662,7 +6686,9 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( dump ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( dump ) @@ -6672,7 +6698,9 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ): if dlg.ShowModal() == wx.ID_OK: - with open( dlg.GetPath(), 'wb' ) as f: f.write( dump ) + path = HydrusData.ToUnicode( dlg.GetPath() ) + + with open( path, 'wb' ) as f: f.write( dump ) @@ -6860,7 +6888,7 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ): seed_cache = self._original_subscription.GetSeedCache() - seed_cache_text = HydrusData.ToString( seed_cache.GetSeedCount() ) + ' urls in cache' + seed_cache_text = str( seed_cache.GetSeedCount() ) + ' urls in cache' self._info_panel.AddF( wx.StaticText( self._info_panel, label = seed_cache_text ), CC.FLAGS_EXPAND_PERPENDICULAR ) self._info_panel.AddF( self._seed_cache_button, CC.FLAGS_LONE_BUTTON ) diff --git a/include/ClientGUIManagement.py b/include/ClientGUIManagement.py index 7a7156d1..21317460 100755 --- a/include/ClientGUIManagement.py +++ b/include/ClientGUIManagement.py @@ -2,8 +2,7 @@ import HydrusConstants as HC import HydrusAudioHandling import ClientDownloading import HydrusExceptions -import HydrusFileHandling -import HydrusImageHandling +import HydrusPaths import HydrusSerialisable import HydrusThreading import ClientConstants as CC @@ -152,7 +151,7 @@ def GenerateDumpMultipartFormDataCTAndBody( fields ): for ( name, field_type, value ) in fields: - if field_type in ( CC.FIELD_TEXT, CC.FIELD_COMMENT, CC.FIELD_PASSWORD, CC.FIELD_VERIFICATION_RECAPTCHA, CC.FIELD_THREAD_ID ): m.field( name, HydrusData.ToBytes( value ) ) + if field_type in ( CC.FIELD_TEXT, CC.FIELD_COMMENT, CC.FIELD_PASSWORD, CC.FIELD_VERIFICATION_RECAPTCHA, CC.FIELD_THREAD_ID ): m.field( name, HydrusData.ToByteString( value ) ) elif field_type == CC.FIELD_CHECKBOX: if value: @@ -185,7 +184,7 @@ class CaptchaControl( wx.Panel ): self._captcha_challenge = None self._captcha_runs_out = 0 - self._bitmap = wx.EmptyBitmap( 0, 0, 24 ) + self._bitmap = wx.EmptyBitmap( 20, 20, 24 ) self._timer = wx.Timer( self, ID_TIMER_CAPTCHA ) self.Bind( wx.EVT_TIMER, self.TIMEREvent, id = ID_TIMER_CAPTCHA ) @@ -326,7 +325,7 @@ class CaptchaControl( wx.Panel ): self._captcha_challenge = None self._captcha_runs_out = 0 - self._bitmap = wx.EmptyBitmap( 0, 0, 24 ) + self._bitmap = wx.EmptyBitmap( 20, 20, 24 ) self._DrawMain() self._DrawEntry() @@ -339,7 +338,7 @@ class CaptchaControl( wx.Panel ): self._captcha_challenge = '' self._captcha_runs_out = 0 - self._bitmap = wx.EmptyBitmap( 0, 0, 24 ) + self._bitmap = wx.EmptyBitmap( 20, 20, 24 ) self._DrawMain() self._DrawEntry() @@ -383,7 +382,7 @@ class CaptchaControl( wx.Panel ): jpeg = HydrusGlobals.client_controller.DoHTTP( HC.GET, 'http://www.google.com/recaptcha/api/image?c=' + self._captcha_challenge ) - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -393,7 +392,7 @@ class CaptchaControl( wx.Panel ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) self._captcha_runs_out = HydrusData.GetNow() + 5 * 60 - 15 @@ -830,7 +829,7 @@ class ManagementPanelDumper( ManagementPanel ): except Exception as e: - ( status, phrase ) = ( 'big error', HydrusData.ToString( e ) ) + ( status, phrase ) = ( 'big error', HydrusData.ToUnicode( e ) ) wx.CallAfter( self.CALLBACKDoneDump, hash, post_field_info, status, phrase ) @@ -865,7 +864,7 @@ class ManagementPanelDumper( ManagementPanel ): total_size = sum( [ m.GetSize() for m in self._hashes_to_media.values() ] ) - initial = 'Hydrus Network Client is starting a dump of ' + HydrusData.ToString( num_files ) + ' files, totalling ' + HydrusData.ConvertIntToBytes( total_size ) + ':' + os.linesep * 2 + initial = 'Hydrus Network Client is starting a dump of ' + str( num_files ) + ' files, totalling ' + HydrusData.ConvertIntToBytes( total_size ) + ':' + os.linesep * 2 else: initial = '' @@ -1096,7 +1095,7 @@ class ManagementPanelDumper( ManagementPanel ): if self._next_dump_index == len( self._sorted_media_hashes ): - self._progress_info.SetLabel( 'done - ' + HydrusData.ToString( self._num_dumped ) + ' dumped' ) + self._progress_info.SetLabel( 'done - ' + str( self._num_dumped ) + ' dumped' ) self._start_button.Disable() @@ -1365,17 +1364,17 @@ class ManagementPanelDumper( ManagementPanel ): except Exception as e: - ( status, phrase ) = ( 'big error', HydrusData.ToString( e ) ) + ( status, phrase ) = ( 'big error', HydrusData.ToUnicode( e ) ) wx.CallAfter( self.CALLBACKDoneDump, hash, post_field_info, status, phrase ) - else: self._progress_info.SetLabel( 'dumping next file in ' + HydrusData.ToString( time_left ) + ' seconds' ) + else: self._progress_info.SetLabel( 'dumping next file in ' + str( time_left ) + ' seconds' ) else: if self._num_dumped == 0: self._progress_info.SetLabel( 'will dump to ' + self._imageboard.GetName() ) - else: self._progress_info.SetLabel( 'paused after ' + HydrusData.ToString( self._num_dumped ) + ' files dumped' ) + else: self._progress_info.SetLabel( 'paused after ' + str( self._num_dumped ) + ' files dumped' ) diff --git a/include/ClientGUIMedia.py b/include/ClientGUIMedia.py index 698d42f1..dd97167c 100755 --- a/include/ClientGUIMedia.py +++ b/include/ClientGUIMedia.py @@ -10,6 +10,7 @@ import ClientGUICanvas import ClientMedia import collections import HydrusExceptions +import HydrusPaths import HydrusTagArchive import HydrusTags import HydrusThreading @@ -23,7 +24,6 @@ import traceback import wx import yaml import HydrusData -import HydrusFileHandling import HydrusGlobals # Option Enums @@ -330,7 +330,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ): path = ClientFiles.GetFilePath( hash, mime ) - HydrusFileHandling.LaunchFile( path ) + HydrusPaths.LaunchFile( path ) return @@ -589,7 +589,9 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ): path = ClientFiles.GetFilePath( hash, mime ) - HydrusFileHandling.LaunchFile( path ) + self._SetFocussedMedia( None ) + + HydrusPaths.LaunchFile( path ) @@ -998,7 +1000,7 @@ class MediaPanelThumbnails( MediaPanel ): self._num_columns = 1 self._drag_init_coordinates = None - self._client_bmp = wx.EmptyBitmap( 0, 0 ) + self._client_bmp = wx.EmptyBitmap( 20, 20, 24 ) self._clean_canvas_pages = {} self._dirty_canvas_pages = [] self._num_rows_per_canvas_page = 1 @@ -1060,15 +1062,40 @@ class MediaPanelThumbnails( MediaPanel ): return page_indices + def _CreateNewDirtyPage( self ): + + ( client_width, client_height ) = self.GetClientSize() + + ( thumbnail_span_width, thumbnail_span_height ) = self._thumbnail_span_dimensions + + self._dirty_canvas_pages.append( wx.EmptyBitmap( client_width, self._num_rows_per_canvas_page * thumbnail_span_width, 24 ) ) + + def _DirtyAllPages( self ): - for ( index, bmp ) in self._clean_canvas_pages.items(): self._dirty_canvas_pages.append( bmp ) + clean_indices = self._clean_canvas_pages.keys() - self._clean_canvas_pages = {} + for clean_index in clean_indices: + + self._DirtyPage( clean_index ) + self.Refresh() + def _DirtyPage( self, clean_index ): + + bmp = self._clean_canvas_pages[ clean_index ] + + del self._clean_canvas_pages[ clean_index ] + + thumbnails = [ thumbnail for ( thumbnail_index, thumbnail ) in self._GetThumbnailsFromPageIndex( clean_index ) ] + + HydrusGlobals.client_controller.GetCache( 'thumbnail' ).CancelWaterfall( self._page_key, thumbnails ) + + self._dirty_canvas_pages.append( bmp ) + + def _DrawCanvasPage( self, page_index, bmp ): ( bmp_width, bmp_height ) = bmp.GetSize() @@ -1083,43 +1110,37 @@ class MediaPanelThumbnails( MediaPanel ): # - num_thumbnails_per_page = self._num_columns * self._num_rows_per_canvas_page + page_thumbnails = self._GetThumbnailsFromPageIndex( page_index ) - start_index = num_thumbnails_per_page * page_index + ( thumbnail_span_width, thumbnail_span_height ) = self._thumbnail_span_dimensions - if start_index <= len( self._sorted_media ): + thumbnails_to_render_later = [] + + for ( thumbnail_index, thumbnail ) in page_thumbnails: - end_index = min( len( self._sorted_media ), start_index + num_thumbnails_per_page ) + hash = thumbnail.GetDisplayMedia().GetHash() - ( thumbnail_span_width, thumbnail_span_height ) = self._thumbnail_span_dimensions + self._StopFading( hash ) - thumbnails_to_render_later = [] - - for thumbnail_index in range( start_index, end_index ): + if thumbnail.IsLoaded(): - thumbnail = self._sorted_media[ thumbnail_index ] + thumbnail_col = thumbnail_index % self._num_columns - hash = thumbnail.GetDisplayMedia().GetHash() + thumbnail_row = thumbnail_index / self._num_columns - self._StopFading( hash ) + x = thumbnail_col * thumbnail_span_width + CC.THUMBNAIL_MARGIN - if thumbnail.IsLoaded(): - - thumbnail_col = thumbnail_index % self._num_columns - - thumbnail_row = thumbnail_index / self._num_columns - - x = thumbnail_col * thumbnail_span_width + CC.THUMBNAIL_MARGIN - - y = ( thumbnail_row - ( page_index * self._num_rows_per_canvas_page ) ) * thumbnail_span_height + CC.THUMBNAIL_MARGIN - - dc.DrawBitmap( thumbnail.GetBmp(), x, y ) - - else: thumbnails_to_render_later.append( thumbnail ) + y = ( thumbnail_row - ( page_index * self._num_rows_per_canvas_page ) ) * thumbnail_span_height + CC.THUMBNAIL_MARGIN + + dc.DrawBitmap( thumbnail.GetBmp(), x, y ) + + else: + + thumbnails_to_render_later.append( thumbnail ) - HydrusGlobals.client_controller.GetCache( 'thumbnail' ).Waterfall( self._page_key, thumbnails_to_render_later ) - + + HydrusGlobals.client_controller.GetCache( 'thumbnail' ).Waterfall( self._page_key, thumbnails_to_render_later ) def _DrawThumbnail( self, thumbnail_index ): @@ -1272,6 +1293,26 @@ class MediaPanelThumbnails( MediaPanel ): return self._sorted_media[ thumbnail_index ] + def _GetThumbnailsFromPageIndex( self, page_index ): + + num_thumbnails_per_page = self._num_columns * self._num_rows_per_canvas_page + + start_index = num_thumbnails_per_page * page_index + + if start_index <= len( self._sorted_media ): + + end_index = min( len( self._sorted_media ), start_index + num_thumbnails_per_page ) + + thumbnails = [ ( index, self._sorted_media[ index ] ) for index in range( start_index, end_index ) ] + + else: + + thumbnails = [] + + + return thumbnails + + def _GetYStart( self ): ( my_virtual_width, my_virtual_height ) = self.GetVirtualSize() @@ -1375,15 +1416,20 @@ class MediaPanelThumbnails( MediaPanel ): self._client_bmp = wx.EmptyBitmap( client_width, client_height, 24 ) - for ( index, bmp ) in self._clean_canvas_pages.items(): wx.CallAfter( bmp.Destroy ) + clean_indices = self._clean_canvas_pages.keys() - for bmp in self._dirty_canvas_pages: wx.CallAfter( bmp.Destroy ) + for clean_index in clean_indices: + + self._DirtyPage( clean_index ) + + + for bmp in self._dirty_canvas_pages: + + wx.CallAfter( bmp.Destroy ) + - self._clean_canvas_pages = {} self._dirty_canvas_pages = [] - for i in range( 5 ): self._dirty_canvas_pages.append( wx.EmptyBitmap( client_width, self._num_rows_per_canvas_page * thumbnail_span_width, 24 ) ) - def _Remove( self ): @@ -1693,16 +1739,22 @@ class MediaPanelThumbnails( MediaPanel ): if page_index not in self._clean_canvas_pages: - if len( self._dirty_canvas_pages ) > 0: bmp = self._dirty_canvas_pages.pop( 0 ) - else: + if len( self._dirty_canvas_pages ) == 0: - index_to_steal = potential_clean_indices_to_steal.pop() - - bmp = self._clean_canvas_pages[ index_to_steal ] - - del self._clean_canvas_pages[ index_to_steal ] + if len( potential_clean_indices_to_steal ) > 0: + + index_to_steal = potential_clean_indices_to_steal.pop() + + self._DirtyPage( index_to_steal ) + + else: + + self._CreateNewDirtyPage() + + bmp = self._dirty_canvas_pages.pop( 0 ) + self._DrawCanvasPage( page_index, bmp ) self._clean_canvas_pages[ page_index ] = bmp @@ -2496,13 +2548,13 @@ class Thumbnail( Selectable ): ( volume, ) = volumes - collections_string = 'v' + HydrusData.ToString( volume ) + collections_string = 'v' + str( volume ) else: volumes_sorted = HydrusTags.SortTags( volumes ) - collections_string_append = 'v' + HydrusData.ToString( volumes_sorted[0] ) + '-' + HydrusData.ToString( volumes_sorted[-1] ) + collections_string_append = 'v' + str( volumes_sorted[0] ) + '-' + str( volumes_sorted[-1] ) @@ -2512,13 +2564,13 @@ class Thumbnail( Selectable ): ( chapter, ) = chapters - collections_string_append = 'c' + HydrusData.ToString( chapter ) + collections_string_append = 'c' + str( chapter ) else: chapters_sorted = HydrusTags.SortTags( chapters ) - collections_string_append = 'c' + HydrusData.ToString( chapters_sorted[0] ) + '-' + HydrusData.ToString( chapters_sorted[-1] ) + collections_string_append = 'c' + str( chapters_sorted[0] ) + '-' + str( chapters_sorted[-1] ) if len( collections_string ) > 0: collections_string += '-' + collections_string_append @@ -2531,13 +2583,13 @@ class Thumbnail( Selectable ): ( page, ) = pages - collections_string_append = 'p' + HydrusData.ToString( page ) + collections_string_append = 'p' + str( page ) else: pages_sorted = HydrusTags.SortTags( pages ) - collections_string_append = 'p' + HydrusData.ToString( pages_sorted[0] ) + '-' + HydrusData.ToString( pages_sorted[-1] ) + collections_string_append = 'p' + str( pages_sorted[0] ) + '-' + str( pages_sorted[-1] ) if len( collections_string ) > 0: collections_string += '-' + collections_string_append @@ -2666,7 +2718,7 @@ class Thumbnail( Selectable ): dc.DrawBitmap( CC.GlobalBMPs.collection, 1, height - 17 ) - num_files_str = HydrusData.ToString( len( self._hashes ) ) + num_files_str = str( len( self._hashes ) ) dc.SetFont( wx.SystemSettings.GetFont( wx.SYS_DEFAULT_GUI_FONT ) ) diff --git a/include/ClientGUIMessages.py b/include/ClientGUIMessages.py index 1eab82a6..7a98fda9 100755 --- a/include/ClientGUIMessages.py +++ b/include/ClientGUIMessages.py @@ -96,7 +96,7 @@ class ConversationsListCtrl( wx.ListCtrl, ListCtrlAutoWidthMixin, ColumnSorterMi def _GetPrettyStatus( self ): if len( self._conversations ) == 1: return '1 conversation' - else: return HydrusData.ToString( len( self._conversations ) ) + ' conversations' + else: return str( len( self._conversations ) ) + ' conversations' def _SetConversations( self, conversations ): @@ -129,7 +129,7 @@ class ConversationsListCtrl( wx.ListCtrl, ListCtrlAutoWidthMixin, ColumnSorterMi updated_string = HydrusData.ConvertTimestampToHumanPrettyTime( updated ) - self.Append( ( '', subject, name_from, ', '.join( [ contact.GetName() for contact in participants if contact.GetName() != name_from ] ), HydrusData.ToString( message_count ), HydrusData.ToString( unread_count ), created_string, updated_string ) ) + self.Append( ( '', subject, name_from, ', '.join( [ contact.GetName() for contact in participants if contact.GetName() != name_from ] ), str( message_count ), str( unread_count ), created_string, updated_string ) ) data_index = i @@ -168,8 +168,8 @@ class ConversationsListCtrl( wx.ListCtrl, ListCtrlAutoWidthMixin, ColumnSorterMi if inbox: self.SetItemImage( selection, 1 ) else: self.SetItemImage( selection, 0 ) - self.SetStringItem( selection, 4, HydrusData.ToString( message_count ) ) - self.SetStringItem( selection, 5, HydrusData.ToString( unread_count ) ) + self.SetStringItem( selection, 4, str( message_count ) ) + self.SetStringItem( selection, 5, str( unread_count ) ) if created is None: diff --git a/include/ClientGUIPages.py b/include/ClientGUIPages.py index e13e3bbb..d04c56db 100755 --- a/include/ClientGUIPages.py +++ b/include/ClientGUIPages.py @@ -52,17 +52,33 @@ class Page( wx.SplitterWindow ): self._media_panel = ClientGUIMedia.MediaPanelThumbnails( self, self._page_key, file_service_key, initial_media_results ) self.SplitVertically( self._search_preview_split, self._media_panel, HC.options[ 'hpos' ] ) + wx.CallAfter( self._search_preview_split.SplitHorizontally, self._management_panel, self._preview_panel, HC.options[ 'vpos' ] ) + if HC.options[ 'hide_preview' ]: + + wx.CallAfter( self._search_preview_split.Unsplit, self._preview_panel ) + + HydrusGlobals.client_controller.sub( self, 'SetPrettyStatus', 'new_page_status' ) HydrusGlobals.client_controller.sub( self, 'SwapMediaPanel', 'swap_media_panel' ) def CleanBeforeDestroy( self ): self._management_panel.CleanBeforeDestroy() - def EventPreviewUnsplit( self, event ): self._search_preview_split.Unsplit( self._preview_panel ) + def EventPreviewUnsplit( self, event ): + + self._search_preview_split.Unsplit( self._preview_panel ) + + HydrusGlobals.client_controller.pub( 'set_focus', self._page_key, None ) + - def EventUnsplit( self, event ): self.Unsplit( self._search_preview_split ) + def EventUnsplit( self, event ): + + self.Unsplit( self._search_preview_split ) + + HydrusGlobals.client_controller.pub( 'set_focus', self._page_key, None ) + def GetManagementController( self ): @@ -87,10 +103,24 @@ class Page( wx.SplitterWindow ): def GetSashPositions( self ): - if self.IsSplit(): x = self.GetSashPosition() + if self.IsSplit(): + + x = self.GetSashPosition() + else: x = HC.options[ 'hpos' ] - if self._search_preview_split.IsSplit(): y = -1 * self._preview_panel.GetSize()[1] + if self._search_preview_split.IsSplit(): + + # I used to do: + # y = -1 * self._preview_panel.GetSize()[1] + # but that crept 4 pixels smaller every time, I assume due to sash caret height + + ( sps_x, sps_y ) = self._search_preview_split.GetClientSize() + + sash_y = self._search_preview_split.GetSashPosition() + + y = -1 * ( sps_y - sash_y ) + else: y = HC.options[ 'vpos' ] return ( x, y ) @@ -113,6 +143,8 @@ class Page( wx.SplitterWindow ): self.Unsplit( self._search_preview_split ) + HydrusGlobals.client_controller.pub( 'set_focus', self._page_key, None ) + else: self.SplitVertically( self._search_preview_split, self._media_panel, HC.options[ 'hpos' ] ) diff --git a/include/ClientImporting.py b/include/ClientImporting.py index 87252e72..32f2fb44 100644 --- a/include/ClientImporting.py +++ b/include/ClientImporting.py @@ -10,6 +10,7 @@ import HydrusData import HydrusExceptions import HydrusFileHandling import HydrusGlobals +import HydrusPaths import HydrusSerialisable import json import os @@ -190,7 +191,7 @@ class GalleryImport( HydrusSerialisable.SerialisableBase ): elif status == CC.STATUS_NEW: - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -211,7 +212,7 @@ class GalleryImport( HydrusSerialisable.SerialisableBase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) @@ -374,6 +375,11 @@ class GalleryImport( HydrusSerialisable.SerialisableBase ): time.sleep( 5 ) + with self._lock: + + self._SetGalleryStatus( page_key, 'waiting politely' ) + + time.sleep( HC.options[ 'website_download_polite_wait' ] ) with self._lock: @@ -894,7 +900,7 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ): filename = os.path.basename( path ) - dest_path = dest_dir + os.path.sep + filename + dest_path = os.path.join( dest_dir, filename ) while os.path.exists( dest_path ): @@ -986,9 +992,9 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ): if os.path.exists( self._path ) and os.path.isdir( self._path ): - filenames = os.listdir( self._path ) + filenames = os.listdir( HydrusData.ToUnicode( self._path ) ) - raw_paths = [ self._path + os.path.sep + filename for filename in filenames ] + raw_paths = [ os.path.join( self._path, filename ) for filename in filenames ] all_paths = ClientFiles.GetAllPaths( raw_paths ) @@ -1200,7 +1206,7 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ): if status == CC.STATUS_NEW: - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -1222,7 +1228,7 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) @@ -1260,8 +1266,6 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ): def _WorkOnQueue( self, page_key ): - do_wait = False - file_url = self._urls_cache.GetNextSeed( CC.STATUS_UNKNOWN ) if file_url is not None: @@ -1271,6 +1275,8 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ): if len( self._pending_page_urls ) > 0: + do_wait = False + with self._lock: page_url = self._pending_page_urls.pop( 0 ) @@ -1347,7 +1353,17 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ): error_occurred = True - parser_status = HydrusData.ToString( e ) + parser_status = HydrusData.ToUnicode( e ) + + + if not error_occurred and do_wait: + + with self._lock: + + self._SetParserStatus( page_key, 'waiting politely' ) + + + time.sleep( HC.options[ 'website_download_polite_wait' ] ) with self._lock: @@ -1358,8 +1374,6 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ): if error_occurred: - HydrusGlobals.client_controller.pub( 'update_status', page_key ) - time.sleep( 5 ) @@ -1373,11 +1387,6 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ): HydrusGlobals.client_controller.pub( 'update_status', page_key ) - if do_wait: - - time.sleep( HC.options[ 'website_download_polite_wait' ] ) - - def _THREADWork( self, page_key ): @@ -1762,10 +1771,10 @@ class SeedCache( HydrusSerialisable.SerialisableBase ): status_strings = [] - if num_successful > 0: status_strings.append( HydrusData.ToString( num_successful ) + ' successful' ) - if num_failed > 0: status_strings.append( HydrusData.ToString( num_failed ) + ' failed' ) - if num_deleted > 0: status_strings.append( HydrusData.ToString( num_deleted ) + ' already deleted' ) - if num_redundant > 0: status_strings.append( HydrusData.ToString( num_redundant ) + ' already in db' ) + if num_successful > 0: status_strings.append( str( num_successful ) + ' successful' ) + if num_failed > 0: status_strings.append( str( num_failed ) + ' failed' ) + if num_deleted > 0: status_strings.append( str( num_deleted ) + ' already deleted' ) + if num_redundant > 0: status_strings.append( str( num_redundant ) + ' already in db' ) status = ', '.join( status_strings ) @@ -1967,10 +1976,12 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ): tags = gallery.GetTags( url, report_hooks = [ hook ] ) + do_wait = True + elif status == CC.STATUS_NEW: - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -1995,7 +2006,7 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) @@ -2388,7 +2399,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): if status == CC.STATUS_NEW: - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -2410,7 +2421,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) @@ -2459,6 +2470,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): def _WorkOnThread( self, page_key ): do_wait = False + error_occurred = False with self._lock: @@ -2475,8 +2487,6 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): HydrusGlobals.client_controller.pub( 'update_status', page_key ) - error_occurred = False - try: ( json_url, file_base ) = ClientDownloading.GetImageboardThreadURLs( self._thread_url ) @@ -2498,7 +2508,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): continue - file_url = file_base + HydrusData.ToString( post[ 'tim' ] ) + post[ 'ext' ] + file_url = file_base + str( post[ 'tim' ] ) + post[ 'ext' ] file_md5_base64 = post[ 'md5' ] file_original_filename = post[ 'filename' ] + post[ 'ext' ] @@ -2513,7 +2523,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): continue - file_url = file_base + HydrusData.ToString( extra_file[ 'tim' ] ) + extra_file[ 'ext' ] + file_url = file_base + str( extra_file[ 'tim' ] ) + extra_file[ 'ext' ] file_md5_base64 = extra_file[ 'md5' ] file_original_filename = extra_file[ 'filename' ] + extra_file[ 'ext' ] @@ -2559,7 +2569,7 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): error_occurred = True - watcher_status = HydrusData.ToString( e ) + watcher_status = HydrusData.ToUnicode( e ) with self._lock: @@ -2576,15 +2586,6 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): self._last_time_checked = HydrusData.GetNow() - self._SetWatcherStatus( page_key, watcher_status ) - self._RegenerateSeedCacheStatus( page_key ) - - - if error_occurred: - - HydrusGlobals.client_controller.pub( 'update_status', page_key ) - - time.sleep( 5 ) else: @@ -2602,22 +2603,36 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ): delay = self._check_period - self._SetWatcherStatus( page_key, 'checking again in ' + HydrusData.ConvertTimestampToPrettyPending( self._last_time_checked + delay ) + ' seconds' ) + watcher_status = 'checking again in ' + HydrusData.ConvertTimestampToPrettyPending( self._last_time_checked + delay ) + ' seconds' else: - self._SetWatcherStatus( page_key, 'checking finished' ) + watcher_status = 'checking finished' - HydrusGlobals.client_controller.pub( 'update_status', page_key ) - - if do_wait: + if not error_occurred and do_wait: + + with self._lock: + + self._SetWatcherStatus( page_key, 'waiting politely' ) + time.sleep( HC.options[ 'website_download_polite_wait' ] ) + with self._lock: + + self._SetWatcherStatus( page_key, watcher_status ) + self._RegenerateSeedCacheStatus( page_key ) + + + if error_occurred: + + time.sleep( 5 ) + + def _THREADWork( self, page_key ): diff --git a/include/ClientLocalServerResources.py b/include/ClientLocalServerResources.py index 85f286de..bccaae57 100644 --- a/include/ClientLocalServerResources.py +++ b/include/ClientLocalServerResources.py @@ -242,11 +242,11 @@ class HydrusResourceCommandBooruThumbnail( HydrusResourceCommandBooru ): mime = media_result.GetMime() if mime in HC.MIMES_WITH_THUMBNAILS: path = ClientFiles.GetThumbnailPath( hash, full_size = False ) - elif mime in HC.AUDIO: path = HC.STATIC_DIR + os.path.sep + 'audio_resized.png' - elif mime in HC.VIDEO: path = HC.STATIC_DIR + os.path.sep + 'video_resized.png' - elif mime == HC.APPLICATION_FLASH: path = HC.STATIC_DIR + os.path.sep + 'flash_resized.png' - elif mime == HC.APPLICATION_PDF: path = HC.STATIC_DIR + os.path.sep + 'pdf_resized.png' - else: path = HC.STATIC_DIR + os.path.sep + 'hydrus_resized.png' + elif mime in HC.AUDIO: path = os.path.join( HC.STATIC_DIR, 'audio_resized.png' ) + elif mime in HC.VIDEO: path = os.path.join( HC.STATIC_DIR, 'video_resized.png' ) + elif mime == HC.APPLICATION_FLASH: path = os.path.join( HC.STATIC_DIR, 'flash_resized.png' ) + elif mime == HC.APPLICATION_PDF: path = os.path.join( HC.STATIC_DIR, 'pdf_resized.png' ) + else: path = os.path.join( HC.STATIC_DIR, 'hydrus_resized.png' ) response_context = HydrusServerResources.ResponseContext( 200, path = path ) diff --git a/include/ClientMedia.py b/include/ClientMedia.py index 068970f0..09bb4569 100644 --- a/include/ClientMedia.py +++ b/include/ClientMedia.py @@ -1034,13 +1034,13 @@ class MediaSingleton( Media ): ( volume, ) = volumes - title_string_append = 'volume ' + HydrusData.ToString( volume ) + title_string_append = 'volume ' + str( volume ) else: volumes_sorted = HydrusTags.SortTags( volumes ) - title_string_append = 'volumes ' + HydrusData.ToString( volumes_sorted[0] ) + '-' + HydrusData.ToString( volumes_sorted[-1] ) + title_string_append = 'volumes ' + str( volumes_sorted[0] ) + '-' + str( volumes_sorted[-1] ) if len( title_string ) > 0: title_string += ' - ' + title_string_append @@ -1053,13 +1053,13 @@ class MediaSingleton( Media ): ( chapter, ) = chapters - title_string_append = 'chapter ' + HydrusData.ToString( chapter ) + title_string_append = 'chapter ' + str( chapter ) else: chapters_sorted = HydrusTags.SortTags( chapters ) - title_string_append = 'chapters ' + HydrusData.ToString( chapters_sorted[0] ) + '-' + HydrusData.ToString( chapters_sorted[-1] ) + title_string_append = 'chapters ' + str( chapters_sorted[0] ) + '-' + str( chapters_sorted[-1] ) if len( title_string ) > 0: title_string += ' - ' + title_string_append @@ -1072,13 +1072,13 @@ class MediaSingleton( Media ): ( page, ) = pages - title_string_append = 'page ' + HydrusData.ToString( page ) + title_string_append = 'page ' + str( page ) else: pages_sorted = HydrusTags.SortTags( pages ) - title_string_append = 'pages ' + HydrusData.ToString( pages_sorted[0] ) + '-' + HydrusData.ToString( pages_sorted[-1] ) + title_string_append = 'pages ' + str( pages_sorted[0] ) + '-' + str( pages_sorted[-1] ) if len( title_string ) > 0: title_string += ' - ' + title_string_append @@ -1098,9 +1098,9 @@ class MediaSingleton( Media ): def IsCollection( self ): return False - def IsImage( self ): return HydrusFileHandling.IsImage( self._media_result.GetMime() ) + def IsImage( self ): return self._media_result.GetMime() in HC.IMAGES - def IsNoisy( self ): return self.GetMime() in HC.NOISY_MIMES + def IsNoisy( self ): return self._media_result.GetMime() in HC.NOISY_MIMES def IsSizeDefinite( self ): return self._media_result.GetSize() is not None diff --git a/include/ClientNetworking.py b/include/ClientNetworking.py index 68df3054..efcf0890 100644 --- a/include/ClientNetworking.py +++ b/include/ClientNetworking.py @@ -1,5 +1,6 @@ import HydrusConstants as HC import HydrusExceptions +import HydrusPaths import HydrusSerialisable import httplib import os @@ -57,7 +58,7 @@ def CheckHydrusVersion( service_key, service_type, response_headers ): if network_version > HC.NETWORK_VERSION: message = 'Your client is out of date; please download the latest release.' else: message = 'The server is out of date; please ask its admin to update to the latest release.' - raise HydrusExceptions.NetworkVersionException( 'Network version mismatch! The server\'s network version was ' + HydrusData.ToString( network_version ) + ', whereas your client\'s is ' + HydrusData.ToString( HC.NETWORK_VERSION ) + '! ' + message ) + raise HydrusExceptions.NetworkVersionException( 'Network version mismatch! The server\'s network version was ' + str( network_version ) + ', whereas your client\'s is ' + str( HC.NETWORK_VERSION ) + '! ' + message ) def ConvertHydrusGETArgsToQuery( request_args ): @@ -102,7 +103,7 @@ def ConvertHydrusGETArgsToQuery( request_args ): request_args[ 'title' ] = request_args[ 'title' ].encode( 'hex' ) - query = '&'.join( [ key + '=' + HydrusData.ToString( value ) for ( key, value ) in request_args.items() ] ) + query = '&'.join( [ key + '=' + HydrusData.ToByteString( value ) for ( key, value ) in request_args.items() ] ) return query @@ -246,7 +247,10 @@ class HTTPConnectionManager( object ): while True: - if HydrusGlobals.model_shutdown: break + if HydrusGlobals.model_shutdown: + + break + last_checked = 0 @@ -343,9 +347,12 @@ class HTTPConnection( object ): data = '' - for block in HydrusData.ReadFileLikeAsBlocks( response ): + for block in HydrusPaths.ReadFileLikeAsBlocks( response ): - if HydrusGlobals.model_shutdown: raise Exception( 'Application is shutting down!' ) + if HydrusGlobals.model_shutdown: + + raise HydrusExceptions.ShutdownException( 'Application is shutting down!' ) + data += block @@ -387,7 +394,7 @@ class HTTPConnection( object ): try: parsed_response = yaml.safe_load( data ) except yaml.error.YAMLError as e: - raise HydrusExceptions.NetworkVersionException( 'Failed to parse a response object!' + os.linesep + HydrusData.ToString( e ) ) + raise HydrusExceptions.NetworkVersionException( 'Failed to parse a response object!' + os.linesep + HydrusData.ToUnicode( e ) ) elif content_type == 'application/json': @@ -423,9 +430,9 @@ class HTTPConnection( object ): except Exception as e: - text = 'Could not connect to ' + HydrusData.ToString( self._host ) + ':' + text = 'Could not connect to ' + HydrusData.ToUnicode( self._host ) + ':' text += os.linesep * 2 - text += HydrusData.ToString( e ) + text += HydrusData.ToUnicode( e ) raise Exception( text ) @@ -441,9 +448,12 @@ class HTTPConnection( object ): with open( temp_path, 'wb' ) as f: - for block in HydrusData.ReadFileLikeAsBlocks( response ): + for block in HydrusPaths.ReadFileLikeAsBlocks( response ): - if HydrusGlobals.model_shutdown: raise Exception( 'Application is shutting down!' ) + if HydrusGlobals.model_shutdown: + + raise HydrusExceptions.ShutdownException( 'Application is shutting down!' ) + size_of_response += len( block ) @@ -481,7 +491,7 @@ class HTTPConnection( object ): if method == HC.GET: method_string = 'GET' elif method == HC.POST: method_string = 'POST' - if 'User-Agent' not in request_headers: request_headers[ 'User-Agent' ] = 'hydrus/' + HydrusData.ToString( HC.NETWORK_VERSION ) + if 'User-Agent' not in request_headers: request_headers[ 'User-Agent' ] = 'hydrus/' + str( HC.NETWORK_VERSION ) # it is important to only send str, not unicode, to httplib # it uses += to extend the message body, which propagates the unicode (and thus fails) when @@ -540,7 +550,7 @@ class HTTPConnection( object ): # some booru is giving daft redirect responses print( url ) - url = urllib.quote( url.encode( 'utf-8' ), safe = '/?=&' ) + url = urllib.quote( HydrusData.ToByteString( url ), safe = '/?=&' ) print( url ) diff --git a/include/HydrusAudioHandling.py b/include/HydrusAudioHandling.py index 3319d68d..d03980c9 100644 --- a/include/HydrusAudioHandling.py +++ b/include/HydrusAudioHandling.py @@ -70,7 +70,7 @@ def PlayNoise( name ): if name == 'success': filename = 'success.mp3' elif name == 'error': filename = 'error.mp3' - path = HC.STATIC_DIR + os.path.sep + filename + path = os.path.join( HC.STATIC_DIR, filename ) noise = mp3play.load( path ) diff --git a/include/HydrusConstants.py b/include/HydrusConstants.py index a0c0e00c..b8114d31 100755 --- a/include/HydrusConstants.py +++ b/include/HydrusConstants.py @@ -5,18 +5,33 @@ import sys BASE_DIR = sys.path[0] -BIN_DIR = BASE_DIR + os.path.sep + 'bin' -DB_DIR = BASE_DIR + os.path.sep + 'db' -CLIENT_ARCHIVES_DIR = DB_DIR + os.path.sep + 'client_archives' -CLIENT_FILES_DIR = DB_DIR + os.path.sep + 'client_files' -SERVER_FILES_DIR = DB_DIR + os.path.sep + 'server_files' -CLIENT_THUMBNAILS_DIR = DB_DIR + os.path.sep + 'client_thumbnails' -SERVER_THUMBNAILS_DIR = DB_DIR + os.path.sep + 'server_thumbnails' -SERVER_MESSAGES_DIR = DB_DIR + os.path.sep + 'server_messages' -CLIENT_UPDATES_DIR = DB_DIR + os.path.sep + 'client_updates' -SERVER_UPDATES_DIR = DB_DIR + os.path.sep + 'server_updates' -LOGS_DIR = BASE_DIR + os.path.sep + 'logs' -STATIC_DIR = BASE_DIR + os.path.sep + 'static' +if BASE_DIR == '': + + BASE_DIR = os.getcwdu() + +else: + + try: + + BASE_DIR = BASE_DIR.decode( 'utf-8' ) + + except: + + pass + + +BIN_DIR = os.path.join( BASE_DIR, 'bin' ) +DB_DIR = os.path.join( BASE_DIR, 'db' ) +CLIENT_ARCHIVES_DIR = os.path.join( DB_DIR, 'client_archives' ) +CLIENT_FILES_DIR = os.path.join( DB_DIR, 'client_files' ) +SERVER_FILES_DIR = os.path.join( DB_DIR, 'server_files' ) +CLIENT_THUMBNAILS_DIR = os.path.join( DB_DIR, 'client_thumbnails' ) +SERVER_THUMBNAILS_DIR = os.path.join( DB_DIR, 'server_thumbnails' ) +SERVER_MESSAGES_DIR = os.path.join( DB_DIR, 'server_messages' ) +CLIENT_UPDATES_DIR = os.path.join( DB_DIR, 'client_updates' ) +SERVER_UPDATES_DIR = os.path.join( DB_DIR, 'server_updates' ) +LOGS_DIR = os.path.join( BASE_DIR, 'logs' ) +STATIC_DIR = os.path.join( BASE_DIR, 'static' ) # @@ -37,7 +52,7 @@ options = {} # Misc NETWORK_VERSION = 17 -SOFTWARE_VERSION = 179 +SOFTWARE_VERSION = 180 UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 ) diff --git a/include/HydrusController.py b/include/HydrusController.py index 054d2fec..89e84846 100644 --- a/include/HydrusController.py +++ b/include/HydrusController.py @@ -22,6 +22,9 @@ class HydrusController( object ): HydrusGlobals.controller = self + self._model_shutdown = False + self._view_shutdown = False + self._pubsub = HydrusPubSub.HydrusPubSub( self, self.pubsub_binding_errors_to_ignore ) self._currently_doing_pubsub = False @@ -152,6 +155,11 @@ class HydrusController( object ): gc.collect() + def ModelIsShutdown( self ): + + return self._model_shutdown + + def NotifyPubSubs( self ): raise NotImplementedError() @@ -169,6 +177,7 @@ class HydrusController( object ): def ShutdownModel( self ): + self._model_shutdown = True HydrusGlobals.model_shutdown = True while not self._db.LoopIsFinished(): time.sleep( 0.1 ) @@ -176,6 +185,7 @@ class HydrusController( object ): def ShutdownView( self ): + self._view_shutdown = True HydrusGlobals.view_shutdown = True self._ShutdownDaemons() @@ -219,11 +229,16 @@ class HydrusController( object ): return self._system_busy + def ViewIsShutdown( self ): + + return self._view_shutdown + + def WaitUntilPubSubsEmpty( self ): while True: - if HydrusGlobals.view_shutdown: raise HydrusExceptions.ShutdownException( 'Application shutting down!' ) + if self._view_shutdown: raise HydrusExceptions.ShutdownException( 'Application shutting down!' ) elif self._pubsub.NoJobsQueued() and not self._currently_doing_pubsub: return else: time.sleep( 0.00001 ) diff --git a/include/HydrusDB.py b/include/HydrusDB.py index 4110c5c4..5bbd8596 100644 --- a/include/HydrusDB.py +++ b/include/HydrusDB.py @@ -23,7 +23,7 @@ class HydrusDB( object ): self._local_shutdown = False self._loop_finished = False - self._db_path = HC.DB_DIR + os.path.sep + self.DB_NAME + '.db' + self._db_path = os.path.join( HC.DB_DIR, self.DB_NAME + '.db' ) self._jobs = Queue.PriorityQueue() self._pubsubs = [] @@ -44,7 +44,7 @@ class HydrusDB( object ): run_analyze_after = version < HC.SOFTWARE_VERSION - if version < HC.SOFTWARE_VERSION - 50: raise Exception( 'Your current version of hydrus ' + HydrusData.ToString( version ) + ' is too old for this version ' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ' to update. Please try updating with version ' + HydrusData.ToString( version + 45 ) + ' or earlier first.' ) + if version < HC.SOFTWARE_VERSION - 50: raise Exception( 'Your current version of hydrus ' + str( version ) + ' is too old for this version ' + str( HC.SOFTWARE_VERSION ) + ' to update. Please try updating with version ' + str( version + 45 ) + ' or earlier first.' ) while version < HC.SOFTWARE_VERSION: @@ -53,7 +53,7 @@ class HydrusDB( object ): try: self._c.execute( 'BEGIN IMMEDIATE' ) except Exception as e: - raise HydrusExceptions.DBAccessException( HydrusData.ToString( e ) ) + raise HydrusExceptions.DBAccessException( HydrusData.ToUnicode( e ) ) try: @@ -66,7 +66,7 @@ class HydrusDB( object ): self._c.execute( 'ROLLBACK' ) - raise Exception( 'Updating the ' + self.DB_NAME + ' db to version ' + HydrusData.ToString( version + 1 ) + ' caused this error:' + os.linesep + traceback.format_exc() ) + raise Exception( 'Updating the ' + self.DB_NAME + ' db to version ' + str( version + 1 ) + ' caused this error:' + os.linesep + traceback.format_exc() ) ( version, ) = self._c.execute( 'SELECT version FROM version;' ).fetchone() @@ -246,7 +246,7 @@ class HydrusDB( object ): error_count = 0 - while not ( ( self._local_shutdown or HydrusGlobals.model_shutdown ) and self._jobs.empty() ): + while not ( ( self._local_shutdown or self._controller.ModelIsShutdown() ) and self._jobs.empty() ): try: @@ -312,7 +312,10 @@ class HydrusDB( object ): job = HydrusData.JobDatabase( action, job_type, synchronous, *args, **kwargs ) - if HydrusGlobals.model_shutdown: raise HydrusExceptions.ShutdownException( 'Application has shut down!' ) + if self._controller.ModelIsShutdown(): + + raise HydrusExceptions.ShutdownException( 'Application has shut down!' ) + self._jobs.put( ( priority + 1, job ) ) # +1 so all writes of equal priority can clear out first @@ -328,7 +331,10 @@ class HydrusDB( object ): job = HydrusData.JobDatabase( action, job_type, synchronous, *args, **kwargs ) - if HydrusGlobals.model_shutdown: raise HydrusExceptions.ShutdownException( 'Application has shut down!' ) + if self._controller.ModelIsShutdown(): + + raise HydrusExceptions.ShutdownException( 'Application has shut down!' ) + self._jobs.put( ( priority, job ) ) diff --git a/include/HydrusDaemons.py b/include/HydrusDaemons.py index 35afd8f3..b148239c 100644 --- a/include/HydrusDaemons.py +++ b/include/HydrusDaemons.py @@ -6,20 +6,19 @@ import threading import time import traceback import HydrusData -import HydrusGlobals -def DAEMONMaintainDB(): +def DAEMONMaintainDB( controller ): - if HydrusGlobals.controller.CurrentlyIdle(): + if controller.CurrentlyIdle(): - HydrusGlobals.controller.MaintainDB() + controller.MaintainDB() -def DAEMONMaintainMemory(): +def DAEMONMaintainMemory( controller ): - HydrusGlobals.controller.MaintainMemory() + controller.MaintainMemory() -def DAEMONSleepCheck(): +def DAEMONSleepCheck( controller ): - HydrusGlobals.controller.SleepCheck() + controller.SleepCheck() \ No newline at end of file diff --git a/include/HydrusData.py b/include/HydrusData.py index 5c168a58..366a2462 100644 --- a/include/HydrusData.py +++ b/include/HydrusData.py @@ -167,7 +167,7 @@ def ConvertIntToPixels( i ): elif i == 1000000: return 'megapixels' else: return 'megapixels' -def ConvertIntToPrettyString( num ): return ToString( locale.format( "%d", num, grouping = True ) ) +def ConvertIntToPrettyString( num ): return locale.format( "%d", num, grouping = True ) def ConvertIntToUnit( unit ): @@ -181,21 +181,21 @@ def ConvertMillisecondsToPrettyTime( ms ): hours = ms / 3600000 if hours == 1: hours_result = '1 hour' - else: hours_result = ToString( hours ) + ' hours' + else: hours_result = str( hours ) + ' hours' ms = ms % 3600000 minutes = ms / 60000 if minutes == 1: minutes_result = '1 minute' - else: minutes_result = ToString( minutes ) + ' minutes' + else: minutes_result = str( minutes ) + ' minutes' ms = ms % 60000 seconds = ms / 1000 if seconds == 1: seconds_result = '1 second' - else: seconds_result = ToString( seconds ) + ' seconds' + else: seconds_result = str( seconds ) + ' seconds' detailed_seconds = float( ms ) / 1000.0 @@ -205,7 +205,7 @@ def ConvertMillisecondsToPrettyTime( ms ): ms = ms % 1000 if ms == 1: milliseconds_result = '1 millisecond' - else: milliseconds_result = ToString( ms ) + ' milliseconds' + else: milliseconds_result = str( ms ) + ' milliseconds' if hours > 0: return hours_result + ' ' + minutes_result @@ -219,12 +219,12 @@ def ConvertNumericalRatingToPrettyString( lower, upper, rating, rounded_result = rating_converted = ( rating * ( upper - lower ) ) + lower - if rounded_result: s = ToString( '%.2f' % round( rating_converted ) ) - else: s = ToString( '%.2f' % rating_converted ) + if rounded_result: s = '%.2f' % round( rating_converted ) + else: s = '%.2f' % rating_converted if out_of: - if lower in ( 0, 1 ): s += '/' + ToString( '%.2f' % upper ) + if lower in ( 0, 1 ): s += '/%.2f' % upper return s @@ -240,7 +240,7 @@ def ConvertPortablePathToAbsPath( portable_path ): if portable_path is None: return None if os.path.isabs( portable_path ): abs_path = portable_path - else: abs_path = os.path.normpath( HC.BASE_DIR + os.path.sep + portable_path ) + else: abs_path = os.path.normpath( os.path.join( HC.BASE_DIR, portable_path ) ) if os.path.exists( abs_path ): return abs_path else: return None @@ -269,31 +269,31 @@ def ConvertTimestampToPrettyAge( timestamp ): seconds = age % 60 if seconds == 1: s = '1 second' - else: s = ToString( seconds ) + ' seconds' + else: s = str( seconds ) + ' seconds' age = age / 60 minutes = age % 60 if minutes == 1: m = '1 minute' - else: m = ToString( minutes ) + ' minutes' + else: m = str( minutes ) + ' minutes' age = age / 60 hours = age % 24 if hours == 1: h = '1 hour' - else: h = ToString( hours ) + ' hours' + else: h = str( hours ) + ' hours' age = age / 24 days = age % 30 if days == 1: d = '1 day' - else: d = ToString( days ) + ' days' + else: d = str( days ) + ' days' age = age / 30 months = age % 12 if months == 1: mo = '1 month' - else: mo = ToString( months ) + ' months' + else: mo = str( months ) + ' months' years = age / 12 if years == 1: y = '1 year' - else: y = ToString( years ) + ' years' + else: y = str( years ) + ' years' if years > 0: return ' '.join( ( y, mo ) ) + ' old' elif months > 0: return ' '.join( ( mo, d ) ) + ' old' @@ -309,31 +309,31 @@ def ConvertTimestampToPrettyAgo( timestamp ): seconds = age % 60 if seconds == 1: s = '1 second' - else: s = ToString( seconds ) + ' seconds' + else: s = str( seconds ) + ' seconds' age = age / 60 minutes = age % 60 if minutes == 1: m = '1 minute' - else: m = ToString( minutes ) + ' minutes' + else: m = str( minutes ) + ' minutes' age = age / 60 hours = age % 24 if hours == 1: h = '1 hour' - else: h = ToString( hours ) + ' hours' + else: h = str( hours ) + ' hours' age = age / 24 days = age % 30 if days == 1: d = '1 day' - else: d = ToString( days ) + ' days' + else: d = str( days ) + ' days' age = age / 30 months = age % 12 if months == 1: mo = '1 month' - else: mo = ToString( months ) + ' months' + else: mo = str( months ) + ' months' years = age / 12 if years == 1: y = '1 year' - else: y = ToString( years ) + ' years' + else: y = str( years ) + ' years' if years > 0: return ' '.join( ( y, mo ) ) + ' ago' elif months > 0: return ' '.join( ( mo, d ) ) + ' ago' @@ -358,31 +358,31 @@ def ConvertTimestampToPrettyExpires( timestamp ): seconds = expires % 60 if seconds == 1: s = '1 second' - else: s = ToString( seconds ) + ' seconds' + else: s = str( seconds ) + ' seconds' expires = expires / 60 minutes = expires % 60 if minutes == 1: m = '1 minute' - else: m = ToString( minutes ) + ' minutes' + else: m = str( minutes ) + ' minutes' expires = expires / 60 hours = expires % 24 if hours == 1: h = '1 hour' - else: h = ToString( hours ) + ' hours' + else: h = str( hours ) + ' hours' expires = expires / 24 days = expires % 30 if days == 1: d = '1 day' - else: d = ToString( days ) + ' days' + else: d = str( days ) + ' days' expires = expires / 30 months = expires % 12 if months == 1: mo = '1 month' - else: mo = ToString( months ) + ' months' + else: mo = str( months ) + ' months' years = expires / 12 if years == 1: y = '1 year' - else: y = ToString( years ) + ' years' + else: y = str( years ) + ' years' if already_happend: @@ -413,31 +413,31 @@ def ConvertTimestampToPrettyPending( timestamp ): seconds = pending % 60 if seconds == 1: s = '1 second' - else: s = ToString( seconds ) + ' seconds' + else: s = str( seconds ) + ' seconds' pending = pending / 60 minutes = pending % 60 if minutes == 1: m = '1 minute' - else: m = ToString( minutes ) + ' minutes' + else: m = str( minutes ) + ' minutes' pending = pending / 60 hours = pending % 24 if hours == 1: h = '1 hour' - else: h = ToString( hours ) + ' hours' + else: h = str( hours ) + ' hours' pending = pending / 24 days = pending % 30 if days == 1: d = '1 day' - else: d = ToString( days ) + ' days' + else: d = str( days ) + ' days' pending = pending / 30 months = pending % 12 if months == 1: mo = '1 month' - else: mo = ToString( months ) + ' months' + else: mo = str( months ) + ' months' years = pending / 12 if years == 1: y = '1 year' - else: y = ToString( years ) + ' years' + else: y = str( years ) + ' years' if years > 0: return 'in ' + ' '.join( ( y, mo ) ) elif months > 0: return 'in ' + ' '.join( ( mo, d ) ) @@ -453,31 +453,31 @@ def ConvertTimestampToPrettySync( timestamp ): seconds = age % 60 if seconds == 1: s = '1 second' - else: s = ToString( seconds ) + ' seconds' + else: s = str( seconds ) + ' seconds' age = age / 60 minutes = age % 60 if minutes == 1: m = '1 minute' - else: m = ToString( minutes ) + ' minutes' + else: m = str( minutes ) + ' minutes' age = age / 60 hours = age % 24 if hours == 1: h = '1 hour' - else: h = ToString( hours ) + ' hours' + else: h = str( hours ) + ' hours' age = age / 24 days = age % 30 if days == 1: d = '1 day' - else: d = ToString( days ) + ' days' + else: d = str( days ) + ' days' age = age / 30 months = age % 12 if months == 1: mo = '1 month' - else: mo = ToString( months ) + ' months' + else: mo = str( months ) + ' months' years = age / 12 if years == 1: y = '1 year' - else: y = ToString( years ) + ' years' + else: y = str( years ) + ' years' if years > 0: return ' '.join( ( y, mo ) ) + ' ago' elif months > 0: return ' '.join( ( mo, d ) ) + ' ago' @@ -587,7 +587,7 @@ def GetNowPrecise(): def GetSiblingProcessPorts( instance ): - path = HC.BASE_DIR + os.path.sep + instance + '_running' + path = os.path.join( HC.BASE_DIR, instance + '_running' ) if os.path.exists( path ): @@ -678,7 +678,7 @@ def IntelligentMassIntersect( sets_to_reduce ): def IsAlreadyRunning( instance ): - path = HC.BASE_DIR + os.path.sep + instance + '_running' + path = os.path.join( HC.BASE_DIR, instance + '_running' ) if os.path.exists( path ): @@ -730,20 +730,9 @@ def MergeKeyToListDicts( key_to_list_dicts ): return result -def ReadFileLikeAsBlocks( f ): - - next_block = f.read( HC.READ_BLOCK_SIZE ) - - while next_block != '': - - yield next_block - - next_block = f.read( HC.READ_BLOCK_SIZE ) - - def RecordRunningStart( instance ): - path = HC.BASE_DIR + os.path.sep + instance + '_running' + path = os.path.join( HC.BASE_DIR, instance + '_running' ) record_string = '' @@ -805,15 +794,20 @@ def RecyclePath( path ): def ShowExceptionDefault( e ): + if isinstance( e, HydrusExceptions.ShutdownException ): + + return + + etype = type( e ) - value = ToString( e ) + value = ToUnicode( e ) trace_list = traceback.format_stack() trace = ''.join( trace_list ) - message = ToString( etype.__name__ ) + ': ' + ToString( value ) + os.linesep + ToString( trace ) + message = ToUnicode( etype.__name__ ) + ': ' + ToUnicode( value ) + os.linesep + ToUnicode( trace ) print( '' ) print( 'The following exception occured at ' + ConvertTimestampToPrettyTime( GetNow() ) + ':' ) @@ -834,7 +828,7 @@ def ShowTextDefault( text ): ShowText = ShowTextDefault -def SplayListForDB( xs ): return '("' + '","'.join( ( ToString( x ) for x in xs ) ) + '")' +def SplayListForDB( xs ): return '(' + ','.join( ( str( x ) for x in xs ) ) + ')' def SplitListIntoChunks( xs, n ): @@ -852,24 +846,67 @@ def TimeUntil( timestamp ): return timestamp - GetNow() -def ToBytes( text_producing_object ): +def ToByteString( text_producing_object ): - if type( text_producing_object ) == unicode: return text_producing_object.encode( 'utf-8' ) - else: return str( text_producing_object ) - -def ToString( text_producing_object ): - - if type( text_producing_object ) in ( str, unicode, bs4.element.NavigableString ): text = text_producing_object + if type( text_producing_object ) == unicode: + + return text_producing_object.encode( 'utf-8' ) + + elif type( text_producing_object ) == str: + + return text_producing_object + else: - try: text = str( text_producing_object ) # dealing with exceptions, etc... - except: text = repr( text_producing_object ) + + try: + + return str( text_producing_object ) + + except: + + return str( repr( text_producing_object ) ) + + - try: return unicode( text ) - except: +def ToUnicode( text_producing_object ): + + if type( text_producing_object ) in ( str, unicode, bs4.element.NavigableString ): - try: return text.decode( locale.getpreferredencoding() ) - except: return str( text ) + text = text_producing_object + else: + + try: + + text = str( text_producing_object ) # dealing with exceptions, etc... + + except: + + text = repr( text_producing_object ) + + + + if type( text ) != unicode: + + try: + + text = text.decode( 'utf-8' ) + + except: + + try: + + text = text.decode( locale.getpreferredencoding() ) + + except: + + pass + + + + + + return text class HydrusYAMLBase( yaml.YAMLObject ): @@ -1069,7 +1106,7 @@ class AccountIdentifier( HydrusSerialisable.SerialisableBase ): def __ne__( self, other ): return self.__hash__() != other.__hash__() - def __repr__( self ): return 'Account Identifier: ' + ToString( ( self._type, self._data ) ) + def __repr__( self ): return 'Account Identifier: ' + ToUnicode( ( self._type, self._data ) ) def _GetSerialisableInfo( self ): @@ -1467,7 +1504,7 @@ class ContentUpdate( object ): def __ne__( self, other ): return not self.__eq__( other ) - def __repr__( self ): return 'Content Update: ' + ToString( ( self._data_type, self._action, self._row ) ) + def __repr__( self ): return 'Content Update: ' + ToUnicode( ( self._data_type, self._action, self._row ) ) def GetHashes( self ): diff --git a/include/HydrusFileHandling.py b/include/HydrusFileHandling.py index 72b300d9..60fe4ac9 100644 --- a/include/HydrusFileHandling.py +++ b/include/HydrusFileHandling.py @@ -11,6 +11,7 @@ import HydrusDocumentHandling import HydrusExceptions import HydrusFlashHandling import HydrusImageHandling +import HydrusPaths import HydrusVideoHandling import os import tempfile @@ -41,57 +42,6 @@ header_and_mime = [ ( 0, '\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C', HC.UNDETERMINED_WM ) ] -def ConvertAbsPathToPortablePath( abs_path ): - - if abs_path == '': return None - - try: return os.path.relpath( abs_path, HC.BASE_DIR ) - except: return abs_path - -def CleanUpTempPath( os_file_handle, temp_path ): - - try: - - os.close( os_file_handle ) - - except OSError: - - gc.collect() - - try: - - os.close( os_file_handle ) - - except OSError: - - print( 'Could not close the temporary file ' + temp_path ) - - return - - - - try: - - os.remove( temp_path ) - - except OSError: - - gc.collect() - - try: - - os.remove( temp_path ) - - except OSError: - - print( 'Could not delete the temporary file ' + temp_path ) - - - -def CopyFileLikeToFileLike( f_source, f_dest ): - - for block in HydrusData.ReadFileLikeAsBlocks( f_source ): f_dest.write( block ) - def GenerateThumbnail( path, dimensions = HC.UNSCALED_THUMBNAIL_DIMENSIONS ): mime = GetMime( path ) @@ -155,7 +105,7 @@ def GetExtraHashesFromPath( path ): with open( path, 'rb' ) as f: - for block in HydrusData.ReadFileLikeAsBlocks( f ): + for block in HydrusPaths.ReadFileLikeAsBlocks( f ): h_md5.update( block ) h_sha1.update( block ) @@ -217,7 +167,7 @@ def GetHashFromPath( path ): with open( path, 'rb' ) as f: - for block in HydrusData.ReadFileLikeAsBlocks( f ): h.update( block ) + for block in HydrusPaths.ReadFileLikeAsBlocks( f ): h.update( block ) return h.digest() @@ -270,68 +220,4 @@ def GetMime( path ): return HC.APPLICATION_UNKNOWN - -def GetTempFile(): return tempfile.TemporaryFile() -def GetTempFileQuick(): return tempfile.SpooledTemporaryFile( max_size = 1024 * 1024 * 4 ) -def GetTempPath(): return tempfile.mkstemp( prefix = 'hydrus' ) - -def IsImage( mime ): return mime in ( HC.IMAGE_JPEG, HC.IMAGE_GIF, HC.IMAGE_PNG, HC.IMAGE_BMP ) - -def LaunchDirectory( path ): - - def do_it(): - - if HC.PLATFORM_WINDOWS: - - os.startfile( path ) - - else: - - if HC.PLATFORM_OSX: cmd = [ 'open' ] - elif HC.PLATFORM_LINUX: cmd = [ 'xdg-open' ] - - cmd.append( path ) - - process = subprocess.Popen( cmd, startupinfo = HydrusData.GetSubprocessStartupInfo() ) - - process.wait() - - process.communicate() - - - - thread = threading.Thread( target = do_it ) - - thread.daemon = True - - thread.start() - -def LaunchFile( path ): - - def do_it(): - - if HC.PLATFORM_WINDOWS: - - os.startfile( path ) - - else: - - if HC.PLATFORM_OSX: cmd = [ 'open' ] - elif HC.PLATFORM_LINUX: cmd = [ 'xdg-open' ] - - cmd.append( path ) - - process = subprocess.Popen( cmd, startupinfo = HydrusData.GetSubprocessStartupInfo() ) - - process.wait() - - process.communicate() - - - - thread = threading.Thread( target = do_it ) - - thread.daemon = True - - thread.start() \ No newline at end of file diff --git a/include/HydrusImageHandling.py b/include/HydrusImageHandling.py index 853bf444..75bf4db0 100755 --- a/include/HydrusImageHandling.py +++ b/include/HydrusImageHandling.py @@ -15,8 +15,8 @@ import threading import time import traceback import HydrusData -import HydrusFileHandling import HydrusGlobals +import HydrusPaths if cv2.__version__.startswith( '2' ): @@ -32,7 +32,7 @@ def ConvertToPngIfBmp( path ): if header == 'BM': - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -40,7 +40,7 @@ def ConvertToPngIfBmp( path ): with open( temp_path, 'wb' ) as f_dest: - HydrusFileHandling.CopyFileLikeToFileLike( f_source, f_dest ) + HydrusPaths.CopyFileLikeToFileLike( f_source, f_dest ) @@ -50,7 +50,7 @@ def ConvertToPngIfBmp( path ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) diff --git a/include/HydrusMessageHandling.py b/include/HydrusMessageHandling.py index 9abd04ea..6d690c44 100755 --- a/include/HydrusMessageHandling.py +++ b/include/HydrusMessageHandling.py @@ -129,7 +129,7 @@ class Message( HydrusData.HydrusYAMLBase ): if type( self._body ) == unicode: body_text = self._body.encode( 'utf-8' ) else: body_text = self._body - message += ''.join( [ yaml.safe_dump( public_key ) for public_key in contact_to_public_keys ] ) + subject_text + body_text + ''.join( self._files ) + HydrusData.ToString( self._conversation_key ) + HydrusData.ToString( self._timestamp ) + message += ''.join( [ yaml.safe_dump( public_key ) for public_key in contact_to_public_keys ] ) + subject_text + body_text + ''.join( self._files ) + HydrusData.ToUnicode( self._conversation_key ) + HydrusData.ToUnicode( self._timestamp ) hash_object = Crypto.Hash.SHA256.new( message ) diff --git a/include/HydrusNATPunch.py b/include/HydrusNATPunch.py index e0fd9974..6b5448d4 100644 --- a/include/HydrusNATPunch.py +++ b/include/HydrusNATPunch.py @@ -12,9 +12,9 @@ from twisted.python import log # new stuff starts here -if HC.PLATFORM_LINUX: upnpc_path = HC.BIN_DIR + os.path.sep + 'upnpc_linux' -elif HC.PLATFORM_OSX: upnpc_path = HC.BIN_DIR + os.path.sep + 'upnpc_osx' -elif HC.PLATFORM_WINDOWS: upnpc_path = HC.BIN_DIR + os.path.sep + 'upnpc_win32.exe' +if HC.PLATFORM_LINUX: upnpc_path = os.path.join( HC.BIN_DIR, 'upnpc_linux' ) +elif HC.PLATFORM_OSX: upnpc_path = os.path.join( HC.BIN_DIR, 'upnpc_osx' ) +elif HC.PLATFORM_WINDOWS: upnpc_path = os.path.join( HC.BIN_DIR, 'upnpc_win32.exe' ) EXTERNAL_IP = {} EXTERNAL_IP[ 'ip' ] = None @@ -37,7 +37,7 @@ def GetExternalIP(): ( output, error ) = p.communicate() - if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to fetch External IP:' + os.linesep * 2 + HydrusData.ToString( error ) ) + if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to fetch External IP:' + os.linesep * 2 + HydrusData.ToUnicode( error ) ) else: try: @@ -79,7 +79,7 @@ def AddUPnPMapping( internal_client, internal_port, external_port, protocol, des ( output, error ) = p.communicate() - if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to add UPnP mapping:' + os.linesep * 2 + HydrusData.ToString( error ) ) + if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to add UPnP mapping:' + os.linesep * 2 + HydrusData.ToUnicode( error ) ) def GetUPnPMappings(): @@ -93,7 +93,7 @@ def GetUPnPMappings(): ( output, error ) = p.communicate() - if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to fetch UPnP mappings:' + os.linesep * 2 + HydrusData.ToString( error ) ) + if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to fetch UPnP mappings:' + os.linesep * 2 + HydrusData.ToUnicode( error ) ) else: try: @@ -147,7 +147,7 @@ def GetUPnPMappings(): print( traceback.format_exc() ) - raise Exception( 'Problem while trying to parse UPnP mappings:' + os.linesep * 2 + HydrusData.ToString( e ) ) + raise Exception( 'Problem while trying to parse UPnP mappings:' + os.linesep * 2 + HydrusData.ToUnicode( e ) ) @@ -161,5 +161,5 @@ def RemoveUPnPMapping( external_port, protocol ): ( output, error ) = p.communicate() - if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to remove UPnP mapping:' + os.linesep * 2 + HydrusData.ToString( error ) ) + if error is not None and len( error ) > 0: raise Exception( 'Problem while trying to remove UPnP mapping:' + os.linesep * 2 + HydrusData.ToUnicode( error ) ) \ No newline at end of file diff --git a/include/HydrusPaths.py b/include/HydrusPaths.py new file mode 100644 index 00000000..9ef3c4c9 --- /dev/null +++ b/include/HydrusPaths.py @@ -0,0 +1,132 @@ +import gc +import HydrusConstants as HC +import HydrusData +import os +import subprocess +import tempfile +import threading + +def CleanUpTempPath( os_file_handle, temp_path ): + + try: + + os.close( os_file_handle ) + + except OSError: + + gc.collect() + + try: + + os.close( os_file_handle ) + + except OSError: + + print( 'Could not close the temporary file ' + temp_path ) + + return + + + + try: + + os.remove( temp_path ) + + except OSError: + + gc.collect() + + try: + + os.remove( temp_path ) + + except OSError: + + print( 'Could not delete the temporary file ' + temp_path ) + + + +def ConvertAbsPathToPortablePath( abs_path ): + + if abs_path == '': return None + + try: return os.path.relpath( abs_path, HC.BASE_DIR ) + except: return abs_path + +def CopyFileLikeToFileLike( f_source, f_dest ): + + for block in ReadFileLikeAsBlocks( f_source ): f_dest.write( block ) + +def GetTempFile(): return tempfile.TemporaryFile() +def GetTempFileQuick(): return tempfile.SpooledTemporaryFile( max_size = 1024 * 1024 * 4 ) +def GetTempPath(): return tempfile.mkstemp( prefix = 'hydrus' ) + +def LaunchDirectory( path ): + + def do_it(): + + if HC.PLATFORM_WINDOWS: + + os.startfile( path ) + + else: + + if HC.PLATFORM_OSX: cmd = [ 'open' ] + elif HC.PLATFORM_LINUX: cmd = [ 'xdg-open' ] + + cmd.append( path ) + + process = subprocess.Popen( cmd, startupinfo = HydrusData.GetSubprocessStartupInfo() ) + + process.wait() + + process.communicate() + + + + thread = threading.Thread( target = do_it ) + + thread.daemon = True + + thread.start() + +def LaunchFile( path ): + + def do_it(): + + if HC.PLATFORM_WINDOWS: + + os.startfile( path ) + + else: + + if HC.PLATFORM_OSX: cmd = [ 'open' ] + elif HC.PLATFORM_LINUX: cmd = [ 'xdg-open' ] + + cmd.append( path ) + + process = subprocess.Popen( cmd, startupinfo = HydrusData.GetSubprocessStartupInfo() ) + + process.wait() + + process.communicate() + + + + thread = threading.Thread( target = do_it ) + + thread.daemon = True + + thread.start() + +def ReadFileLikeAsBlocks( f ): + + next_block = f.read( HC.READ_BLOCK_SIZE ) + + while next_block != '': + + yield next_block + + next_block = f.read( HC.READ_BLOCK_SIZE ) + + \ No newline at end of file diff --git a/include/HydrusServer.py b/include/HydrusServer.py index d7b5f57a..ef09eae1 100755 --- a/include/HydrusServer.py +++ b/include/HydrusServer.py @@ -101,7 +101,7 @@ eris = '''
-
+
MM:::::M:::::::::::::::::::::MMM MM::::M::::::::::::::::::::MMM MM:::M::::::::::::::::::::MMM - MM::M:::::::::::::::::::MMM THIS IS THE HYDRUS SERVER ADMIN SERVICE, VERSION ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' + MM::M:::::::::::::::::::MMM THIS IS THE HYDRUS SERVER ADMIN SERVICE, VERSION ''' + str( HC.SOFTWARE_VERSION ) + ''' MM:M:::::::::::::::::::MMM MMM::::::::::::::::::MMM MM::::::::::::::::::MMM @@ -173,7 +173,7 @@ CLIENT_ROOT_MESSAGE = '''hydrus client -This hydrus client uses software version ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' and network version ''' + HydrusData.ToString( HC.NETWORK_VERSION ) + '''.
+This hydrus client uses software version ''' + str( HC.SOFTWARE_VERSION ) + ''' and network version ''' + str( HC.NETWORK_VERSION ) + '''.
It only serves requests from 127.0.0.1.
''' @@ -183,7 +183,7 @@ ROOT_MESSAGE_BEGIN = '''hydrus service -This hydrus service uses software version ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' and network version ''' + HydrusData.ToString( HC.NETWORK_VERSION ) + '''.
+This hydrus service uses software version ''' + str( HC.SOFTWARE_VERSION ) + ''' and network version ''' + str( HC.NETWORK_VERSION ) + '''.
''' ROOT_MESSAGE_END = '''
diff --git a/include/HydrusServerAMP.py b/include/HydrusServerAMP.py index 1fb8f2b6..88a5ccfe 100644 --- a/include/HydrusServerAMP.py +++ b/include/HydrusServerAMP.py @@ -122,7 +122,7 @@ class MessagingServiceProtocol( HydrusAMP ): if network_version < HC.NETWORK_VERSION: message = 'Your client is out of date; please download the latest release.' else: message = 'This server is out of date; please ask its admin to update to the latest release.' - message = 'Network version mismatch! This server\'s network version is ' + HydrusData.ToString( HC.NETWORK_VERSION ) + ', whereas your client\'s is ' + HydrusData.ToString( network_version ) + '! ' + message + message = 'Network version mismatch! This server\'s network version is ' + str( HC.NETWORK_VERSION ) + ', whereas your client\'s is ' + str( network_version ) + '! ' + message raise HydrusExceptions.NetworkVersionException( message ) diff --git a/include/HydrusServerResources.py b/include/HydrusServerResources.py index fad9a4ce..9f992929 100644 --- a/include/HydrusServerResources.py +++ b/include/HydrusServerResources.py @@ -3,6 +3,7 @@ import HydrusConstants as HC import HydrusExceptions import HydrusFileHandling import HydrusImageHandling +import HydrusPaths import HydrusSerialisable import HydrusThreading import os @@ -23,7 +24,7 @@ CLIENT_ROOT_MESSAGE = '''hydrus client -This hydrus client uses software version ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' and network version ''' + HydrusData.ToString( HC.NETWORK_VERSION ) + '''.
+This hydrus client uses software version ''' + str( HC.SOFTWARE_VERSION ) + ''' and network version ''' + str( HC.NETWORK_VERSION ) + '''.
It only serves requests from 127.0.0.1.
''' @@ -33,7 +34,7 @@ ROOT_MESSAGE_BEGIN = '''hydrus service -This hydrus service uses software version ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' and network version ''' + HydrusData.ToString( HC.NETWORK_VERSION ) + '''.
+This hydrus service uses software version ''' + str( HC.SOFTWARE_VERSION ) + ''' and network version ''' + str( HC.NETWORK_VERSION ) + '''.
''' ROOT_MESSAGE_END = '''
@@ -60,7 +61,7 @@ def ParseFileArguments( path ): except Exception as e: - raise HydrusExceptions.ForbiddenException( HydrusData.ToString( e ) ) + raise HydrusExceptions.ForbiddenException( HydrusData.ToUnicode( e ) ) args = {} @@ -86,8 +87,8 @@ def ParseFileArguments( path ): return args -hydrus_favicon = FileResource( HC.STATIC_DIR + os.path.sep + 'hydrus.ico', defaultType = 'image/x-icon' ) -local_booru_css = FileResource( HC.STATIC_DIR + os.path.sep + 'local_booru_style.css', defaultType = 'text/css' ) +hydrus_favicon = FileResource( os.path.join( HC.STATIC_DIR, 'hydrus.ico' ), defaultType = 'image/x-icon' ) +local_booru_css = FileResource( os.path.join( HC.STATIC_DIR, 'local_booru_style.css' ), defaultType = 'text/css' ) class HydrusDomain( object ): @@ -127,7 +128,7 @@ class HydrusResourceWelcome( Resource ): if service_type == HC.LOCAL_FILE: body = CLIENT_ROOT_MESSAGE else: body = ROOT_MESSAGE_BEGIN + message + ROOT_MESSAGE_END - self._body = body.encode( 'utf-8' ) + self._body = HydrusData.ToByteString( body ) self._server_version_string = HC.service_string_lookup[ service_type ] + '/' + str( HC.NETWORK_VERSION ) @@ -256,13 +257,13 @@ class HydrusResourceCommand( Resource ): else: - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() request.temp_file_info = ( os_file_handle, temp_path ) with open( temp_path, 'wb' ) as f: - for block in HydrusData.ReadFileLikeAsBlocks( request.content ): + for block in HydrusPaths.ReadFileLikeAsBlocks( request.content ): f.write( block ) @@ -304,9 +305,7 @@ class HydrusResourceCommand( Resource ): request.setHeader( 'Content-Type', content_type ) request.setHeader( 'Content-Length', str( content_length ) ) - if type( body ) == unicode: body = body.encode( 'utf-8' ) - - request.write( body ) + request.write( HydrusData.ToByteString( body ) ) elif response_context.HasPath(): @@ -333,7 +332,8 @@ class HydrusResourceCommand( Resource ): content_length = size - request.setHeader( 'Content-Type', content_type ) + # can't be unicode! + request.setHeader( 'Content-Type', str( content_type ) ) request.setHeader( 'Content-Length', str( content_length ) ) request.setHeader( 'Expires', time.strftime( '%a, %d %b %Y %H:%M:%S GMT', time.gmtime( time.time() + 86400 * 365 ) ) ) @@ -427,7 +427,7 @@ class HydrusResourceCommand( Resource ): if network_version < HC.NETWORK_VERSION: message = 'Your client is out of date; please download the latest release.' else: message = 'This server is out of date; please ask its admin to update to the latest release.' - raise HydrusExceptions.NetworkVersionException( 'Network version mismatch! This server\'s network version is ' + HydrusData.ToString( HC.NETWORK_VERSION ) + ', whereas your client\'s is ' + HydrusData.ToString( network_version ) + '! ' + message ) + raise HydrusExceptions.NetworkVersionException( 'Network version mismatch! This server\'s network version is ' + str( HC.NETWORK_VERSION ) + ', whereas your client\'s is ' + str( network_version ) + '! ' + message ) @@ -465,12 +465,12 @@ class HydrusResourceCommand( Resource ): if do_yaml: default_mime = HC.APPLICATION_YAML - default_encoding = lambda x: yaml.safe_dump( HydrusData.ToString( x ) ) + default_encoding = lambda x: yaml.safe_dump( HydrusData.ToUnicode( x ) ) else: default_mime = HC.TEXT_HTML - default_encoding = lambda x: HydrusData.ToString( x ) + default_encoding = lambda x: HydrusData.ToByteString( x ) if failure.type == KeyError: response_context = ResponseContext( 403, mime = default_mime, body = default_encoding( 'It appears one or more parameters required for that request were missing:' + os.linesep + failure.getTraceback() ) ) @@ -518,7 +518,7 @@ class HydrusResourceCommand( Resource ): ( os_file_handle, temp_path ) = request.temp_file_info - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) del request.temp_file_info diff --git a/include/HydrusTags.py b/include/HydrusTags.py index 8e5bfa7a..1327d0e5 100644 --- a/include/HydrusTags.py +++ b/include/HydrusTags.py @@ -113,7 +113,7 @@ def CleanTag( tag ): tag = tag.lower() - tag = HydrusData.ToString( tag ) + tag = HydrusData.ToUnicode( tag ) tag.replace( '\r', '' ) tag.replace( '\n', '' ) diff --git a/include/HydrusThreading.py b/include/HydrusThreading.py index 05421eeb..0e4bb8cd 100644 --- a/include/HydrusThreading.py +++ b/include/HydrusThreading.py @@ -121,7 +121,7 @@ class DAEMONQueue( DAEMON ): try: - self._callable( items ) + self._callable( self._controller, items ) except HydrusExceptions.ShutdownException: @@ -172,7 +172,7 @@ class DAEMONWorker( DAEMON ): try: - self._callable() + self._callable( self._controller ) except HydrusExceptions.ShutdownException: @@ -219,7 +219,7 @@ class DAEMONCallToThread( DAEMON ): while self._queue.empty(): - if HydrusGlobals.model_shutdown: return + if self._controller.ModelIsShutdown(): return self._event.wait( 1200 ) @@ -379,7 +379,7 @@ class JobKey( object ): if 'popup_db_traceback' in self._variables: stuff_to_print.append( self._variables[ 'popup_db_traceback' ] ) - stuff_to_print = [ HydrusData.ToString( s ) for s in stuff_to_print ] + stuff_to_print = [ HydrusData.ToUnicode( s ) for s in stuff_to_print ] try: diff --git a/include/HydrusVideoHandling.py b/include/HydrusVideoHandling.py index 822655d6..8b04a77c 100755 --- a/include/HydrusVideoHandling.py +++ b/include/HydrusVideoHandling.py @@ -17,9 +17,9 @@ import traceback import threading import time -if HC.PLATFORM_LINUX: FFMPEG_PATH = '' + HC.BIN_DIR + os.path.sep + 'ffmpeg' -elif HC.PLATFORM_OSX: FFMPEG_PATH = '' + HC.BIN_DIR + os.path.sep + 'ffmpeg' -elif HC.PLATFORM_WINDOWS: FFMPEG_PATH = '' + HC.BIN_DIR + os.path.sep + 'ffmpeg.exe' +if HC.PLATFORM_LINUX: FFMPEG_PATH = os.path.join( HC.BIN_DIR, 'ffmpeg' ) +elif HC.PLATFORM_OSX: FFMPEG_PATH = os.path.join( HC.BIN_DIR, 'ffmpeg' ) +elif HC.PLATFORM_WINDOWS: FFMPEG_PATH = os.path.join( HC.BIN_DIR, 'ffmpeg.exe' ) if cv2.__version__.startswith( '2' ): @@ -433,7 +433,7 @@ class GIFRenderer( object ): self._num_frames = num_frames self._target_resolution = target_resolution - if HC.PLATFORM_LINUX or HC.PLATFORM_OSX: + if cv2.__version__.startswith( '2' ): self._InitialisePIL() @@ -453,7 +453,7 @@ class GIFRenderer( object ): self._next_render_index = ( self._next_render_index + 1 ) % self._num_frames - raise HydrusExceptions.CantRenderWithCVException( 'CV could not render frame ' + HydrusData.ToString( self._next_render_index - 1 ) + '.' ) + raise HydrusExceptions.CantRenderWithCVException( 'CV could not render frame ' + str( self._next_render_index - 1 ) + '.' ) else: diff --git a/include/ServerController.py b/include/ServerController.py index 668ffc83..ed30f6f1 100755 --- a/include/ServerController.py +++ b/include/ServerController.py @@ -221,7 +221,7 @@ class Controller( HydrusController.HydrusController ): connection = HydrusNetworking.GetLocalConnection( port ) connection.close() - raise Exception( 'Something was already bound to port ' + HydrusData.ToString( port ) ) + raise Exception( 'Something was already bound to port ' + str( port ) ) except: @@ -241,7 +241,7 @@ class Controller( HydrusController.HydrusController ): except: - raise Exception( 'Tried to bind port ' + HydrusData.ToString( port ) + ' but it failed.' ) + raise Exception( 'Tried to bind port ' + str( port ) + ' but it failed.' ) @@ -287,7 +287,7 @@ class Controller( HydrusController.HydrusController ): if already_bound: - raise HydrusExceptions.PermissionException( 'Something was already bound to port ' + HydrusData.ToString( port ) ) + raise HydrusExceptions.PermissionException( 'Something was already bound to port ' + str( port ) ) @@ -357,7 +357,7 @@ class Controller( HydrusController.HydrusController ): interrupt_received = False - while not HydrusGlobals.model_shutdown: + while not self._model_shutdown: try: diff --git a/include/ServerDB.py b/include/ServerDB.py index 84459854..abd404a6 100755 --- a/include/ServerDB.py +++ b/include/ServerDB.py @@ -4,8 +4,8 @@ import httplib import HydrusConstants as HC import HydrusDB import HydrusExceptions -import HydrusFileHandling import HydrusNATPunch +import HydrusPaths import HydrusSerialisable import itertools import json @@ -157,7 +157,7 @@ class DB( HydrusDB.HydrusDB ): with open( dest_path, 'wb' ) as f_dest: - HydrusFileHandling.CopyFileLikeToFileLike( f_source, f_dest ) + HydrusPaths.CopyFileLikeToFileLike( f_source, f_dest ) @@ -543,9 +543,12 @@ class DB( HydrusDB.HydrusDB ): for ( one, two ) in itertools.product( hex_chars, hex_chars ): - new_dir = dir + os.path.sep + one + two + new_dir = os.path.join( dir, one + two ) - if not os.path.exists( new_dir ): os.mkdir( new_dir ) + if not os.path.exists( new_dir ): + + os.mkdir( new_dir ) + @@ -1135,7 +1138,7 @@ class DB( HydrusDB.HydrusDB ): result = self._c.execute( 'SELECT account_type_id FROM account_types WHERE service_id = ? AND title = ?;', ( service_id, title ) ).fetchone() - if result is None: raise HydrusExceptions.NotFoundException( 'Could not find account title ' + HydrusData.ToString( title ) + ' in db for this service.' ) + if result is None: raise HydrusExceptions.NotFoundException( 'Could not find account title ' + HydrusData.ToUnicode( title ) + ' in db for this service.' ) ( account_type_id, ) = result @@ -1149,28 +1152,13 @@ class DB( HydrusDB.HydrusDB ): return [ account_type for ( account_type, ) in self._c.execute( 'SELECT account_type FROM account_types WHERE service_id = ?;', ( service_id, ) ) ] - def _GetDirtyUpdates( self ): + def _GetDirtyUpdates( self, service_key ): - service_ids_to_tuples = HydrusData.BuildKeyToListDict( [ ( service_id, ( begin, end ) ) for ( service_id, begin, end ) in self._c.execute( 'SELECT service_id, begin, end FROM update_cache WHERE dirty = ?;', ( True, ) ) ] ) + service_id = self._GetServiceId( service_key ) - service_keys_to_tuples = {} + result = self._c.execute( 'SELECT begin, end FROM update_cache WHERE service_id = ? AND dirty = ?;', ( service_id, True ) ).fetchall() - for ( service_id, tuples ) in service_ids_to_tuples.items(): - - result_1 = self._c.execute( 'SELECT 1 FROM file_petitions WHERE service_id = ? AND status = ?;', ( service_id, HC.PETITIONED ) ).fetchone() - result_2 = self._c.execute( 'SELECT 1 FROM mapping_petitions WHERE service_id = ? AND status = ?;', ( service_id, HC.PETITIONED ) ).fetchone() - - if result_1 is not None or result_2 is not None: - - continue - - - service_key = self._GetServiceKey( service_id ) - - service_keys_to_tuples[ service_key ] = tuples - - - return service_keys_to_tuples + return result def _GetFile( self, hash ): @@ -1844,7 +1832,7 @@ class DB( HydrusDB.HydrusDB ): title = account_type.GetTitle() - if self._AccountTypeExists( service_id, title ): raise HydrusExceptions.ForbiddenException( 'Already found account type ' + HydrusData.ToString( title ) + ' in the db for this service, so could not add!' ) + if self._AccountTypeExists( service_id, title ): raise HydrusExceptions.ForbiddenException( 'Already found account type ' + HydrusData.ToUnicode( title ) + ' in the db for this service, so could not add!' ) self._c.execute( 'INSERT OR IGNORE INTO account_types ( service_id, title, account_type ) VALUES ( ?, ?, ? );', ( service_id, title, account_type ) ) @@ -1867,7 +1855,7 @@ class DB( HydrusDB.HydrusDB ): title = account_type.GetTitle() - if old_title != title and self._AccountTypeExists( service_id, title ): raise HydrusExceptions.ForbiddenException( 'Already found account type ' + HydrusData.ToString( title ) + ' in the database, so could not rename ' + HydrusData.ToString( old_title ) + '!' ) + if old_title != title and self._AccountTypeExists( service_id, title ): raise HydrusExceptions.ForbiddenException( 'Already found account type ' + HydrusData.ToUnicode( title ) + ' in the database, so could not rename ' + HydrusData.ToUnicode( old_title ) + '!' ) account_type_id = self._GetAccountTypeId( service_id, old_title ) @@ -1906,6 +1894,13 @@ class DB( HydrusDB.HydrusDB ): if service_type in HC.REPOSITORIES: + update_dir = ServerFiles.GetExpectedUpdateDir( service_key ) + + if not os.path.exists( update_dir ): + + os.mkdir( update_dir ) + + begin = 0 end = HydrusData.GetNow() @@ -1922,6 +1917,13 @@ class DB( HydrusDB.HydrusDB ): self._c.execute( 'DELETE FROM services WHERE service_id = ?;', ( service_id, ) ) + update_dir = ServerFiles.GetExpectedUpdateDir( service_key ) + + if os.path.exists( update_dir ): + + HydrusData.DeletePath( update_dir ) + + self.pub_after_commit( 'action_service', service_key, 'stop' ) elif action == HC.EDIT: @@ -2219,56 +2221,6 @@ class DB( HydrusDB.HydrusDB ): def _UpdateDB( self, version ): - if version == 128: - - self._c.execute( 'COMMIT' ) - - self._c.execute( 'PRAGMA foreign_keys = OFF;' ) - - self._c.execute( 'BEGIN IMMEDIATE' ) - - # - - old_account_info = self._c.execute( 'SELECT * FROM accounts;' ).fetchall() - - self._c.execute( 'DROP TABLE accounts;' ) - - self._c.execute( 'CREATE TABLE accounts ( account_id INTEGER PRIMARY KEY, account_key BLOB_BYTES, access_key BLOB_BYTES );' ) - self._c.execute( 'CREATE UNIQUE INDEX accounts_account_key_index ON accounts ( account_key );' ) - self._c.execute( 'CREATE UNIQUE INDEX accounts_access_key_index ON accounts ( access_key );' ) - - for ( account_id, access_key ) in old_account_info: - - account_key = HydrusData.GenerateKey() - - self._c.execute( 'INSERT INTO accounts ( account_id, account_key, access_key ) VALUES ( ?, ?, ? );', ( account_id, sqlite3.Binary( account_key ), sqlite3.Binary( access_key ) ) ) - - - # - - old_r_k_info = self._c.execute( 'SELECT * FROM registration_keys;' ).fetchall() - - self._c.execute( 'DROP TABLE registration_keys;' ) - - self._c.execute( 'CREATE TABLE registration_keys ( registration_key BLOB_BYTES PRIMARY KEY, service_id INTEGER REFERENCES services ON DELETE CASCADE, account_type_id INTEGER, account_key BLOB_BYTES, access_key BLOB_BYTES, expiry INTEGER );' ) - self._c.execute( 'CREATE UNIQUE INDEX registration_keys_access_key_index ON registration_keys ( access_key );' ) - - for ( registration_key, service_id, account_type_id, access_key, expires ) in old_r_k_info: - - account_key = HydrusData.GenerateKey() - - self._c.execute( 'INSERT INTO registration_keys ( registration_key, service_id, account_type_id, account_key, access_key, expiry ) VALUES ( ?, ?, ?, ?, ?, ? );', ( sqlite3.Binary( registration_key ), service_id, account_type_id, sqlite3.Binary( account_key ), sqlite3.Binary( access_key ), expires ) ) - - - # - - self._c.execute( 'COMMIT' ) - - self._c.execute( 'PRAGMA foreign_keys = ON;' ) - - self._c.execute( 'BEGIN IMMEDIATE' ) - - if version == 131: accounts_info = self._c.execute( 'SELECT * FROM accounts;' ).fetchall() @@ -2346,7 +2298,10 @@ class DB( HydrusDB.HydrusDB ): if len( account_log_text ) > 0: - with open( HC.BASE_DIR + os.path.sep + 'update to v132 new access keys.txt', 'wb' ) as f: f.write( account_log_text ) + with open( os.path.join( HC.BASE_DIR, 'update to v132 new access keys.txt' ), 'wb' ) as f: + + f.write( account_log_text ) + for ( service_id, account_type_id ) in account_type_map_info: @@ -2383,9 +2338,12 @@ class DB( HydrusDB.HydrusDB ): for ( one, two ) in itertools.product( hex_chars, hex_chars ): - new_dir = dir + os.path.sep + one + two + new_dir = os.path.join( dir, one + two ) - if not os.path.exists( new_dir ): os.mkdir( new_dir ) + if not os.path.exists( new_dir ): + + os.mkdir( new_dir ) + @@ -2410,7 +2368,7 @@ class DB( HydrusDB.HydrusDB ): for filename in os.listdir( HC.SERVER_UPDATES_DIR ): - path = HC.SERVER_UPDATES_DIR + os.path.sep + filename + path = os.path.join( HC.SERVER_UPDATES_DIR, filename ) HydrusData.RecyclePath( path ) @@ -2427,7 +2385,7 @@ class DB( HydrusDB.HydrusDB ): for filename in os.listdir( HC.SERVER_UPDATES_DIR ): - path = HC.SERVER_UPDATES_DIR + os.path.sep + filename + path = os.path.join( HC.SERVER_UPDATES_DIR, filename ) with open( path, 'rb' ) as f: @@ -2482,6 +2440,35 @@ class DB( HydrusDB.HydrusDB ): self._c.executemany( 'DELETE FROM mappings WHERE tag_id = ?;', ( ( tag_id, ) for tag_id in bad_tag_ids ) ) + if version == 179: + + print( 'moving updates about' ) + + for filename in os.listdir( HC.SERVER_UPDATES_DIR ): + + try: + + ( service_key_encoded, gumpf ) = filename.split( '_', 1 ) + + except ValueError: + + continue + + + dest_dir = os.path.join( HC.SERVER_UPDATES_DIR, service_key_encoded ) + + if not os.path.exists( dest_dir ): + + os.mkdir( dest_dir ) + + + source_path = os.path.join( HC.SERVER_UPDATES_DIR, filename ) + dest_path = os.path.join( dest_dir, gumpf ) + + shutil.move( source_path, dest_path ) + + + print( 'The server has updated to version ' + str( version + 1 ) ) self._c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) ) diff --git a/include/ServerDaemons.py b/include/ServerDaemons.py index 1cc74804..f2eec4d0 100644 --- a/include/ServerDaemons.py +++ b/include/ServerDaemons.py @@ -4,7 +4,6 @@ import httplib import HydrusConstants as HC import HydrusData import HydrusExceptions -import HydrusFileHandling import HydrusGlobals import HydrusNATPunch import HydrusServer @@ -21,21 +20,31 @@ import time import traceback import yaml -def DAEMONCheckDataUsage(): HydrusGlobals.server_controller.WriteSynchronous( 'check_data_usage' ) - -def DAEMONCheckMonthlyData(): HydrusGlobals.server_controller.WriteSynchronous( 'check_monthly_data' ) - -def DAEMONClearBans(): HydrusGlobals.server_controller.WriteSynchronous( 'clear_bans' ) - -def DAEMONDeleteOrphans(): HydrusGlobals.server_controller.WriteSynchronous( 'delete_orphans' ) - -def DAEMONFlushRequestsMade( all_requests ): HydrusGlobals.server_controller.WriteSynchronous( 'flush_requests_made', all_requests ) - -def DAEMONGenerateUpdates(): +def DAEMONCheckDataUsage( controller ): + + controller.WriteSynchronous( 'check_data_usage' ) + +def DAEMONCheckMonthlyData( controller ): + + controller.WriteSynchronous( 'check_monthly_data' ) + +def DAEMONClearBans( controller ): + + controller.WriteSynchronous( 'clear_bans' ) + +def DAEMONDeleteOrphans( controller ): + + controller.WriteSynchronous( 'delete_orphans' ) + +def DAEMONFlushRequestsMade( controller, all_requests ): + + controller.WriteSynchronous( 'flush_requests_made', all_requests ) + +def DAEMONGenerateUpdates( controller ): if not HydrusGlobals.server_busy: - update_ends = HydrusGlobals.server_controller.Read( 'update_ends' ) + update_ends = controller.Read( 'update_ends' ) for ( service_key, biggest_end ) in update_ends.items(): @@ -53,7 +62,7 @@ def DAEMONGenerateUpdates(): while next_end < now: - HydrusGlobals.server_controller.WriteSynchronous( 'create_update', service_key, next_begin, next_end ) + controller.WriteSynchronous( 'create_update', service_key, next_begin, next_end ) biggest_end = next_end @@ -70,29 +79,36 @@ def DAEMONGenerateUpdates(): time_to_stop = HydrusData.GetNow() + 30 - dirty_updates = HydrusGlobals.server_controller.Read( 'dirty_updates' ) + service_keys = controller.Read( 'service_keys', HC.REPOSITORIES ) - for ( service_key, tuples ) in dirty_updates.items(): + for service_key in service_keys: - for ( begin, end ) in tuples: + num_petitions = controller.Read( 'num_petitions', service_key ) + + if num_petitions == 0: - if HydrusGlobals.view_shutdown or HydrusData.TimeHasPassed( time_to_stop ): + dirty_updates = controller.Read( 'dirty_updates', service_key ) + + for ( begin, end ) in dirty_updates: - return + if HydrusGlobals.view_shutdown or HydrusData.TimeHasPassed( time_to_stop ): + + return + + + HydrusGlobals.server_busy = True + + controller.WriteSynchronous( 'clean_update', service_key, begin, end ) + + HydrusGlobals.server_busy = False + + time.sleep( 1 ) - - HydrusGlobals.server_busy = True - - HydrusGlobals.server_controller.WriteSynchronous( 'clean_update', service_key, begin, end ) - - HydrusGlobals.server_busy = False - - time.sleep( 1 ) -def DAEMONUPnP(): +def DAEMONUPnP( controller ): try: @@ -104,7 +120,7 @@ def DAEMONUPnP(): except: return # This IGD probably doesn't support UPnP, so don't spam the user with errors they can't fix! - services_info = HydrusGlobals.server_controller.Read( 'services_info' ) + services_info = controller.Read( 'services_info' ) for ( service_key, service_type, options ) in services_info: diff --git a/include/ServerFiles.py b/include/ServerFiles.py index cec8122c..1a11bd44 100644 --- a/include/ServerFiles.py +++ b/include/ServerFiles.py @@ -15,27 +15,34 @@ def GetExpectedPath( file_type, hash ): first_two_chars = hash_encoded[:2] - path = directory + os.path.sep + first_two_chars + os.path.sep + hash_encoded + path = os.path.join( directory, first_two_chars, hash_encoded ) return path def GetExpectedContentUpdatePackagePath( service_key, begin, subindex ): - path = HC.SERVER_UPDATES_DIR + os.path.sep + service_key.encode( 'hex' ) + '_' + str( int( begin ) ) + '_' + str( subindex ) + path = os.path.join( GetExpectedUpdateDir( service_key ), str( int( begin ) ) + '_' + str( subindex ) ) return path def GetExpectedServiceUpdatePackagePath( service_key, begin ): - path = HC.SERVER_UPDATES_DIR + os.path.sep + service_key.encode( 'hex' ) + '_' + str( int( begin ) ) + '_metadata' + path = os.path.join( GetExpectedUpdateDir( service_key ), str( int( begin ) ) + '_metadata' ) return path +def GetExpectedUpdateDir( service_key ): + + return os.path.join( HC.SERVER_UPDATES_DIR, service_key.encode( 'hex' ) ) + def GetPath( file_type, hash ): path = GetExpectedPath( file_type, hash ) - if not os.path.exists( path ): raise HydrusExceptions.NotFoundException( file_type + ' not found!' ) + if not os.path.exists( path ): + + raise HydrusExceptions.NotFoundException( file_type + ' not found!' ) + return path @@ -43,7 +50,10 @@ def GetContentUpdatePackagePath( service_key, begin, subindex ): path = GetExpectedContentUpdatePackagePath( service_key, begin, subindex ) - if not os.path.exists( path ): raise HydrusExceptions.NotFoundException( 'Update not found!' ) + if not os.path.exists( path ): + + raise HydrusExceptions.NotFoundException( 'Update not found!' ) + return path @@ -51,27 +61,13 @@ def GetServiceUpdatePackagePath( service_key, begin ): path = GetExpectedServiceUpdatePackagePath( service_key, begin ) - if not os.path.exists( path ): raise HydrusExceptions.NotFoundException( 'Update not found!' ) + if not os.path.exists( path ): + + raise HydrusExceptions.NotFoundException( 'Update not found!' ) + return path -def GetUpdatePackagePaths( service_key, begin ): - - paths = [] - prefix = service_key.encode( 'hex' ) + '_' + str( int( begin ) ) - - for filename in os.listdir( HC.SERVER_UPDATES_DIR ): - - if filename.startswith( prefix ): - - path = HC.SERVER_UPDATES_DIR + os.path.sep + filename - - paths.append( path ) - - - - return paths - def IterateAllPaths( file_type ): if file_type == 'file': directory = HC.SERVER_FILES_DIR @@ -82,10 +78,13 @@ def IterateAllPaths( file_type ): for ( one, two ) in itertools.product( hex_chars, hex_chars ): - dir = directory + os.path.sep + one + two + dir = os.path.join( directory, one + two ) next_paths = os.listdir( dir ) - for path in next_paths: yield dir + os.path.sep + path + for path in next_paths: + + yield os.path.join( dir, path ) + \ No newline at end of file diff --git a/include/TestClientDaemons.py b/include/TestClientDaemons.py index aa4015dd..8e797b62 100644 --- a/include/TestClientDaemons.py +++ b/include/TestClientDaemons.py @@ -22,11 +22,11 @@ class TestDaemons( unittest.TestCase ): if not os.path.exists( test_dir ): os.mkdir( test_dir ) - with open( test_dir + os.path.sep + '0', 'wb' ) as f: f.write( TestConstants.tinest_gif ) - with open( test_dir + os.path.sep + '1', 'wb' ) as f: f.write( TestConstants.tinest_gif ) # previously imported - with open( test_dir + os.path.sep + '2', 'wb' ) as f: f.write( TestConstants.tinest_gif ) - with open( test_dir + os.path.sep + '3', 'wb' ) as f: f.write( 'blarg' ) # broken - with open( test_dir + os.path.sep + '4', 'wb' ) as f: f.write( 'blarg' ) # previously failed + with open( os.path.join( test_dir, '0' ), 'wb' ) as f: f.write( TestConstants.tinest_gif ) + with open( os.path.join( test_dir, '1' ), 'wb' ) as f: f.write( TestConstants.tinest_gif ) # previously imported + with open( os.path.join( test_dir, '2' ), 'wb' ) as f: f.write( TestConstants.tinest_gif ) + with open( os.path.join( test_dir, '3' ), 'wb' ) as f: f.write( 'blarg' ) # broken + with open( os.path.join( test_dir, '4' ), 'wb' ) as f: f.write( 'blarg' ) # previously failed # @@ -34,9 +34,7 @@ class TestDaemons( unittest.TestCase ): HydrusGlobals.test_controller.SetRead( 'serialisable_named', [ import_folder ] ) - - - ClientDaemons.DAEMONCheckImportFolders() + ClientDaemons.DAEMONCheckImportFolders( HydrusGlobals.test_controller ) #(('C:\\code\\Hydrus\\temp\\7baa9a818a14b7a9cbefb04c16bdc45ac651eb7400c1996e66e2efeef9e3ee5d',), {'service_keys_to_tags': {HC.LOCAL_TAG_SERVICE_KEY: set(['local tag'])}}) #(('C:\\code\\Hydrus\\temp\\e0dbdcb1a13c0565ffb73f2f497528adbe1703ca1dfc69680202487187b9fcfa',), {'service_keys_to_tags': {HC.LOCAL_TAG_SERVICE_KEY: set(['local tag'])}}) @@ -52,11 +50,11 @@ class TestDaemons( unittest.TestCase ): self.assertEqual( updated_import_folder, import_folder ) - self.assertTrue( not os.path.exists( test_dir + os.path.sep + '0' ) ) - self.assertTrue( not os.path.exists( test_dir + os.path.sep + '1' ) ) - self.assertTrue( not os.path.exists( test_dir + os.path.sep + '2' ) ) - self.assertTrue( os.path.exists( test_dir + os.path.sep + '3' ) ) - self.assertTrue( os.path.exists( test_dir + os.path.sep + '4' ) ) + self.assertTrue( not os.path.exists( os.path.join( test_dir, '0' ) ) ) + self.assertTrue( not os.path.exists( os.path.join( test_dir, '1' ) ) ) + self.assertTrue( not os.path.exists( os.path.join( test_dir, '2' ) ) ) + self.assertTrue( os.path.exists( os.path.join( test_dir, '3' ) ) ) + self.assertTrue( os.path.exists( os.path.join( test_dir, '4' ) ) ) finally: diff --git a/include/TestClientDownloading.py b/include/TestClientDownloading.py index a6270f16..cfb27512 100644 --- a/include/TestClientDownloading.py +++ b/include/TestClientDownloading.py @@ -2,11 +2,11 @@ import ClientConstants as CC import ClientDefaults import collections import HydrusConstants as HC +import HydrusPaths import ClientDownloading import os import TestConstants import unittest -import HydrusFileHandling import HydrusGlobals class TestDownloaders( unittest.TestCase ): @@ -27,8 +27,8 @@ class TestDownloaders( unittest.TestCase ): def test_deviantart( self ): - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'da_gallery.html' ) as f: da_gallery = f.read() - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'da_page.html' ) as f: da_page = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'da_gallery.html' ) ) as f: da_gallery = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'da_page.html' ) ) as f: da_page = f.read() HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'http://sakimichan.deviantart.com/gallery/?catpath=/&offset=0', da_gallery ) HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'http://sakimichan.deviantart.com/art/Sailor-moon-in-PJs-506918040', da_page ) @@ -52,7 +52,7 @@ class TestDownloaders( unittest.TestCase ): tags = ['title:Sailor moon in PJs', 'creator:sakimichan'] - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -62,7 +62,7 @@ class TestDownloaders( unittest.TestCase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) info = ( data, tags ) @@ -74,8 +74,8 @@ class TestDownloaders( unittest.TestCase ): def test_newgrounds( self ): - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'newgrounds_gallery_games.html' ) as f: newgrounds_gallery_games = f.read() - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'newgrounds_gallery_movies.html' ) as f: newgrounds_gallery_movies = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'newgrounds_gallery_games.html' ) ) as f: newgrounds_gallery_games = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'newgrounds_gallery_movies.html' ) ) as f: newgrounds_gallery_movies = f.read() HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'http://warlord-of-noodles.newgrounds.com/games/', newgrounds_gallery_games ) HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'http://warlord-of-noodles.newgrounds.com/movies/', newgrounds_gallery_movies ) @@ -105,13 +105,13 @@ class TestDownloaders( unittest.TestCase ): # - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'newgrounds_page.html' ) as f: newgrounds_page = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'newgrounds_page.html' ) ) as f: newgrounds_page = f.read() HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'http://www.newgrounds.com/portal/view/583715', newgrounds_page ) HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'http://uploads.ungrounded.net/583000/583715_catdust.swf', 'swf file' ) - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -123,7 +123,7 @@ class TestDownloaders( unittest.TestCase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) info = ( data, tags ) @@ -135,8 +135,8 @@ class TestDownloaders( unittest.TestCase ): def test_pixiv( self ): - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'pixiv_gallery.html' ) as f: pixiv_gallery = f.read() - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'pixiv_image_page.html' ) as f: pixiv_page = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'pixiv_gallery.html' ) ) as f: pixiv_gallery = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'pixiv_image_page.html' ) ) as f: pixiv_page = f.read() HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'http://www.pixiv.net/search.php?word=naruto&s_mode=s_tag_full&order=date_d&p=1', pixiv_gallery ) HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'http://www.pixiv.net/member_illust.php?mode=medium&illust_id=50926312', pixiv_page ) @@ -159,7 +159,7 @@ class TestDownloaders( unittest.TestCase ): # - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -169,7 +169,7 @@ class TestDownloaders( unittest.TestCase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) info = ( data, tags ) @@ -183,8 +183,8 @@ class TestDownloaders( unittest.TestCase ): def test_sankaku( self ): - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'sankaku_gallery.html' ) as f: sankaku_gallery = f.read() - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'sankaku_page.html' ) as f: sankaku_page = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'sankaku_gallery.html' ) ) as f: sankaku_gallery = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'sankaku_page.html' ) ) as f: sankaku_page = f.read() HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'https://chan.sankakucomplex.com/?tags=animal_ears&page=1', sankaku_gallery ) HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'https://chan.sankakucomplex.com/post/show/4324703', sankaku_page ) @@ -208,7 +208,7 @@ class TestDownloaders( unittest.TestCase ): HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'https://cs.sankakucomplex.com/data/c5/c3/c5c3c91ca68bd7662f546cc44fe0d378.jpg?4324703', 'image file' ) - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -218,7 +218,7 @@ class TestDownloaders( unittest.TestCase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) info = ( data, tags ) @@ -229,12 +229,12 @@ class TestDownloaders( unittest.TestCase ): # flash is tricky for sankaku - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'sankaku_flash.html' ) as f: sankaku_flash = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'sankaku_flash.html' ) ) as f: sankaku_flash = f.read() HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'https://chan.sankakucomplex.com/post/show/4318061', sankaku_flash ) HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'https://cs.sankakucomplex.com/data/48/ce/48cecd707d8a562d47db74d934505f51.swf?4318061', 'swf file' ) - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -244,7 +244,7 @@ class TestDownloaders( unittest.TestCase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) self.assertEqual( data, 'swf file' ) @@ -252,8 +252,8 @@ class TestDownloaders( unittest.TestCase ): def test_booru_e621( self ): - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'e621_gallery.html' ) as f: e621_gallery = f.read() - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'e621_page.html' ) as f: e621_page = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'e621_gallery.html' ) ) as f: e621_gallery = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'e621_page.html' ) ) as f: e621_page = f.read() HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'https://e621.net/post/index/1/hair', e621_gallery ) HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'https://e621.net/post/show/672179/2015-ambiguous_gender-animal_genitalia-anon-balls-', e621_page ) @@ -277,7 +277,7 @@ class TestDownloaders( unittest.TestCase ): HydrusGlobals.test_controller.GetHTTP().SetResponse( HC.GET, 'https://static1.e621.net/data/75/88/758892ccca10cef5d242b9f49a0b2a13.png', 'png file' ) - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -287,7 +287,7 @@ class TestDownloaders( unittest.TestCase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) info = ( data, tags ) @@ -299,10 +299,10 @@ class TestDownloaders( unittest.TestCase ): def test_hentai_foundry( self ): - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'hf_picture_gallery.html' ) as f: picture_gallery = f.read() - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'hf_scrap_gallery.html' ) as f: scrap_gallery = f.read() - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'hf_picture_page.html' ) as f: picture_page = f.read() - with open( HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + 'hf_scrap_page.html' ) as f: scrap_page = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'hf_picture_gallery.html' ) ) as f: picture_gallery = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'hf_scrap_gallery.html' ) ) as f: scrap_gallery = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'hf_picture_page.html' ) ) as f: picture_page = f.read() + with open( os.path.join( HC.STATIC_DIR, 'testing', 'hf_scrap_page.html' ) ) as f: scrap_page = f.read() # what about page/1 or whatever? @@ -345,7 +345,7 @@ class TestDownloaders( unittest.TestCase ): # ask for specific url - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -355,7 +355,7 @@ class TestDownloaders( unittest.TestCase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) info = ( data, tags ) @@ -364,7 +364,7 @@ class TestDownloaders( unittest.TestCase ): self.assertEqual( info, expected_info ) - ( os_file_handle, temp_path ) = HydrusFileHandling.GetTempPath() + ( os_file_handle, temp_path ) = HydrusPaths.GetTempPath() try: @@ -374,7 +374,7 @@ class TestDownloaders( unittest.TestCase ): finally: - HydrusFileHandling.CleanUpTempPath( os_file_handle, temp_path ) + HydrusPaths.CleanUpTempPath( os_file_handle, temp_path ) info = ( data, tags ) diff --git a/include/TestConstants.py b/include/TestConstants.py index 23626fe4..7c1d33e1 100644 --- a/include/TestConstants.py +++ b/include/TestConstants.py @@ -6,7 +6,6 @@ import random import threading import weakref import HydrusData -import HydrusFileHandling tinest_gif = '\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x00\xFF\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x00\x3B' diff --git a/include/TestDB.py b/include/TestDB.py index f49c03c4..e0d099f1 100644 --- a/include/TestDB.py +++ b/include/TestDB.py @@ -53,8 +53,8 @@ class TestClientDB( unittest.TestCase ): HC.DB_DIR = tempfile.mkdtemp() - HC.CLIENT_FILES_DIR = HC.DB_DIR + os.path.sep + 'client_files' - HC.CLIENT_THUMBNAILS_DIR = HC.DB_DIR + os.path.sep + 'client_thumbnails' + HC.CLIENT_FILES_DIR = os.path.join( HC.DB_DIR, 'client_files' ) + HC.CLIENT_THUMBNAILS_DIR = os.path.join( HC.DB_DIR, 'client_thumbnails' ) self._db = ClientDB.DB( HydrusGlobals.test_controller ) @@ -108,7 +108,7 @@ class TestClientDB( unittest.TestCase ): hash = '\xadm5\x99\xa6\xc4\x89\xa5u\xeb\x19\xc0&\xfa\xce\x97\xa9\xcdey\xe7G(\xb0\xce\x94\xa6\x01\xd22\xf3\xc3' - path = HC.STATIC_DIR + os.path.sep + 'hydrus.png' + path = os.path.join( HC.STATIC_DIR, 'hydrus.png' ) self._write( 'import_file', path ) @@ -312,7 +312,7 @@ class TestClientDB( unittest.TestCase ): hash = '\xadm5\x99\xa6\xc4\x89\xa5u\xeb\x19\xc0&\xfa\xce\x97\xa9\xcdey\xe7G(\xb0\xce\x94\xa6\x01\xd22\xf3\xc3' - path = HC.STATIC_DIR + os.path.sep + 'hydrus.png' + path = os.path.join( HC.STATIC_DIR, 'hydrus.png' ) self._write( 'import_file', path ) @@ -540,7 +540,7 @@ class TestClientDB( unittest.TestCase ): hash = '\xadm5\x99\xa6\xc4\x89\xa5u\xeb\x19\xc0&\xfa\xce\x97\xa9\xcdey\xe7G(\xb0\xce\x94\xa6\x01\xd22\xf3\xc3' - path = HC.STATIC_DIR + os.path.sep + 'hydrus.png' + path = os.path.join( HC.STATIC_DIR, 'hydrus.png' ) self._write( 'import_file', path ) @@ -661,7 +661,7 @@ class TestClientDB( unittest.TestCase ): for ( filename, hex_hash, size, mime, width, height, duration, num_frames, num_words ) in test_files: - path = HC.STATIC_DIR + os.path.sep + 'testing' + os.path.sep + filename + path = os.path.join( HC.STATIC_DIR, 'testing', filename ) hash = hex_hash.decode( 'hex' ) @@ -733,7 +733,7 @@ class TestClientDB( unittest.TestCase ): self.assertTrue( os.path.exists( HC.DB_DIR ) ) - self.assertTrue( os.path.exists( HC.DB_DIR + os.path.sep + 'client.db' ) ) + self.assertTrue( os.path.exists( os.path.join( HC.DB_DIR, 'client.db' ) ) ) self.assertTrue( os.path.exists( HC.CLIENT_FILES_DIR ) ) @@ -743,11 +743,11 @@ class TestClientDB( unittest.TestCase ): for ( one, two ) in itertools.product( hex_chars, hex_chars ): - dir = HC.CLIENT_FILES_DIR + os.path.sep + one + two + dir = os.path.join( HC.CLIENT_FILES_DIR, one + two ) self.assertTrue( os.path.exists( dir ) ) - dir = HC.CLIENT_THUMBNAILS_DIR + os.path.sep + one + two + dir = os.path.join( HC.CLIENT_THUMBNAILS_DIR, one + two ) self.assertTrue( os.path.exists( dir ) ) @@ -761,7 +761,7 @@ class TestClientDB( unittest.TestCase ): md5 = 'fdadb2cae78f2dfeb629449cd005f2a2'.decode( 'hex' ) - path = HC.STATIC_DIR + os.path.sep + 'hydrus.png' + path = os.path.join( HC.STATIC_DIR, 'hydrus.png' ) # @@ -800,7 +800,7 @@ class TestClientDB( unittest.TestCase ): self._clear_db() - path = HC.STATIC_DIR + os.path.sep + 'hydrus.png' + path = os.path.join( HC.STATIC_DIR, 'hydrus.png' ) HC.options[ 'exclude_deleted_files' ] = False @@ -1236,8 +1236,8 @@ class TestServerDB( unittest.TestCase ): HC.DB_DIR = tempfile.mkdtemp() - HC.SERVER_FILES_DIR = HC.DB_DIR + os.path.sep + 'server_files' - HC.SERVER_THUMBNAILS_DIR = HC.DB_DIR + os.path.sep + 'server_thumbnails' + HC.SERVER_FILES_DIR = os.path.join( HC.DB_DIR, 'server_files' ) + HC.SERVER_THUMBNAILS_DIR = os.path.join( HC.DB_DIR, 'server_thumbnails' ) self._db = ServerDB.DB( HydrusGlobals.test_controller ) diff --git a/include/TestHydrusImageHandling.py b/include/TestHydrusImageHandling.py index f8879714..6b6213ac 100644 --- a/include/TestHydrusImageHandling.py +++ b/include/TestHydrusImageHandling.py @@ -9,7 +9,7 @@ class TestImageHandling( unittest.TestCase ): def test_phash( self ): - phash = HydrusImageHandling.GeneratePerceptualHash( HC.STATIC_DIR + os.path.sep + 'hydrus.png' ) + phash = HydrusImageHandling.GeneratePerceptualHash( os.path.join( HC.STATIC_DIR, 'hydrus.png' ) ) self.assertEqual( phash, '\xb0\x08\x83\xb2\x08\x0b8\x08' ) diff --git a/include/TestHydrusServer.py b/include/TestHydrusServer.py index e2fafeca..88e8071f 100644 --- a/include/TestHydrusServer.py +++ b/include/TestHydrusServer.py @@ -41,6 +41,9 @@ class TestServer( unittest.TestCase ): services_manager._keys_to_services[ self._tag_service.GetServiceKey() ] = self._tag_service services_manager._keys_to_services[ self._admin_service.GetServiceKey() ] = self._admin_service + os.mkdir( ServerFiles.GetExpectedUpdateDir( self._file_service.GetServiceKey() ) ) + os.mkdir( ServerFiles.GetExpectedUpdateDir( self._tag_service.GetServiceKey() ) ) + permissions = [ HC.GET_DATA, HC.POST_DATA, HC.POST_PETITIONS, HC.RESOLVE_PETITIONS, HC.MANAGE_USERS, HC.GENERAL_ADMIN, HC.EDIT_SERVICES ] account_key = HydrusData.GenerateKey() @@ -69,6 +72,13 @@ class TestServer( unittest.TestCase ): time.sleep( 1 ) + @classmethod + def tearDownClass( self ): + + shutil.rmtree( ServerFiles.GetExpectedUpdateDir( self._file_service.GetServiceKey() ) ) + shutil.rmtree( ServerFiles.GetExpectedUpdateDir( self._tag_service.GetServiceKey() ) ) + + def _test_basics( self, host, port ): connection = httplib.HTTPConnection( host, port, timeout = 10 ) @@ -88,7 +98,7 @@ class TestServer( unittest.TestCase ): # - with open( HC.STATIC_DIR + os.path.sep + 'hydrus.ico', 'rb' ) as f: favicon = f.read() + with open( os.path.join( HC.STATIC_DIR, 'hydrus.ico' ), 'rb' ) as f: favicon = f.read() connection.request( 'GET', '/favicon.ico' ) @@ -157,7 +167,7 @@ class TestServer( unittest.TestCase ): try: os.remove( path ) except: pass - path = HC.STATIC_DIR + os.path.sep + 'hydrus.png' + path = os.path.join( HC.STATIC_DIR, 'hydrus.png' ) with open( path, 'rb' ) as f: file = f.read() @@ -209,7 +219,10 @@ class TestServer( unittest.TestCase ): # - with open( HC.STATIC_DIR + os.path.sep + 'local_booru_style.css', 'rb' ) as f: css = f.read() + with open( os.path.join( HC.STATIC_DIR, 'local_booru_style.css' ), 'rb' ) as f: + + css = f.read() + connection.request( 'GET', '/style.css' ) diff --git a/server.py b/server.py index e1fdacdc..c476dfd2 100644 --- a/server.py +++ b/server.py @@ -46,7 +46,7 @@ try: initial_sys_stdout = sys.stdout initial_sys_stderr = sys.stderr - with open( HC.LOGS_DIR + os.path.sep + 'server.log', 'a' ) as f: + with open( os.path.join( HC.LOGS_DIR, 'server.log' ), 'a' ) as f: class logger( object ): diff --git a/test.py b/test.py index 56cb5d57..833fbbf1 100644 --- a/test.py +++ b/test.py @@ -156,6 +156,11 @@ class Controller( object ): return write + def ModelIsShutdown( self ): + + return HydrusGlobals.model_shutdown + + def Read( self, name, *args, **kwargs ): return self._reads[ name ] def ResetIdleTimer( self ): pass @@ -193,6 +198,11 @@ class Controller( object ): def SetWebCookies( self, name, value ): self._cookies[ name ] = value + def ViewIsShutdown( self ): + + return HydrusGlobals.view_shutdown + + def Write( self, name, *args, **kwargs ): self._writes[ name ].append( ( args, kwargs ) )