Version 180

This commit is contained in:
Hydrus 2015-11-04 16:30:28 -06:00
parent 01ed3ccf00
commit 13d418ded2
53 changed files with 1718 additions and 1307 deletions

View File

@ -28,7 +28,7 @@ try:
initial_sys_stdout = sys.stdout
initial_sys_stderr = sys.stderr
with open( HC.LOGS_DIR + os.path.sep + 'client.log', 'a' ) as f:
with open( os.path.join( HC.LOGS_DIR, 'client.log' ), 'a' ) as f:
sys.stdout = f
sys.stderr = f

View File

@ -8,6 +8,48 @@
<div class="content">
<h3>changelog</h3>
<ul>
<li><h3>version 180</h3></li>
<ul>
<li>middle click on any taglist now does 'open a new search page for selection'</li>
<li>moved mouse idle checking code to the wx thread, which seems to have fixed a serious X11 crash</li>
<li>memory gunk should now be painted over when transparent animations are resized on linux</li>
<li>fixed some page up/down index calculation on the autocomplete dropdown</li>
<li>system predicates will remove themselves from the active predicate list silently again</li>
<li>system predicates will work again in queries that include tags!</li>
<li>greatly improved my string/unicode conversion code</li>
<li>dropped many inefficient unicode conversions from db code</li>
<li>improved the sql-grammar of some specifically efficient db code</li>
<li>removed incorrect unicode conversions from url/network request code</li>
<li>removed unicode conversion code from network response code</li>
<li>all directory iteration should now occur in unicode</li>
<li>all inputted paths should now be converted to unicode</li>
<li>replaced every single ugly raw path concatenation with a better method</li>
<li>improved some bitmap placeholder initialisation that was causing Linux terminal spam</li>
<li>added an option to always hide the preview window to options->gui</li>
<li>the preview window will not accept setmedia calls if it is hidden</li>
<li>if the preview window is actively hidden due to an unsplitting event, it will null its current media</li>
<li>fixed a shutdown calculation that was under-remembering the height of the preview window by four pixels every time</li>
<li>improved thumbnail waterfall code--it should be a little faster. less subject to lag when taxed, and waterfall with more genuine randomness</li>
<li>improved some thumbnail page drawing and clean/dirty conversion code</li>
<li>when pages are dirtied, any to-be-waterfalled thumbnails are cancelled, making superfast scrolling less crashtastic</li>
<li>new dirty thumbnail pages are now generated as needed, rather than precached</li>
<li>subscriptions will now correctly do a polite wait after fetching tags for redundant files</li>
<li>splash screen will now explicitly raise itself to the front on init</li>
<li>the export tag txts function of the export dialog now exports the tag txt to [filename].jpg.txt, rather than [filename].txt</li>
<li>the server now stores its updates in service specific subdirectories, like the client</li>
<li>some importers will better report when they are waiting politely</li>
<li>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)</li>
<li>'open externally' from thumbnails now defocusses the preview window</li>
<li>refactored away a bunch of bad global controller references</li>
<li>added some shutdownexceptions</li>
<li>silenced shutdownexception terminal spam</li>
<li>reworded the 'maintenace and processing' options panel a little to explain things better</li>
<li>improved how the base_dir is figured out on program boot</li>
<li>improved serverside 'should I clean dirty updates?' check code</li>
<li>deleted some old code</li>
<li>split path-specific functions off from HydrusFileHandling to HydrusPaths and de-looped my import tree appropriately</li>
<li>general refactoring</li>
</ul>
<li><h3>version 179</h3></li>
<ul>
<li>all tag listboxes support multiple selection</li>

View File

@ -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:

View File

@ -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'

View File

@ -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:

View File

@ -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 )

View File

@ -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:

View File

@ -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 )

View File

@ -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 = []

View File

@ -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 ):

View File

@ -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 )

File diff suppressed because it is too large Load Diff

View File

@ -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()

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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' )

View File

@ -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 ) )

View File

@ -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:

View File

@ -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' ] )

View File

@ -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 ):

View File

@ -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 )

View File

@ -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

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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 ) )

View File

@ -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()

View File

@ -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 ):

View File

@ -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()

View File

@ -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 )

