@@ -72,98 +72,76 @@ def load_pickle(fp):
7272 return None
7373
7474
75- def testfile(dbfile, verbose=False, listname=None):
76- # Use our safe loader
77- loadfunc = load_pickle
78- if dbfile.endswith('.db') or dbfile.endswith('.db.last'):
79- loadfunc = marshal.load
80- elif dbfile.endswith('.pck') or dbfile.endswith('.pck.last'):
81- loadfunc = load_pickle
82- else:
83- assert 0
84- if verbose:
85- print('Processing file: %s' % dbfile)
86- print(' File type: %s' % ('marshal' if dbfile.endswith('.db') else 'pickle'))
87- print(' File size: %d bytes' % os.path.getsize(dbfile))
88- fp = open(dbfile, 'rb')
75+ def testfile(dbfile, listname=None, verbose=0):
76+ """Test the integrity of a list's config database file."""
8977 try:
90- data = loadfunc(fp)
9178 if verbose:
92- print(' Successfully loaded data')
93- if isinstance(data, dict):
94- print(' Number of entries: %d' % len(data))
95- if 'version' in data:
96- print(' Database version: %s' % data['version'])
97- # Add detailed debugging for request.pck files
98- if dbfile.endswith('request.pck'):
99- print(' Request data structure:')
100- for key, value in data.items():
101- print(' Key: %s' % key)
102- print(' Value type: %s' % type(value))
103- if isinstance(value, (str, bytes)):
104- print(' Value length: %d' % len(value))
105- if len(str(value)) < 100: # Only print short values
106- print(' Value: %s' % value)
107- elif isinstance(value, (list, tuple)):
108- print(' Number of items: %d' % len(value))
109- if len(value) > 0:
110- print(' First item type: %s' % type(value[0]))
111- if isinstance(value[0], (str, bytes)) and len(str(value[0])) < 100:
112- print(' First item: %s' % value[0])
113- # Handle string/bytes conversion with better error handling
114- if isinstance(data, bytes):
79+ print(' Loading file %s for list %s...' %
80+ (os.path.basename(dbfile), listname or 'unknown'))
81+ if dbfile.endswith('.pck'):
82+ # Try to load the pickle file
11583 try:
116- data = data.decode('utf-8', 'replace')
117- except Exception as e:
118- if verbose:
119- print(' Warning: Error decoding bytes in %s for list %s: %s' %
120- (os.path.basename(dbfile), listname or 'unknown', str(e)))
121- data = str(data)
122- elif isinstance(data, dict):
123- new_data = {}
124- for k, v in data.items():
125- try:
126- if isinstance(k, bytes):
127- k = k.decode('utf-8', 'replace')
128- if isinstance(v, bytes):
129- v = v.decode('utf-8', 'replace')
130- elif isinstance(v, (list, tuple)):
131- v = list(v)
132- for i, item in enumerate(v):
133- if isinstance(item, bytes):
134- try:
135- v[i] = item.decode('utf-8', 'replace')
136- except Exception as e:
137- if verbose:
138- print(' Warning: Error decoding list item in %s for list %s: %s' %
139- (os.path.basename(dbfile), listname or 'unknown', str(e)))
140- v[i] = str(item)
141- new_data[k] = v
142- except Exception as e:
143- if verbose:
144- print(' Warning: Error processing dictionary item in %s for list %s: %s' %
145- (os.path.basename(dbfile), listname or 'unknown', str(e)))
146- new_data[str(k)] = str(v)
147- data = new_data
148- elif isinstance(data, (list, tuple)):
149- data = list(data)
150- for i, item in enumerate(data):
151- if isinstance(item, bytes):
84+ with open(dbfile, 'rb') as fp:
85+ # First try to detect Python 2 pickle
15286 try:
153- data[i] = item.decode('utf-8', 'replace')
154- except Exception as e:
87+ fp.seek(0)
88+ header = fp.read(2)
89+ is_py2_pickle = header.startswith(b'c') or header.startswith(b'C')
15590 if verbose:
156- print(' Warning: Error decoding list item in %s for list %s: %s' %
157- (os.path.basename(dbfile), listname or 'unknown', str(e)))
158- data[i] = str(item)
159- return data
160- except Exception as e:
91+ print(' Python 2 pickle detected: %s' % ('Yes' if is_py2_pickle else 'No'))
92+ except:
93+ is_py2_pickle = False
94+
95+ # Now load the actual data
96+ fp.seek(0)
97+ data = pickle.load(fp)
98+ if verbose:
99+ # Get pickle version info
100+ fp.seek(0)
101+ version = pickle.format_version
102+ protocol = pickle.HIGHEST_PROTOCOL
103+ print(' Pickle format version: %s' % version)
104+ print(' Pickle protocol: %d' % protocol)
105+ if is_py2_pickle:
106+ print(' WARNING: This file was likely written with Python 2')
107+ print(' String data may need special handling for Python 3 compatibility')
108+ except (EOFError, pickle.UnpicklingError) as e:
109+ print(' Error loading file %s for list %s: %s' %
110+ (os.path.basename(dbfile), listname or 'unknown', str(e)))
111+ # Always print error for request.pck files, even if not verbose
112+ if dbfile.endswith('request.pck'):
113+ print(' File %s for list %s: ERROR - %s' %
114+ (os.path.basename(dbfile), listname or 'unknown', str(e)))
115+ raise
116+ elif dbfile.endswith('.db'):
117+ # Try to load the marshal file
118+ try:
119+ with open(dbfile, 'rb') as fp:
120+ data = marshal.load(fp)
121+ if verbose:
122+ print(' Marshal format version: %d' % marshal.version)
123+ if marshal.version < 2:
124+ print(' WARNING: This file was likely written with Python 2')
125+ print(' String data may need special handling for Python 3 compatibility')
126+ except (EOFError, ValueError) as e:
127+ print(' Error loading file %s for list %s: %s' %
128+ (os.path.basename(dbfile), listname or 'unknown', str(e)))
129+ # Always print error for request.pck files, even if not verbose
130+ if dbfile.endswith('request.pck'):
131+ print(' File %s for list %s: ERROR - %s' %
132+ (os.path.basename(dbfile), listname or 'unknown', str(e)))
133+ raise
161134 if verbose:
162- print(' Error loading file %s for list %s: %s' %
135+ print(' File %s for list %s: OK' %
136+ (os.path.basename(dbfile), listname or 'unknown'))
137+ except Exception as e:
138+ print(' Error loading file %s for list %s: %s' %
139+ (os.path.basename(dbfile), listname or 'unknown', str(e)))
140+ # Always print error for request.pck files, even if not verbose
141+ if dbfile.endswith('request.pck'):
142+ print(' File %s for list %s: ERROR - %s' %
163143 (os.path.basename(dbfile), listname or 'unknown', str(e)))
164144 raise
165- finally:
166- fp.close()
167145
168146
169147def main():
@@ -223,9 +201,7 @@ def main():
223201 for dbfile in dbfiles:
224202 if os.path.exists(dbfile):
225203 try:
226- testfile(dbfile, args.verbose, listname)
227- if args.verbose:
228- print(' File %s: OK' % os.path.basename(dbfile))
204+ testfile(dbfile, listname, args.verbose)
229205 except Exception as e:
230206 print(' File %s: ERROR - %s' % (os.path.basename(dbfile), str(e)))
231207 elif args.verbose:
0 commit comments