hydrus/hydrus/core/HydrusSerialisable.py

593 lines
21 KiB
Python
Raw Normal View History

2015-04-22 22:57:25 +00:00
import json
2021-01-20 22:22:03 +00:00
import os
2017-01-25 22:56:55 +00:00
import zlib
2015-04-22 22:57:25 +00:00
2018-01-17 22:52:10 +00:00
LZ4_OK = False
try:
2018-08-22 21:10:59 +00:00
import lz4
2018-01-17 22:52:10 +00:00
import lz4.block
LZ4_OK = True
2018-07-18 21:07:15 +00:00
except: # ImportError wasn't enough here as Linux went up the shoot with a __version__ doesn't exist bs
2018-01-17 22:52:10 +00:00
2018-10-24 21:34:02 +00:00
print( 'Could not import lz4--nbd.' )
2018-01-17 22:52:10 +00:00
2020-07-29 20:52:44 +00:00
from hydrus.core import HydrusData
2021-01-20 22:22:03 +00:00
from hydrus.core import HydrusExceptions
2020-07-29 20:52:44 +00:00
2015-04-22 22:57:25 +00:00
SERIALISABLE_TYPE_BASE = 0
SERIALISABLE_TYPE_BASE_NAMED = 1
2019-06-05 19:42:39 +00:00
SERIALISABLE_TYPE_SHORTCUT_SET = 2
2020-06-11 12:01:08 +00:00
SERIALISABLE_TYPE_SUBSCRIPTION_LEGACY = 3
2015-05-13 20:22:39 +00:00
SERIALISABLE_TYPE_PERIODIC = 4
2015-10-07 21:56:22 +00:00
SERIALISABLE_TYPE_GALLERY_IDENTIFIER = 5
2017-09-20 19:47:31 +00:00
SERIALISABLE_TYPE_TAG_IMPORT_OPTIONS = 6
SERIALISABLE_TYPE_FILE_IMPORT_OPTIONS = 7
2018-06-27 19:27:05 +00:00
SERIALISABLE_TYPE_FILE_SEED_CACHE = 8
2015-05-20 21:31:40 +00:00
SERIALISABLE_TYPE_HDD_IMPORT = 9
2015-06-03 21:05:13 +00:00
SERIALISABLE_TYPE_SERVER_TO_CLIENT_CONTENT_UPDATE_PACKAGE = 10
SERIALISABLE_TYPE_SERVER_TO_CLIENT_SERVICE_UPDATE_PACKAGE = 11
2015-06-17 20:01:41 +00:00
SERIALISABLE_TYPE_MANAGEMENT_CONTROLLER = 12
2015-06-24 22:10:14 +00:00
SERIALISABLE_TYPE_GUI_SESSION = 13
SERIALISABLE_TYPE_PREDICATE = 14
SERIALISABLE_TYPE_FILE_SEARCH_CONTEXT = 15
SERIALISABLE_TYPE_EXPORT_FOLDER = 16
2018-05-23 21:05:06 +00:00
SERIALISABLE_TYPE_WATCHER_IMPORT = 17
2018-04-05 01:22:26 +00:00
SERIALISABLE_TYPE_SIMPLE_DOWNLOADER_IMPORT = 18
2015-09-09 22:04:39 +00:00
SERIALISABLE_TYPE_IMPORT_FOLDER = 19
2018-07-18 21:07:15 +00:00
SERIALISABLE_TYPE_MULTIPLE_GALLERY_IMPORT = 20
2015-10-07 21:56:22 +00:00
SERIALISABLE_TYPE_DICTIONARY = 21
SERIALISABLE_TYPE_CLIENT_OPTIONS = 22
2015-10-14 21:02:25 +00:00
SERIALISABLE_TYPE_CONTENT = 23
2017-03-02 02:14:56 +00:00
SERIALISABLE_TYPE_PETITION = 24
2015-10-14 21:02:25 +00:00
SERIALISABLE_TYPE_ACCOUNT_IDENTIFIER = 25
SERIALISABLE_TYPE_LIST = 26
2016-09-21 19:54:04 +00:00
SERIALISABLE_TYPE_PARSE_FORMULA_HTML = 27
2016-09-07 20:01:05 +00:00
SERIALISABLE_TYPE_URLS_IMPORT = 28
2016-10-05 20:22:40 +00:00
SERIALISABLE_TYPE_PARSE_NODE_CONTENT_LINK = 29
2017-12-13 22:33:07 +00:00
SERIALISABLE_TYPE_CONTENT_PARSER = 30
2016-09-21 19:54:04 +00:00
SERIALISABLE_TYPE_PARSE_FORMULA_JSON = 31
2016-10-05 20:22:40 +00:00
SERIALISABLE_TYPE_PARSE_ROOT_FILE_LOOKUP = 32
2017-03-02 02:14:56 +00:00
SERIALISABLE_TYPE_BYTES_DICT = 33
SERIALISABLE_TYPE_CONTENT_UPDATE = 34
SERIALISABLE_TYPE_CREDENTIALS = 35
SERIALISABLE_TYPE_DEFINITIONS_UPDATE = 36
SERIALISABLE_TYPE_METADATA = 37
SERIALISABLE_TYPE_BANDWIDTH_RULES = 38
SERIALISABLE_TYPE_BANDWIDTH_TRACKER = 39
SERIALISABLE_TYPE_CLIENT_TO_SERVER_UPDATE = 40
2017-04-12 21:46:46 +00:00
SERIALISABLE_TYPE_SHORTCUT = 41
SERIALISABLE_TYPE_APPLICATION_COMMAND = 42
2017-04-26 21:58:12 +00:00
SERIALISABLE_TYPE_DUPLICATE_ACTION_OPTIONS = 43
2018-04-25 22:07:52 +00:00
SERIALISABLE_TYPE_TAG_FILTER = 44
2021-01-13 21:48:58 +00:00
SERIALISABLE_TYPE_NETWORK_BANDWIDTH_MANAGER_LEGACY = 45
SERIALISABLE_TYPE_NETWORK_SESSION_MANAGER_LEGACY = 46
2017-06-28 20:23:21 +00:00
SERIALISABLE_TYPE_NETWORK_CONTEXT = 47
SERIALISABLE_TYPE_NETWORK_LOGIN_MANAGER = 48
2017-08-09 21:33:51 +00:00
SERIALISABLE_TYPE_MEDIA_SORT = 49
2019-05-08 21:06:42 +00:00
SERIALISABLE_TYPE_URL_CLASS = 50
2017-09-27 21:52:54 +00:00
SERIALISABLE_TYPE_STRING_MATCH = 51
2017-11-08 22:07:12 +00:00
SERIALISABLE_TYPE_CHECKER_OPTIONS = 52
2017-10-04 17:51:58 +00:00
SERIALISABLE_TYPE_NETWORK_DOMAIN_MANAGER = 53
2020-06-11 12:01:08 +00:00
SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LEGACY = 54
2017-11-15 22:35:49 +00:00
SERIALISABLE_TYPE_STRING_CONVERTER = 55
SERIALISABLE_TYPE_FILENAME_TAGGING_OPTIONS = 56
2018-06-27 19:27:05 +00:00
SERIALISABLE_TYPE_FILE_SEED = 57
2017-12-13 22:33:07 +00:00
SERIALISABLE_TYPE_PAGE_PARSER = 58
2018-01-31 22:58:15 +00:00
SERIALISABLE_TYPE_PARSE_FORMULA_COMPOUND = 59
2018-02-07 23:40:33 +00:00
SERIALISABLE_TYPE_PARSE_FORMULA_CONTEXT_VARIABLE = 60
2018-02-21 21:59:37 +00:00
SERIALISABLE_TYPE_TAG_SUMMARY_GENERATOR = 61
2018-04-11 22:30:40 +00:00
SERIALISABLE_TYPE_PARSE_RULE_HTML = 62
SERIALISABLE_TYPE_SIMPLE_DOWNLOADER_PARSE_FORMULA = 63
2018-05-16 20:09:50 +00:00
SERIALISABLE_TYPE_MULTIPLE_WATCHER_IMPORT = 64
2018-06-27 19:27:05 +00:00
SERIALISABLE_TYPE_SERVICE_TAG_IMPORT_OPTIONS = 65
SERIALISABLE_TYPE_GALLERY_SEED = 66
SERIALISABLE_TYPE_GALLERY_SEED_LOG = 67
2018-07-18 21:07:15 +00:00
SERIALISABLE_TYPE_GALLERY_IMPORT = 68
2018-08-22 21:10:59 +00:00
SERIALISABLE_TYPE_GALLERY_URL_GENERATOR = 69
SERIALISABLE_TYPE_NESTED_GALLERY_URL_GENERATOR = 70
2018-10-03 21:00:15 +00:00
SERIALISABLE_TYPE_DOMAIN_METADATA_PACKAGE = 71
2018-10-17 21:00:09 +00:00
SERIALISABLE_TYPE_LOGIN_CREDENTIAL_DEFINITION = 72
SERIALISABLE_TYPE_LOGIN_SCRIPT_DOMAIN = 73
SERIALISABLE_TYPE_LOGIN_STEP = 74
2019-01-23 22:19:16 +00:00
SERIALISABLE_TYPE_CLIENT_API_MANAGER = 75
SERIALISABLE_TYPE_CLIENT_API_PERMISSIONS = 76
2019-02-27 23:03:30 +00:00
SERIALISABLE_TYPE_SERVICE_KEYS_TO_TAGS = 77
2019-08-21 21:34:01 +00:00
SERIALISABLE_TYPE_MEDIA_COLLECT = 78
2019-10-02 23:38:59 +00:00
SERIALISABLE_TYPE_TAG_DISPLAY_MANAGER = 79
2020-03-11 21:52:11 +00:00
SERIALISABLE_TYPE_TAG_SEARCH_CONTEXT = 80
SERIALISABLE_TYPE_FAVOURITE_SEARCH_MANAGER = 81
2020-05-06 21:31:41 +00:00
SERIALISABLE_TYPE_NOTE_IMPORT_OPTIONS = 82
2020-05-13 19:03:16 +00:00
SERIALISABLE_TYPE_STRING_SPLITTER = 83
SERIALISABLE_TYPE_STRING_PROCESSOR = 84
2020-05-20 21:36:02 +00:00
SERIALISABLE_TYPE_TAG_AUTOCOMPLETE_OPTIONS = 85
2020-06-11 12:01:08 +00:00
SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LOG_CONTAINER = 86
SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_HEADER = 87
SERIALISABLE_TYPE_SUBSCRIPTION = 88
SERIALISABLE_TYPE_FILE_SEED_CACHE_STATUS = 89
2020-06-17 21:31:54 +00:00
SERIALISABLE_TYPE_SUBSCRIPTION_CONTAINER = 90
2020-07-15 20:52:09 +00:00
SERIALISABLE_TYPE_COLUMN_LIST_STATUS = 91
SERIALISABLE_TYPE_COLUMN_LIST_MANAGER = 92
2020-07-22 20:59:16 +00:00
SERIALISABLE_TYPE_NUMBER_TEST = 93
2021-01-13 21:48:58 +00:00
SERIALISABLE_TYPE_NETWORK_BANDWIDTH_MANAGER = 94
SERIALISABLE_TYPE_NETWORK_SESSION_MANAGER = 95
SERIALISABLE_TYPE_NETWORK_SESSION_MANAGER_SESSION_CONTAINER = 96
SERIALISABLE_TYPE_NETWORK_BANDWIDTH_MANAGER_TRACKER_CONTAINER = 97
2021-02-17 18:22:44 +00:00
SERIALISABLE_TYPE_SIDECAR_EXPORTER = 98
2021-03-03 22:23:35 +00:00
SERIALISABLE_TYPE_STRING_SORTER = 99
2021-03-10 23:10:11 +00:00
SERIALISABLE_TYPE_STRING_SLICER = 100
SERIALISABLE_TYPE_TAG_SORT = 101
2015-04-22 22:57:25 +00:00
SERIALISABLE_TYPES_TO_OBJECT_TYPES = {}
2021-01-20 22:22:03 +00:00
def CreateFromNetworkBytes( network_string, raise_error_on_future_version = False ):
2015-05-13 20:22:39 +00:00
2017-01-25 22:56:55 +00:00
try:
2019-01-09 22:59:03 +00:00
obj_bytes = zlib.decompress( network_string )
2017-01-25 22:56:55 +00:00
except zlib.error:
2018-01-17 22:52:10 +00:00
if LZ4_OK:
2019-01-09 22:59:03 +00:00
obj_bytes = lz4.block.decompress( network_string )
2018-01-17 22:52:10 +00:00
else:
raise
2017-01-25 22:56:55 +00:00
2015-06-03 21:05:13 +00:00
2019-01-09 22:59:03 +00:00
obj_string = str( obj_bytes, 'utf-8' )
2021-01-20 22:22:03 +00:00
return CreateFromString( obj_string, raise_error_on_future_version = raise_error_on_future_version )
2015-06-03 21:05:13 +00:00
2021-01-20 22:22:03 +00:00
def CreateFromNoneableSerialisableTuple( obj_tuple_or_none, raise_error_on_future_version = False ):
2020-06-11 12:01:08 +00:00
if obj_tuple_or_none is None:
return None
else:
2021-01-20 22:22:03 +00:00
return CreateFromSerialisableTuple( obj_tuple_or_none, raise_error_on_future_version = raise_error_on_future_version )
2020-06-11 12:01:08 +00:00
2021-01-20 22:22:03 +00:00
def CreateFromString( obj_string, raise_error_on_future_version = False ):
2015-06-03 21:05:13 +00:00
obj_tuple = json.loads( obj_string )
2021-01-20 22:22:03 +00:00
return CreateFromSerialisableTuple( obj_tuple, raise_error_on_future_version = raise_error_on_future_version )
2015-06-03 21:05:13 +00:00
2021-01-20 22:22:03 +00:00
def CreateFromSerialisableTuple( obj_tuple, raise_error_on_future_version = False ):
2015-06-03 21:05:13 +00:00
if len( obj_tuple ) == 3:
2015-06-24 22:10:14 +00:00
( serialisable_type, version, serialisable_info ) = obj_tuple
2015-06-03 21:05:13 +00:00
obj = SERIALISABLE_TYPES_TO_OBJECT_TYPES[ serialisable_type ]()
else:
2015-06-24 22:10:14 +00:00
( serialisable_type, name, version, serialisable_info ) = obj_tuple
2015-06-03 21:05:13 +00:00
obj = SERIALISABLE_TYPES_TO_OBJECT_TYPES[ serialisable_type ]( name )
2015-05-13 20:22:39 +00:00
2021-01-20 22:22:03 +00:00
obj.InitialiseFromSerialisableInfo( version, serialisable_info, raise_error_on_future_version = raise_error_on_future_version )
2015-05-13 20:22:39 +00:00
return obj
2015-06-03 21:05:13 +00:00
2020-06-11 12:01:08 +00:00
def GetNoneableSerialisableTuple( obj_or_none ):
if obj_or_none is None:
return None
else:
return obj_or_none.GetSerialisableTuple()
2018-04-11 22:30:40 +00:00
def SetNonDupeName( obj, disallowed_names ):
2020-03-11 21:52:11 +00:00
non_dupe_name = HydrusData.GetNonDupeName( obj.GetName(), disallowed_names )
2018-04-11 22:30:40 +00:00
obj.SetName( non_dupe_name )
2021-01-20 22:22:03 +00:00
def ObjectVersionIsFromTheFuture( obj_tuple ):
if len( obj_tuple ) == 3:
( serialisable_type, version, serialisable_info ) = obj_tuple
else:
( serialisable_type, name, version, serialisable_info ) = obj_tuple
return SERIALISABLE_TYPES_TO_OBJECT_TYPES[ serialisable_type ].SERIALISABLE_VERSION > version
2015-04-22 22:57:25 +00:00
class SerialisableBase( object ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_BASE
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Base Serialisable Object'
2015-06-03 21:05:13 +00:00
SERIALISABLE_VERSION = 1
2015-04-22 22:57:25 +00:00
def _GetSerialisableInfo( self ):
raise NotImplementedError()
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
raise NotImplementedError()
2015-07-22 19:40:39 +00:00
def _UpdateSerialisableInfo( self, version, old_serialisable_info ):
2015-04-22 22:57:25 +00:00
2015-07-22 19:40:39 +00:00
return old_serialisable_info
2015-04-22 22:57:25 +00:00
2016-07-20 19:57:10 +00:00
2019-01-09 22:59:03 +00:00
def DumpToNetworkBytes( self ):
2015-10-14 21:02:25 +00:00
obj_string = self.DumpToString()
2019-01-09 22:59:03 +00:00
obj_bytes = bytes( obj_string, 'utf-8' )
return zlib.compress( obj_bytes, 9 )
2015-10-14 21:02:25 +00:00
2015-04-22 22:57:25 +00:00
2015-10-14 21:02:25 +00:00
def DumpToString( self ):
2015-04-22 22:57:25 +00:00
2015-10-14 21:02:25 +00:00
obj_tuple = self.GetSerialisableTuple()
2015-04-22 22:57:25 +00:00
2015-10-14 21:02:25 +00:00
return json.dumps( obj_tuple )
2015-04-22 22:57:25 +00:00
2016-10-05 20:22:40 +00:00
def Duplicate( self ):
return CreateFromString( self.DumpToString() )
2015-10-14 21:02:25 +00:00
def GetSerialisableTuple( self ):
2015-04-22 22:57:25 +00:00
2019-02-06 22:41:35 +00:00
if hasattr( self, '_lock' ):
with getattr( self, '_lock' ):
serialisable_info = self._GetSerialisableInfo()
else:
serialisable_info = self._GetSerialisableInfo()
return ( self.SERIALISABLE_TYPE, self.SERIALISABLE_VERSION, serialisable_info )
2015-05-13 20:22:39 +00:00
2021-01-20 22:22:03 +00:00
def InitialiseFromSerialisableInfo( self, version, serialisable_info, raise_error_on_future_version = False ):
if version > self.SERIALISABLE_VERSION:
if raise_error_on_future_version:
message = 'Unfortunately, an object of type {} could not be loaded because it was created in a client that uses an updated version of that object! This client supports versions up to {}, but the object was version {}.'.format( self.SERIALISABLE_NAME, self.SERIALISABLE_VERSION, version )
message += os.linesep * 2
message += 'Please update your client to import this object.'
raise HydrusExceptions.SerialisationException( message )
else:
message = 'An object of type {} was created in a client that uses an updated version of that object! This client supports versions up to {}, but the object was version {}. For now, the client will try to continue work, but things may break. If you know why this has occured, please correct it. If you do not, please let hydrus dev know.'.format( self.SERIALISABLE_NAME, self.SERIALISABLE_VERSION, version )
HydrusData.ShowText( message )
2015-04-22 22:57:25 +00:00
2015-07-22 19:40:39 +00:00
while version < self.SERIALISABLE_VERSION:
2015-04-22 22:57:25 +00:00
2015-07-22 19:40:39 +00:00
( version, serialisable_info ) = self._UpdateSerialisableInfo( version, serialisable_info )
2015-04-22 22:57:25 +00:00
self._InitialiseFromSerialisableInfo( serialisable_info )
class SerialisableBaseNamed( SerialisableBase ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_BASE_NAMED
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Named Base Serialisable Object'
2015-04-22 22:57:25 +00:00
def __init__( self, name ):
SerialisableBase.__init__( self )
self._name = name
2015-10-14 21:02:25 +00:00
def GetSerialisableTuple( self ):
return ( self.SERIALISABLE_TYPE, self._name, self.SERIALISABLE_VERSION, self._GetSerialisableInfo() )
2016-07-20 19:57:10 +00:00
2015-04-22 22:57:25 +00:00
def GetName( self ): return self._name
def SetName( self, name ): self._name = name
2015-10-07 21:56:22 +00:00
2017-08-09 21:33:51 +00:00
def SetNonDupeName( self, disallowed_names ):
2020-03-11 21:52:11 +00:00
self._name = HydrusData.GetNonDupeName( self._name, disallowed_names )
2017-08-09 21:33:51 +00:00
2015-10-07 21:56:22 +00:00
class SerialisableDictionary( SerialisableBase, dict ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_DICTIONARY
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Serialisable Dictionary'
2015-10-07 21:56:22 +00:00
SERIALISABLE_VERSION = 1
def __init__( self, *args, **kwargs ):
dict.__init__( self, *args, **kwargs )
SerialisableBase.__init__( self )
def _GetSerialisableInfo( self ):
simple_key_simple_value_pairs = []
simple_key_serialisable_value_pairs = []
serialisable_key_simple_value_pairs = []
serialisable_key_serialisable_value_pairs = []
2020-07-15 20:52:09 +00:00
for ( key, value ) in self.items():
2015-10-07 21:56:22 +00:00
if isinstance( key, SerialisableBase ):
2015-10-14 21:02:25 +00:00
serialisable_key = key.GetSerialisableTuple()
2015-10-07 21:56:22 +00:00
if isinstance( value, SerialisableBase ):
2015-10-14 21:02:25 +00:00
serialisable_value = value.GetSerialisableTuple()
2015-10-07 21:56:22 +00:00
serialisable_key_serialisable_value_pairs.append( ( serialisable_key, serialisable_value ) )
else:
serialisable_value = value
serialisable_key_simple_value_pairs.append( ( serialisable_key, serialisable_value ) )
else:
serialisable_key = key
if isinstance( value, SerialisableBase ):
2015-10-14 21:02:25 +00:00
serialisable_value = value.GetSerialisableTuple()
2015-10-07 21:56:22 +00:00
simple_key_serialisable_value_pairs.append( ( serialisable_key, serialisable_value ) )
else:
serialisable_value = value
simple_key_simple_value_pairs.append( ( serialisable_key, serialisable_value ) )
return ( simple_key_simple_value_pairs, simple_key_serialisable_value_pairs, serialisable_key_simple_value_pairs, serialisable_key_serialisable_value_pairs )
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
2021-01-20 22:22:03 +00:00
have_shown_load_error = False
2015-10-07 21:56:22 +00:00
( simple_key_simple_value_pairs, simple_key_serialisable_value_pairs, serialisable_key_simple_value_pairs, serialisable_key_serialisable_value_pairs ) = serialisable_info
for ( key, value ) in simple_key_simple_value_pairs:
self[ key ] = value
for ( key, serialisable_value ) in simple_key_serialisable_value_pairs:
2021-01-20 22:22:03 +00:00
try:
value = CreateFromSerialisableTuple( serialisable_value )
except HydrusExceptions.SerialisationException as e:
if not have_shown_load_error:
HydrusData.ShowText( 'An object in a dictionary could not load. It has been discarded from the dictionary. More may also have failed to load, but to stop error spam, they will go silently. Your client may be running on code versions behind its database. Depending on the severity of this error, you may need to rollback to a previous backup. If you have no backup, you may want to kill your hydrus process now to stop the cleansed dictionary being saved back to the db.' )
HydrusData.ShowException( e )
have_shown_load_error = True
continue
2015-10-07 21:56:22 +00:00
self[ key ] = value
for ( serialisable_key, value ) in serialisable_key_simple_value_pairs:
2021-01-20 22:22:03 +00:00
try:
key = CreateFromSerialisableTuple( serialisable_key )
except HydrusExceptions.SerialisationException as e:
if not have_shown_load_error:
HydrusData.ShowText( 'An object in a dictionary could not load. It has been discarded from the dictionary. More may also have failed to load, but to stop error spam, they will go silently. Your client may be running on code versions behind its database. Depending on the severity of this error, you may need to rollback to a previous backup. If you have no backup, you may want to kill your hydrus process now to stop the cleansed dictionary being saved back to the db.' )
HydrusData.ShowException( e )
have_shown_load_error = True
continue
2015-10-07 21:56:22 +00:00
self[ key ] = value
for ( serialisable_key, serialisable_value ) in serialisable_key_serialisable_value_pairs:
2021-01-20 22:22:03 +00:00
try:
key = CreateFromSerialisableTuple( serialisable_key )
value = CreateFromSerialisableTuple( serialisable_value )
except HydrusExceptions.SerialisationException as e:
if not have_shown_load_error:
HydrusData.ShowText( 'An object in a dictionary could not load. It has been discarded from the dictionary. More may also have failed to load, but to stop error spam, they will go silently. Your client may be running on code versions behind its database. Depending on the severity of this error, you may need to rollback to a previous backup. If you have no backup, you may want to kill your hydrus process now to stop the cleansed dictionary being saved back to the db.' )
HydrusData.ShowException( e )
have_shown_load_error = True
continue
2015-10-07 21:56:22 +00:00
self[ key ] = value
2015-10-14 21:02:25 +00:00
SERIALISABLE_TYPES_TO_OBJECT_TYPES[ SERIALISABLE_TYPE_DICTIONARY ] = SerialisableDictionary
2017-03-02 02:14:56 +00:00
class SerialisableBytesDictionary( SerialisableBase, dict ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_BYTES_DICT
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Serialisable Dictionary With Bytestring Key/Value Support'
2017-03-02 02:14:56 +00:00
SERIALISABLE_VERSION = 1
def __init__( self, *args, **kwargs ):
dict.__init__( self, *args, **kwargs )
SerialisableBase.__init__( self )
def _GetSerialisableInfo( self ):
pairs = []
2019-01-09 22:59:03 +00:00
for ( key, value ) in list(self.items()):
2017-03-02 02:14:56 +00:00
2017-03-15 20:13:04 +00:00
if isinstance( key, int ):
encoded_key = key
else:
2019-01-09 22:59:03 +00:00
encoded_key = key.hex()
2017-03-15 20:13:04 +00:00
2017-03-02 02:14:56 +00:00
if isinstance( value, ( list, tuple, set ) ):
2019-01-09 22:59:03 +00:00
encoded_value = [ item.hex() for item in value ]
2017-03-02 02:14:56 +00:00
2017-12-06 22:06:56 +00:00
elif value is None:
encoded_value = value
2017-03-02 02:14:56 +00:00
else:
2019-01-09 22:59:03 +00:00
encoded_value = value.hex()
2017-03-02 02:14:56 +00:00
pairs.append( ( encoded_key, encoded_value ) )
return pairs
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
for ( encoded_key, encoded_value ) in serialisable_info:
2017-03-15 20:13:04 +00:00
if isinstance( encoded_key, int ):
key = encoded_key
else:
2019-01-09 22:59:03 +00:00
key = bytes.fromhex( encoded_key )
2017-03-15 20:13:04 +00:00
2017-03-02 02:14:56 +00:00
if isinstance( encoded_value, ( list, tuple, set ) ):
2019-01-09 22:59:03 +00:00
value = [ bytes.fromhex( encoded_item ) for encoded_item in encoded_value ]
2017-03-02 02:14:56 +00:00
2017-12-06 22:06:56 +00:00
elif encoded_value is None:
value = encoded_value
2017-03-02 02:14:56 +00:00
else:
2019-01-09 22:59:03 +00:00
value = bytes.fromhex( encoded_value )
2017-03-02 02:14:56 +00:00
self[ key ] = value
SERIALISABLE_TYPES_TO_OBJECT_TYPES[ SERIALISABLE_TYPE_BYTES_DICT ] = SerialisableBytesDictionary
2015-10-14 21:02:25 +00:00
class SerialisableList( SerialisableBase, list ):
SERIALISABLE_TYPE = SERIALISABLE_TYPE_LIST
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = 'Serialisable List'
2015-10-14 21:02:25 +00:00
SERIALISABLE_VERSION = 1
def __init__( self, *args, **kwargs ):
list.__init__( self, *args, **kwargs )
SerialisableBase.__init__( self )
def _GetSerialisableInfo( self ):
return [ obj.GetSerialisableTuple() for obj in self ]
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
2021-01-20 22:22:03 +00:00
have_shown_load_error = False
2015-10-14 21:02:25 +00:00
for obj_tuple in serialisable_info:
2021-01-20 22:22:03 +00:00
try:
obj = CreateFromSerialisableTuple( obj_tuple )
except HydrusExceptions.SerialisationException as e:
if not have_shown_load_error:
HydrusData.ShowText( 'An object in a list could not load. It has been discarded from the list. More may also have failed to load, but to stop error spam, they will go silently. Your client may be running on code versions behind its database. Depending on the severity of this error, you may need to rollback to a previous backup. If you have no backup, you may want to kill your hydrus process now to stop the cleansed list being saved back to the db.' )
HydrusData.ShowException( e )
have_shown_load_error = True
continue
self.append( obj )
2015-10-14 21:02:25 +00:00
2017-01-25 22:56:55 +00:00
SERIALISABLE_TYPES_TO_OBJECT_TYPES[ SERIALISABLE_TYPE_LIST ] = SerialisableList