View File

@ -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 )

View File

@ -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 ) )

132
include/HydrusPaths.py Normal file
View File

@ -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 )

View File

@ -101,7 +101,7 @@ eris = '''<html><head><title>hydrus</title></head><body><pre>
<font color="gray">MM</font>:::::<font color="gray">M</font>:::::::::::::::::::::<font color="gray">MMM</font>
<font color="gray">MM</font>::::<font color="gray">M</font>::::::::::::::::::::<font color="gray">MMM</font>
<font color="gray">MM</font>:::<font color="gray">M</font>::::::::::::::::::::<font color="gray">MMM</font>
<font color="gray">MM</font>::<font color="gray">M</font>:::::::::::::::::::<font color="gray">MMM</font> THIS IS THE HYDRUS SERVER ADMIN SERVICE, VERSION ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + '''
<font color="gray">MM</font>::<font color="gray">M</font>:::::::::::::::::::<font color="gray">MMM</font> THIS IS THE HYDRUS SERVER ADMIN SERVICE, VERSION ''' + str( HC.SOFTWARE_VERSION ) + '''
<font color="gray">MM</font>:<font color="gray">M</font>:::::::::::::::::::<font color="gray">MMM</font>
<font color="gray">MMM</font>::::::::::::::::::<font color="gray">MMM</font>
<font color="gray">MM</font>::::::::::::::::::<font color="gray">MMM</font>
@ -173,7 +173,7 @@ CLIENT_ROOT_MESSAGE = '''<html>
<title>hydrus client</title>
</head>
<body>
<p>This hydrus client uses software version ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' and network version ''' + HydrusData.ToString( HC.NETWORK_VERSION ) + '''.</p>
<p>This hydrus client uses software version ''' + str( HC.SOFTWARE_VERSION ) + ''' and network version ''' + str( HC.NETWORK_VERSION ) + '''.</p>
<p>It only serves requests from 127.0.0.1.</p>
</body>
</html>'''
@ -183,7 +183,7 @@ ROOT_MESSAGE_BEGIN = '''<html>
<title>hydrus service</title>
</head>
<body>
<p>This hydrus service uses software version ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' and network version ''' + HydrusData.ToString( HC.NETWORK_VERSION ) + '''.</p>
<p>This hydrus service uses software version ''' + str( HC.SOFTWARE_VERSION ) + ''' and network version ''' + str( HC.NETWORK_VERSION ) + '''.</p>
<p>'''
ROOT_MESSAGE_END = '''</p>

View File

@ -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 )

View File

@ -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 = '''<html>
<title>hydrus client</title>
</head>
<body>
<p>This hydrus client uses software version ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' and network version ''' + HydrusData.ToString( HC.NETWORK_VERSION ) + '''.</p>
<p>This hydrus client uses software version ''' + str( HC.SOFTWARE_VERSION ) + ''' and network version ''' + str( HC.NETWORK_VERSION ) + '''.</p>
<p>It only serves requests from 127.0.0.1.</p>
</body>
</html>'''
@ -33,7 +34,7 @@ ROOT_MESSAGE_BEGIN = '''<html>
<title>hydrus service</title>
</head>
<body>
<p>This hydrus service uses software version ''' + HydrusData.ToString( HC.SOFTWARE_VERSION ) + ''' and network version ''' + HydrusData.ToString( HC.NETWORK_VERSION ) + '''.</p>
<p>This hydrus service uses software version ''' + str( HC.SOFTWARE_VERSION ) + ''' and network version ''' + str( HC.NETWORK_VERSION ) + '''.</p>
<p>'''
ROOT_MESSAGE_END = '''</p>
@ -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

View File

@ -113,7 +113,7 @@ def CleanTag( tag ):
tag = tag.lower()
tag = HydrusData.ToString( tag )
tag = HydrusData.ToUnicode( tag )
tag.replace( '\r', '' )
tag.replace( '\n', '' )

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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, ) )

View File

@ -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:

View File

@ -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 )

View File

@ -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:

View File

@ -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 )

View File

@ -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'

View File

@ -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 )

View File

@ -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' )

View File

@ -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' )

View File

@ -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 ):

10
test.py
View File

@ -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 ) )