diff --git a/.gitignore b/.gitignore index 378eac2..cde270d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ build +*.pyc +__pycache__ diff --git a/cpyrit/config.py b/cpyrit/config.py index 0f6b882..d0020ed 100644 --- a/cpyrit/config.py +++ b/cpyrit/config.py @@ -18,7 +18,6 @@ # You should have received a copy of the GNU General Public License # along with Pyrit. If not, see . -from __future__ import with_statement import os import sys @@ -43,12 +42,12 @@ def read_configfile(filename): for line in f: if line.startswith('#') or '=' not in line: continue - option, value = map(str.strip, line.split('=', 1)) + option, value = list(map(str.strip, line.split('=', 1))) if option in config: config[option] = value else: - print >> sys.stderr, "WARNING: Unknown option '%s' " \ - "in configfile '%s'" % (option, filename) + print("WARNING: Unknown option '%s' " \ + "in configfile '%s'" % (option, filename), file=sys.stderr) return config @@ -68,3 +67,4 @@ def write_configfile(config, filename): if not os.path.exists(configpath): os.makedirs(configpath) write_configfile(cfg, default_configfile) + diff --git a/cpyrit/cpyrit.py b/cpyrit/cpyrit.py index b161006..0590ca6 100644 --- a/cpyrit/cpyrit.py +++ b/cpyrit/cpyrit.py @@ -28,10 +28,9 @@ CPyrit enumerates the available cores and schedules workunits among them. """ -from __future__ import with_statement from collections import deque -import BaseHTTPServer +import http.server import hashlib import random import socket @@ -39,20 +38,21 @@ import threading import time import uuid -import util +from . import util import warnings -import xmlrpclib -import config -import network -import storage -import _cpyrit_cpu +import xmlrpc.client +from . import config +from . import network +from . import storage +import _cpyrit_cpu +from functools import reduce # prevent call to socket.getfqdn def fast_address_string(self): return '%s' % self.client_address[0] -BaseHTTPServer.BaseHTTPRequestHandler.address_string = fast_address_string +http.server.BaseHTTPRequestHandler.address_string = fast_address_string del fast_address_string @@ -207,8 +207,8 @@ def run(self): import _cpyrit_opencl except ImportError: pass -except Exception, e: - print >> sys.stderr, "Failed to load Pyrit's OpenCL-core ('%s')." % e +except Exception as e: + print("Failed to load Pyrit's CAL-core ('%s')." % e, file=sys.stderr) else: version_check(_cpyrit_opencl) @@ -230,8 +230,8 @@ def __init__(self, queue, platform_idx, dev_idx): import _cpyrit_cuda except ImportError: pass -except Exception, e: - print >> sys.stderr, "Failed to load Pyrit's CUDA-core ('%s')." % e +except Exception as e: + print("Failed to load Pyrit's CUDA-core ('%s')." % e, file=sys.stderr) else: version_check(_cpyrit_cuda) @@ -252,8 +252,8 @@ def __init__(self, queue, dev_idx): import _cpyrit_calpp except ImportError: pass -except Exception, e: - print >> sys.stderr, "Failed to load Pyrit's CAL-core ('%s')." % e +except Exception as e: + print("Failed to load Pyrit's CAL-core ('%s')." % e, file=sys.stderr) else: version_check(_cpyrit_calpp) @@ -301,7 +301,7 @@ def __init__(self, core): def run(self): while True: - for _, client in self.core.clients.items(): + for _, client in list(self.core.clients.items()): if time.time() - client.lastseen > 15.0: self.core.rpc_unregister(uuid) time.sleep(3) @@ -342,7 +342,7 @@ def _get_client(self, uuid): client.ping() return client else: - raise xmlrpclib.Fault(403, "Client unknown or timed-out") + raise xmlrpc.client.Fault(403, "Client unknown or timed-out") def rpc_register(self, uuids): with self.client_lock: @@ -373,7 +373,7 @@ def rpc_gather(self, client_uuid, buffersize): else: client.workunits.append((essid, pwlist)) key, buf = storage.PAW2_Buffer.pack(pwlist) - return (essid, xmlrpclib.Binary(buf)) + return (essid, xmlrpc.client.Binary(buf)) def rpc_scatter(self, client_uuid, encoded_buf): client = self._get_client(client_uuid) @@ -387,7 +387,7 @@ def rpc_scatter(self, client_uuid, encoded_buf): if len(buf) != len(pwlist) * 32: raise ValueError("Result has invalid size of %i. Expected %i." % (len(buf), len(pwlist) * 32)) - results = [buf[i * 32:i * 32 + 32] for i in xrange(len(pwlist))] + results = [buf[i * 32:i * 32 + 32] for i in range(len(pwlist))] self.compTime = time.time() - self.startTime self.resCount += len(results) self.callCount += 1 @@ -404,7 +404,7 @@ def rpc_revoke(self, client_uuid): def __iter__(self): with self.client_lock: - return self.clients.values().__iter__() + return list(self.clients.values()).__iter__() class CPyrit(object): @@ -459,14 +459,14 @@ def __init__(self): # CPUs - for i in xrange(util.ncpus): + for i in range(util.ncpus): self.cores.append(CPUCore(queue=self)) # Network if config.cfg['rpc_server'] == 'true': - for port in xrange(17935, 18000): + for port in range(17935, 18000): try: ncore = NetworkCore(queue=self, port=port) except socket.error: @@ -476,7 +476,7 @@ def __init__(self): self.cores.append(ncore) if config.cfg['rpc_announce'] == 'true': cl = config.cfg['rpc_knownclients'].split(' ') - cl = filter(lambda x: len(x) > 0, map(str.strip, cl)) + cl = [x for x in map(str.strip, cl) if len(x) > 0] bcst = config.cfg['rpc_announce_broadcast'] == 'true' self.announcer = network.NetworkAnnouncer(port=port, \ clients=cl, \ @@ -501,7 +501,7 @@ def _check_cores(self): raise SystemError("The core '%s' has died unexpectedly" % core) def _len(self): - return sum((sum((len(pwlist) for pwlist in pwdict.itervalues())) + return sum((sum((len(pwlist) for pwlist in list(pwdict.values()))) for essid, pwdict in self.inqueue)) def __len__(self): @@ -694,7 +694,7 @@ def _scatter(self, essid, passwords, results): for idx, length in slices: self.outqueue[idx] = list(results[ptr:ptr + length]) ptr += length - for idx in sorted(self.outqueue.iterkeys(), reverse=True)[1:]: + for idx in sorted(iter(list(self.outqueue.keys())), reverse=True)[1:]: res = self.outqueue[idx] o_idx = idx + len(res) if o_idx in self.outqueue: @@ -760,16 +760,16 @@ def __exit__(self, exc_type, exc_val, exc_tb): if self.cp is not None: self.cp.shutdown() - def next(self): + def __next__(self): while True: try: - key = self.iterkeys.next() + key = next(self.iterkeys) except StopIteration: if self.yieldNewResults: solvedPMKs = self.cp.dequeue(block=True) if solvedPMKs is not None: solvedEssid, solvedKey, solvedPasswords = self.workunits.pop(0) - solvedResults = zip(solvedPasswords, solvedPMKs) + solvedResults = list(zip(solvedPasswords, solvedPMKs)) self.storage.essids[solvedEssid, solvedKey] = solvedResults return solvedResults assert len(self.workunits) == 0 @@ -789,7 +789,7 @@ def next(self): solvedPMKs = self.cp.dequeue(block=False) if solvedPMKs is not None: solvedEssid, solvedKey, solvedPasswords = self.workunits.pop(0) - solvedResults = zip(solvedPasswords, solvedPMKs) + solvedResults = list(zip(solvedPasswords, solvedPMKs)) self.storage.essids[solvedEssid, solvedKey] = solvedResults return solvedResults @@ -816,7 +816,7 @@ def __enter__(self): def __exit__(self, exc_type, exc_val, exc_tb): self.cp.shutdown() - def next(self): + def __next__(self): pwbuffer = [] for line in self.iterator: pw = line.strip('\r\n')[:63] @@ -828,10 +828,10 @@ def next(self): pwbuffer = [] solvedPMKs = self.cp.dequeue(block=False) if solvedPMKs is not None: - return zip(self.workunits.pop(0), solvedPMKs) + return list(zip(self.workunits.pop(0), solvedPMKs)) if len(pwbuffer) > 0: self.workunits.append(pwbuffer) self.cp.enqueue(self.essid, self.workunits[-1]) for solvedPMKs in self.cp: - return zip(self.workunits.pop(0), solvedPMKs) + return list(zip(self.workunits.pop(0), solvedPMKs)) raise StopIteration diff --git a/cpyrit/network.py b/cpyrit/network.py index 6897209..5a79456 100644 --- a/cpyrit/network.py +++ b/cpyrit/network.py @@ -18,16 +18,16 @@ # You should have received a copy of the GNU General Public License # along with Pyrit. If not, see . -from __future__ import with_statement + import hashlib import socket import time import threading -import xmlrpclib +import xmlrpc.client -import storage -import util +from . import storage +from . import util class NetworkClient(util.Thread): @@ -37,7 +37,7 @@ class NetworkGatherer(threading.Thread): def __init__(self, client): threading.Thread.__init__(self) self.client = client - self.server = xmlrpclib.ServerProxy("http://%s:%s" % \ + self.server = xmlrpc.client.ServerProxy("http://%s:%s" % \ client.srv_addr) self.shallStop = False self.setDaemon(True) @@ -64,7 +64,7 @@ def shutdown(self): def __init__(self, srv_addr, enqueue_callback, known_uuids): util.Thread.__init__(self) - self.server = xmlrpclib.ServerProxy("http://%s:%s" % srv_addr) + self.server = xmlrpc.client.ServerProxy("http://%s:%s" % srv_addr) self.srv_uuid, self.uuid = self.server.register(";".join(known_uuids)) if not self.uuid: raise KeyError("Loop detected to %s" % self.srv_uuid) @@ -92,7 +92,7 @@ def run(self): buf = ''.join(solvedPMKs) md = hashlib.sha1() md.update(buf) - encoded_buf = xmlrpclib.Binary(md.digest() + buf) + encoded_buf = xmlrpc.client.Binary(md.digest() + buf) self.server.scatter(self.uuid, encoded_buf) self.stat_sent += len(solvedPMKs) self.ping() @@ -118,7 +118,7 @@ class NetworkServer(util.Thread): def __init__(self): util.Thread.__init__(self) - import cpyrit + from . import cpyrit self.cp = cpyrit.CPyrit() self.clients_lock = threading.Lock() self.clients = {} @@ -131,9 +131,9 @@ def __init__(self): def addClient(self, srv_addr): with self.clients_lock: - if any(c.srv_addr == srv_addr for c in self.clients.itervalues()): + if any(c.srv_addr == srv_addr for c in list(self.clients.values())): return - known_uuids = set(c.srv_uuid for c in self.clients.itervalues()) + known_uuids = set(c.srv_uuid for c in list(self.clients.values())) if self.cp.ncore_uuid is not None: known_uuids.add(self.cp.ncore_uuid) try: @@ -144,7 +144,8 @@ def addClient(self, srv_addr): client.start() self.clients[client.uuid] = client - def enqueue(self, uuid, (essid, pwlist)): + def enqueue(self, uuid, xxx_todo_changeme): + (essid, pwlist) = xxx_todo_changeme with self.clients_lock: if uuid not in self.clients: raise KeyError("Client unknown or timed-out") @@ -167,7 +168,7 @@ def run(self): client.scatter(solvedPMKs) self.stat_scattered += len(solvedPMKs) with self.clients_lock: - for client in self.clients.values(): + for client in list(self.clients.values()): if not client.isAlive() or \ time.time() - client.lastseen > 15.0: del self.clients[client.uuid] @@ -177,7 +178,7 @@ def run(self): def __contains__(self, srv_addr): with self.clients_lock: - i = self.clients.itervalues() + i = iter(list(self.clients.values())) return any(c.srv_addr == srv_addr for c in i) def __len__(self): @@ -186,12 +187,12 @@ def __len__(self): def __iter__(self): with self.clients_lock: - return self.clients.values().__iter__() + return list(self.clients.values()).__iter__() def shutdown(self): self.shallStop = True with self.clients_lock: - for client in self.clients.itervalues(): + for client in list(self.clients.values()): client.shutdown() self.join() @@ -282,7 +283,7 @@ def waitForAnnouncement(self, block=True, timeout=None): def __iter__(self): return self - def next(self): + def __next__(self): return self.waitForAnnouncement(block=True) def shutdown(self): diff --git a/cpyrit/pckttools.py b/cpyrit/pckttools.py index 039de23..c0a54fd 100644 --- a/cpyrit/pckttools.py +++ b/cpyrit/pckttools.py @@ -28,15 +28,15 @@ AccessPoint -> Station -> EAPOLAuthentication. """ -from __future__ import with_statement + import binascii import tempfile import threading -import Queue +import queue import warnings -import util +from . import util import _cpyrit_cpu try: @@ -47,7 +47,7 @@ import scapy.layers.dot11 import scapy.packet import scapy.utils -except ImportError, e: +except ImportError as e: raise util.ScapyImportError(e) # Scapy 2.4.0 @@ -192,7 +192,7 @@ def __init__(self, mac): self.stations = {} def __iter__(self): - return self.stations.values().__iter__() + return list(self.stations.values()).__iter__() def __str__(self): return self.mac @@ -212,7 +212,7 @@ def __len__(self): def getCompletedAuthentications(self): """Return list of completed Authentication.""" auths = [] - for station in self.stations.itervalues(): + for station in list(self.stations.values()): auths.extend(station.getAuthentications()) return auths @@ -352,10 +352,10 @@ def addConfirmationFrame(self, pckt_idx, pckt): def _buildAuthentications(self, f1_frames, f2_frames, f3_frames): auths = [] for (version, snonce, keymic_frame, WPAKeyMIC), \ - (f2_idx, f2) in f2_frames.iteritems(): + (f2_idx, f2) in list(f2_frames.items()): # Combinations with Frame3 are of higher value as the AP # acknowledges that the STA used the correct PMK in Frame2 - for anonce, (f3_idx, f3) in f3_frames.iteritems(): + for anonce, (f3_idx, f3) in list(f3_frames.items()): if anonce in f1_frames: # We have F1+F2+F3. Frame2 is only cornered by the # ReplayCounter. Technically we don't benefit @@ -374,7 +374,7 @@ def _buildAuthentications(self, f1_frames, f2_frames, f3_frames): anonce, WPAKeyMIC, keymic_frame, \ 1, spread, (None, f2, f3)) auths.append(auth) - for anonce, (f1_idx, f1) in f1_frames.iteritems(): + for anonce, (f1_idx, f1) in list(f1_frames.items()): # No third frame. Combinations with Frame1 are possible but # can also be triggered by STAs that use an incorrect PMK. spread = abs(f1_idx - f2_idx) @@ -422,7 +422,7 @@ def getAuthentications(self): handshake-packets. Best matches come first. """ auths = [] - for frames in self.eapoldict.itervalues(): + for frames in list(self.eapoldict.values()): auths.extend(self._buildAuthentications(*frames)) return sorted(auths) @@ -610,7 +610,7 @@ def read(self): def __iter__(self): return self - def next(self): + def __next__(self): pckt = self.read() if pckt is not None: return pckt @@ -807,7 +807,7 @@ def parse_packet(self, pckt): def __iter__(self): return [ap for essid, ap in sorted([(ap.essid, ap) \ - for ap in self.air.itervalues()])].__iter__() + for ap in list(self.air.values())])].__iter__() def __getitem__(self, bssid): return self.air[bssid] @@ -834,7 +834,7 @@ def run(self): while not self.shallStop: try: results = self.workqueue.get(block=True, timeout=0.5) - except Queue.Empty: + except queue.Empty: pass else: solution = self.solve(results) @@ -869,7 +869,7 @@ def __init__(self, workqueue, auth): class AuthCracker(object): def __init__(self, authentication, use_aes=False): - self.queue = Queue.Queue(10) + self.queue = queue.Queue(10) self.workers = [] self.solution = None if authentication.version == "HMAC_SHA1_AES" \ @@ -878,7 +878,7 @@ def __init__(self, authentication, use_aes=False): self.cracker = CCMPCrackerThread else: self.cracker = EAPOLCrackerThread - for i in xrange(util.ncpus): + for i in range(util.ncpus): self.workers.append(self.cracker(self.queue, authentication)) def _getSolution(self): diff --git a/cpyrit/storage.py b/cpyrit/storage.py index 3933f62..40e5793 100644 --- a/cpyrit/storage.py +++ b/cpyrit/storage.py @@ -23,9 +23,6 @@ """ -from __future__ import with_statement - -import BaseHTTPServer import hashlib import itertools import os @@ -34,7 +31,7 @@ import struct import sys import threading -import xmlrpclib +import xmlrpc.client import zlib try: import sqlalchemy as sql @@ -47,15 +44,15 @@ else: UniversalBinary = sql.Binary -import config -import util +from . import config +from . import util import _cpyrit_cpu # prevent call to socket.getfqdn def fast_address_string(self): return '%s' % self.client_address[0] -BaseHTTPServer.BaseHTTPRequestHandler.address_string = fast_address_string +http.server.BaseHTTPRequestHandler.address_string = fast_address_string del fast_address_string @@ -77,7 +74,7 @@ def check_xmlfault(f): def protected_f(*args, **kwds): try: ret = f(*args, **kwds) - except xmlrpclib.Fault, e: + except xmlrpc.client.Fault as e: # rpc does not know Exceptions so they always come as pure # strings. One way would be to hack into the de-marshalling. # These seems easier and less intrusive. @@ -95,7 +92,7 @@ def protected_f(*args, **kwds): else: raise return ret - protected_f.func_name = f.func_name + protected_f.__name__ = f.__name__ protected_f.__doc__ = f.__doc__ return protected_f return check_xmlfault @@ -198,7 +195,7 @@ def __len__(self): return self.numElems def __iter__(self): - return itertools.izip(self.passwords, self.pmks) + return list(zip(self.passwords, self.pmks)) def getpmkbuffer(self): return buffer(self.pmkbuffer) @@ -272,7 +269,7 @@ class PasswordStore(object): Passwords are indexed by keys and are returned as iterables. The iterator cycles over all available keys. """ - h1_list = ["%02.2X" % i for i in xrange(256)] + h1_list = ["%02.2X" % i for i in range(256)] del i def __init__(self): @@ -293,7 +290,7 @@ def flush_buffer(self): For efficiency reasons this function should not be called if the caller wants to add more passwords in the foreseeable future. """ - for pw_h1, pw_bucket in self.pwbuffer.iteritems(): + for pw_h1, pw_bucket in list(self.pwbuffer.items()): self._flush_bucket(pw_h1, pw_bucket) self.pwbuffer[pw_h1] = (set if self.unique_check else list)() @@ -412,15 +409,16 @@ def __init__(self, basepath): self.essids[essid][1][pyrfile[:len(pyrfile) - 4]] = \ os.path.join(essidpath, pyrfile) else: - print >>sys.stderr, "ESSID %s is corrupted." % essid_hash + print("ESSID %s is corrupted." % essid_hash, file=sys.stderr) - def __getitem__(self, (essid, key)): + def __getitem__(self, xxx_todo_changeme6): """Receive a iterable of (password,PMK)-tuples stored under the given ESSID and key. Returns a empty iterable if the key is not stored. Raises KeyError if the ESSID is not stored. """ + (essid, key) = xxx_todo_changeme6 try: fname = self.essids[essid][1][key] except IndexError: @@ -433,10 +431,11 @@ def __getitem__(self, (essid, key)): raise StorageError("Invalid ESSID in result-collection") return results - def __setitem__(self, (essid, key), results): + def __setitem__(self, xxx_todo_changeme7, results): """Store a iterable of (password,PMK)-tuples under the given ESSID and key. """ + (essid, key) = xxx_todo_changeme7 if essid not in self.essids: raise KeyError("ESSID not in store.") filename = os.path.join(self.essids[essid][0], key) + '.pyr' @@ -456,10 +455,11 @@ def __contains__(self, essid): """Return True if the given ESSID is currently stored.""" return essid in self.essids - def __delitem__(self, (essid, key)): + def __delitem__(self, xxx_todo_changeme8): """Delete the given ESSID:key resultset or the entire ESSID and all results from the storage. """ + (essid, key) = xxx_todo_changeme8 if essid not in self: raise KeyError("ESSID not in storage") if key is not None: @@ -471,7 +471,7 @@ def __delitem__(self, (essid, key)): else: essid_root, pyrfiles = self.essids[essid] del self.essids[essid] - for fname in pyrfiles.itervalues(): + for fname in list(pyrfiles.values()): os.unlink(fname) os.unlink(os.path.join(essid_root, 'essid')) os.rmdir(essid_root) @@ -534,7 +534,7 @@ def __contains__(self, key): def __iter__(self): """Iterate over all keys that can be used to receive password-sets.""" - return self.pwfiles.keys().__iter__() + return list(self.pwfiles.keys()).__iter__() def __len__(self): """Return the number of keys that can be used to receive @@ -566,7 +566,7 @@ def _flush_bucket(self, pw_h1, bucket): if len(bucket) == 0: return if self.unique_check: - for key, pwpath in self.pwfiles.iteritems(): + for key, pwpath in list(self.pwfiles.items()): if pwpath.endswith(pw_h1): bucket.difference_update(self[key]) if len(bucket) == 0: @@ -583,7 +583,7 @@ def _flush_bucket(self, pw_h1, bucket): class RPCStorage(Storage): def __init__(self, url): - self.cli = xmlrpclib.ServerProxy(url) + self.cli = xmlrpc.client.ServerProxy(url) self.essids = RPCESSIDStore(self.cli) self.passwords = RPCPasswordStore(self.cli) @@ -598,13 +598,14 @@ def __init__(self, cli): self.cli = cli @handle_xmlfault() - def __getitem__(self, (essid, key)): + def __getitem__(self, xxx_todo_changeme3): """Receive a iterable of (password,PMK)-tuples stored under the given ESSID and key. Returns a empty iterable if the key is not stored. Raises KeyError if the ESSID is not stored. """ + (essid, key) = xxx_todo_changeme3 buf = self.cli.essids.getitem(essid, key) if buf: results = PYR2_Buffer(buf.data) @@ -615,10 +616,11 @@ def __getitem__(self, (essid, key)): raise KeyError @handle_xmlfault() - def __setitem__(self, (essid, key), results): + def __setitem__(self, xxx_todo_changeme4, results): """Store a iterable of (password,PMK)-tuples under the given ESSID and key. """ + (essid, key) = xxx_todo_changeme4 b = xmlrpclib.Binary(PYR2_Buffer.pack(essid, results)) self.cli.essids.setitem(essid, key, b) @@ -638,10 +640,11 @@ def __contains__(self, essid): return self.cli.essids.contains(essid) @handle_xmlfault() - def __delitem__(self, (essid, key)): + def __delitem__(self, xxx_todo_changeme5): """Delete the ESSID:key resultset or the entire ESSID and all results from the storage. """ + (essid, key) = xxx_todo_changeme5 if key is None: key = '' self.cli.essids.delitem(essid, key) @@ -682,7 +685,7 @@ def __init__(self, cli): @handle_xmlfault() def __iter__(self): """Iterate over all keys that can be used to receive password-sets.""" - return self.cli.passwords.keys().__iter__() + return list(self.cli.passwords.keys()).__iter__() @handle_xmlfault() def __len__(self): @@ -757,7 +760,7 @@ def passwords_contains(self, key): def passwords_getitem(self, key): newkey, buf = PAW2_Buffer.pack(self.storage.passwords[key]) - return xmlrpclib.Binary(buf) + return xmlrpc.client.Binary(buf) def passwords_delitem(self, key): del self.storage.passwords[key] @@ -789,7 +792,7 @@ def essids_getitem(self, essid, key): return False else: buf = PYR2_Buffer.pack(essid, results) - return xmlrpclib.Binary(buf) + return xmlrpc.client.Binary(buf) def essids_setitem(self, essid, key, buf): results = PYR2_Buffer(buf.data) @@ -996,13 +999,14 @@ def __len__(self): with SessionContext(self.SessionClass) as session: return session.query(ESSID_DBObject).count() - def __getitem__(self, (essid, key)): + def __getitem__(self, xxx_todo_changeme): """Receive a iterable of (password,PMK)-tuples stored under the given ESSID and key. Returns a empty iterable if the key is not stored. Raises KeyError if the ESSID is not stored. """ + (essid, key) = xxx_todo_changeme with SessionContext(self.SessionClass) as session: q = session.query(PYR2_DBObject).join(ESSID_DBObject) result = q.filter(sql.and_(ESSID_DBObject.essid == essid, \ @@ -1013,10 +1017,11 @@ def __getitem__(self, (essid, key)): else: return result - def __setitem__(self, (essid, key), results): + def __setitem__(self, xxx_todo_changeme1, results): """Store a iterable of (password,PMK)-tuples under the given ESSID and key. """ + (essid, key) = xxx_todo_changeme1 with SessionContext(self.SessionClass) as session: q = session.query(ESSID_DBObject) essid_obj = q.filter(ESSID_DBObject.essid == essid).one() @@ -1035,10 +1040,11 @@ def __setitem__(self, (essid, key), results): result_obj.pack(results) session.commit() - def __delitem__(self, (essid, key)): + def __delitem__(self, xxx_todo_changeme2): """Delete the given ESSID:key resultset or the entire ESSID and all results from the storage. """ + (essid, key) = xxx_todo_changeme2 with SessionContext(self.SessionClass) as session: essid_query = session.query(ESSID_DBObject) essid_query = essid_query.filter(ESSID_DBObject.essid == essid) @@ -1156,3 +1162,4 @@ def _flush_bucket(self, pw_h1, bucket): return session.add(PAW2_DBObject(pw_h1, bucket)) session.commit() + diff --git a/cpyrit/util.py b/cpyrit/util.py index 59e14f0..01fc238 100644 --- a/cpyrit/util.py +++ b/cpyrit/util.py @@ -36,16 +36,16 @@ local installations. """ -from __future__ import with_statement + import bisect -import cStringIO +import io import gzip import os -import Queue +import queue import random import socket -import SimpleXMLRPCServer +import xmlrpc.server import sys import struct import time @@ -53,7 +53,7 @@ import _cpyrit_cpu from _cpyrit_cpu import VERSION, grouper -import config +from . import config __version__ = VERSION @@ -343,7 +343,7 @@ def write(self, results): def close(self): self.f.close() - def next(self): + def __next__(self): if self.mode != 'r': raise TypeError("Can't read from write-only file.") self.tail = self.tail + self.f.read(512 * 1024) @@ -372,7 +372,7 @@ def __init__(self, f, maxsize=10 * 1024 ** 2): self.hasstopped = False self.maxsize = maxsize self.excp = None - self.buf = cStringIO.StringIO() + self.buf = io.StringIO() self.cv = threading.Condition() self.start() @@ -460,12 +460,12 @@ def run(self): self.cv.wait() else: data = self.buf.getvalue() - self.buf = cStringIO.StringIO() + self.buf = io.StringIO() self.cv.notifyAll() if data: self.filehndl.write(data) self.filehndl.flush() - except Exception, e: + except Exception as e: # Re-create a 'trans-thread-safe' instance self.excp = type(e)(str(e)) finally: @@ -502,8 +502,7 @@ def __iadd__(self, p): def __purge(self): t = time.time() if t - self.datapoints[0][0] > self.window: - self.datapoints = filter(lambda x: (t - x[0]) < self.window, \ - self.datapoints) + self.datapoints = [x for x in self.datapoints if (t - x[0]) < self.window] def getAvg(self): self.__purge() @@ -539,7 +538,7 @@ def shutdown(self): self.join() -class AsyncXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, Thread): +class AsyncXMLRPCServer(xmlrpc.server.SimpleXMLRPCServer, Thread): """A stoppable XMLRPCServer The main socket is made non-blocking so we can check on @@ -548,8 +547,9 @@ class AsyncXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer, Thread): Sub-classes should add (name:function)-entries to self.methods """ - def __init__(self, (iface, port)=('', 17934)): - SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, (iface, port), \ + def __init__(self, xxx_todo_changeme=('', 17934)): + (iface, port) = xxx_todo_changeme + xmlrpc.server.SimpleXMLRPCServer.__init__(self, (iface, port), \ logRequests=False) Thread.__init__(self) self.setDaemon(True) diff --git a/modules/cpyrit_calpp/setup.py b/modules/cpyrit_calpp/setup.py index 6dd21d5..8031d88 100755 --- a/modules/cpyrit_calpp/setup.py +++ b/modules/cpyrit_calpp/setup.py @@ -26,7 +26,7 @@ import subprocess import sys -VERSION = '0.5.0' +VERSION = '0.5.2' CALPP_INC_DIRS = [] @@ -34,14 +34,14 @@ try: CALPP_INC_DIR = os.environ['ATISTREAMSDKROOT'] except KeyError: - print >>sys.stderr, "unavailable enviroment variable ATISTREAMSDKROOT" + print("unavailable enviroment variable ATISTREAMSDKROOT", file=sys.stderr) raise else: if os.path.exists(CALPP_INC_DIR): CALPP_INC_DIRS.append(os.path.join(CALPP_INC_DIR, 'include')) else: - print >>sys.stderr, "The headers required to build CAL++ kernel" \ - "were not found. Trying to continue anyway..." + print("The headers required to build CAL++ kernel" \ + "were not found. Trying to continue anyway...", file=sys.stderr) EXTRA_COMPILE_ARGS = ['-Wall', '-fno-strict-aliasing', \ @@ -50,7 +50,7 @@ class GPUBuilder(build_ext): def run(self): - print "Building modules..." + print("Building modules...") build_ext.run(self) @@ -66,7 +66,7 @@ def _unlink(self, node): pass def run(self): - print "Removing temporary files and pre-built GPU-kernels..." + print("Removing temporary files and pre-built GPU-kernels...") clean.run(self) diff --git a/modules/cpyrit_cuda/setup.py b/modules/cpyrit_cuda/setup.py index a05fc85..7a2a010 100755 --- a/modules/cpyrit_cuda/setup.py +++ b/modules/cpyrit_cuda/setup.py @@ -37,8 +37,8 @@ NVCC = os.path.join(path, 'bin', 'nvcc') break else: - print >>sys.stderr, "The CUDA compiler and headers required to build " \ - "kernel were not found. Trying to continue anyway..." + print("The CUDA compiler and headers required to build " \ + "kernel were not found. Trying to continue anyway...", file=sys.stderr) EXTRA_COMPILE_ARGS = ['-Wall', '-fno-strict-aliasing', @@ -53,8 +53,8 @@ def _call(self, comm): if p.returncode == 0: return stdo else: - print >>sys.stderr, "%s\nFailed to execute command '%s'" % \ - (stde, comm) + print("%s\nFailed to execute command '%s'" % \ + (stde, comm), file=sys.stderr) return None def _makedirs(self, pathname): @@ -65,7 +65,7 @@ def _makedirs(self, pathname): def run(self): if '_cpyrit_cudakernel.ptx.h' in os.listdir('./'): - print "Skipping rebuild of Nvidia CUDA kernel ..." + print("Skipping rebuild of Nvidia CUDA kernel ...") else: nvcc_o = self._call(NVCC + ' -V') if nvcc_o is not None: @@ -73,7 +73,7 @@ def run(self): else: raise SystemError("Nvidia's CUDA-compiler 'nvcc' can't be " \ "found.") - print "Compiling CUDA module using nvcc %s..." % nvcc_version + print("Compiling CUDA module using nvcc %s..." % nvcc_version) # We need to hardcode arch at least for MacOS 10.6 / CUDA 3.1 bits, linkage = platform.architecture() @@ -82,12 +82,12 @@ def run(self): elif bits == '64bit': bit_flag = ' -m64' else: - print >>sys.stderr, "Can't detect platform, using 32bit" + print("Can't detect platform, using 32bit", file=sys.stderr) bit_flag = ' -m32' nvcc_cmd = NVCC + bit_flag + ' -ccbin clang -Xcompiler "-fPIC" --ptx ./_cpyrit_cudakernel.cu' - print "Executing '%s'" % nvcc_cmd + print("Executing '%s'" % nvcc_cmd) subprocess.check_call(nvcc_cmd, shell=True) with open("_cpyrit_cudakernel.ptx", "rb") as fid: @@ -97,7 +97,7 @@ def run(self): fid.write("unsigned char __cudakernel_packedmodule[] = {") fid.write(','.join(ptx_inc)) fid.write("};\nsize_t cudakernel_modulesize = %i;\n" % len(ptx)) - print "Building modules..." + print("Building modules...") build_ext.run(self) @@ -113,15 +113,16 @@ def _unlink(self, node): pass def run(self): - print "Removing temporary files and pre-built GPU-kernels..." + print("Removing temporary files and pre-built GPU-kernels...") try: for f in ('_cpyrit_cudakernel.linkinfo', \ '_cpyrit_cudakernel.ptx', \ '_cpyrit_cudakernel.ptx.h'): self._unlink(f) - except Exception, (errno, sterrno): - print >>sys.stderr, "Exception while cleaning temporary " \ - "files ('%s')" % sterrno + except Exception as xxx_todo_changeme: + (errno, sterrno) = xxx_todo_changeme.args + print("Exception while cleaning temporary " \ + "files ('%s')" % sterrno, file=sys.stderr) clean.run(self) diff --git a/modules/cpyrit_opencl/setup.py b/modules/cpyrit_opencl/setup.py old mode 100755 new mode 100644 index 4f0bcd3..3c81073 --- a/modules/cpyrit_opencl/setup.py +++ b/modules/cpyrit_opencl/setup.py @@ -18,7 +18,7 @@ # You should have received a copy of the GNU General Public License # along with Pyrit. If not, see . -from __future__ import with_statement + from distutils.core import setup, Extension from distutils.command.build_ext import build_ext from distutils.command.clean import clean @@ -57,8 +57,8 @@ OPENCL_INC_DIRS.append(path) break else: - print >>sys.stderr, "The headers required to build the OpenCL-kernel " \ - "were not found. Trying to continue anyway..." + print("The headers required to build the OpenCL-kernel " \ + "were not found. Trying to continue anyway...", file=sys.stderr) EXTRA_COMPILE_ARGS = ['-Wall', '-fno-strict-aliasing', \ @@ -77,7 +77,7 @@ def run(self): f.write("unsigned char oclkernel_packedprogram[] = {") f.write(",".join(("0x%02X" % ord(c) for c in oclkernel_inc))) f.write("};\nsize_t oclkernel_size = %i;\n" % len(oclkernel_code)) - print "Building modules..." + print("Building modules...") build_ext.run(self) @@ -92,13 +92,14 @@ def _unlink(self, node): pass def run(self): - print "Removing temporary files and pre-built GPU-kernels..." + print("Removing temporary files and pre-built GPU-kernels...") try: for f in ('_cpyrit_oclkernel.cl.h',): self._unlink(f) - except Exception, (errno, sterrno): - print >>sys.stderr, "Exception while cleaning temporary " \ - "files ('%s')" % sterrno + except Exception as xxx_todo_changeme: + (errno, sterrno) = xxx_todo_changeme.args + print("Exception while cleaning temporary " \ + "files ('%s')" % sterrno, file=sys.stderr) clean.run(self) @@ -144,3 +145,4 @@ def run(self): if __name__ == "__main__": setup(**setup_args) + diff --git a/pyrit b/pyrit index a5316a1..12ccca3 100755 --- a/pyrit +++ b/pyrit @@ -5,6 +5,6 @@ if __name__ == "__main__": try: pyrit_cli.Pyrit_CLI().initFromArgv() except (KeyboardInterrupt, SystemExit): - print >>sys.stderr, "\nInterrupted..." - except pyrit_cli.PyritRuntimeError, e: + print("\nInterrupted...", file=sys.stderr) + except pyrit_cli.PyritRuntimeError as e: sys.exit(e) diff --git a/pyrit_cli.py b/pyrit_cli.py old mode 100644 new mode 100755 index 3e587e9..d91be3f --- a/pyrit_cli.py +++ b/pyrit_cli.py @@ -18,7 +18,6 @@ # You should have received a copy of the GNU General Public License # along with Pyrit. If not, see . -from __future__ import with_statement import getopt import glob @@ -79,7 +78,7 @@ def initFromArgv(self): raise PyritRuntimeError("The command '%s' requires the " \ "option '%s'. See 'help'." % \ (command, param)) - for arg, value in args.iteritems(): + for arg, value in list(args.items()): if arg in req_params or arg in opt_params: if arg == '-e': options['essid'] = value @@ -164,7 +163,7 @@ def new_f(*args, **kwds): "functions but seems to be " \ "unavailable.") f(*args, **kwds) - new_f.func_name = f.func_name + new_f.__name__ = f.__name__ new_f.__doc__ = f.__doc__ return new_f return check_pkttools @@ -204,10 +203,9 @@ def _fuzzyGetAP(self, parser, bssid=None, essid=None): ap = None if essid is not None: if ap is None: - aps = filter(lambda ap: (ap.essid is None + aps = [ap for ap in parser if (ap.essid is None or ap.essid == essid) - and ap.isCompleted(), - parser) + and ap.isCompleted()] if len(aps) > 0: ap = aps[0] self.tell("Picked AccessPoint %s automatically..." % ap) @@ -342,9 +340,9 @@ def eval_results(self, storage): pwcount, essid_results = storage.getStats() self.tell("\rPasswords available: %i\n" % pwcount) if len(essid_results) > 0: - m = max(len(essid) for essid in essid_results.iterkeys()) - n = max(len(str(c)) for c in essid_results.itervalues()) - for essid, rescnt in sorted(essid_results.iteritems()): + m = max(len(essid) for essid in list(essid_results.keys())) + n = max(len(str(c)) for c in list(essid_results.values())) + for essid, rescnt in sorted(essid_results.items()): self.tell("ESSID '%s'%s : %s%i (%.2f%%)" % (essid, \ ' ' * (m - len(essid)), \ ' ' * (n - len(str(rescnt))), rescnt, \ @@ -572,25 +570,25 @@ def stripLive(self, capturefile, outfile): lambda sta: self._stripLive_newStation(parser, writer, sta) parser.new_keypckt_callback = \ - lambda (sta, idx, pckt): \ - self._stripLive_newKeyPckt(parser, writer, sta, idx, pckt) + lambda sta_idx_pckt: \ + self._stripLive_newKeyPckt(parser, writer, sta_idx_pckt[0], sta_idx_pckt[1], sta_idx_pckt[2]) parser.new_encpckt_callback = \ - lambda (sta, pckt): \ - self._stripLive_newEncPckt(parser, writer, sta, pckt) + lambda sta_pckt: \ + self._stripLive_newEncPckt(parser, writer, sta_pckt[0], sta_pckt[1]) parser.new_auth_callback = \ - lambda (sta, auth): self._stripLive_newAuth(parser, writer, sta, \ - auth) + lambda sta_auth: self._stripLive_newAuth(parser, writer, sta_auth[0], \ + sta_auth[1]) self.tell("Parsing packets from '%s'..." % capturefile) pckt_rdr = cpyrit.pckttools.PcapDevice(use_bpf=True) try: pckt_rdr.open_offline(capturefile) - except IOError, offline_error: + except IOError as offline_error: try: pckt_rdr.open_live(capturefile) - except IOError, live_error: + except IOError as live_error: raise PyritRuntimeError("Failed to open '%s' either as a " \ "file ('%s') or as a device " \ "('%s')" % (capturefile, \ @@ -636,8 +634,8 @@ def export_hashdb(self, storage, outfile, essid=None): con.text_factory = str cur = con.cursor() cur.execute('SELECT * FROM sqlite_master') - tbls = [x[1] for x in cur.fetchall() if x[0] == u'table'] - if u'pmk' not in tbls or u'essid' not in tbls or u'passwd' not in tbls: + tbls = [x[1] for x in cur.fetchall() if x[0] == 'table'] + if 'pmk' not in tbls or 'essid' not in tbls or 'passwd' not in tbls: self.tell("The database '%s' seems to be uninitialized. " % \ outfile) self.tell("Trying to create default table-layout...", end=None) @@ -1207,13 +1205,13 @@ def benchmark(self, timeout=45, calibrate=10): t = time.time() perfcounter = cpyrit.util.PerformanceCounter(timeout + 5) while time.time() - t < timeout: - pws = ["barbarbar%s" % random.random() for i in xrange(bsize)] + pws = ["barbarbar%s" % random.random() for i in range(bsize)] cp.enqueue('foo', pws) r = cp.dequeue(block=False) if r is not None: perfcounter += len(r) self.tell("\rRunning benchmark (%.1f PMKs/s)... %s" % \ - (perfcounter.avg, cycler.next()), end=None) + (perfcounter.avg, next(cycler)), end=None) self.tell('') self.tell("\nComputed %.2f PMKs/s total." % perfcounter.avg) for i, core in enumerate(cp.cores): @@ -1291,10 +1289,10 @@ def selftest(self, timeout=60): t = time.time() err = False while time.time() - t < timeout and not err: - essid = random.choice(cpyrit.util.PMK_TESTVECTORS.keys()) + essid = random.choice(list(cpyrit.util.PMK_TESTVECTORS.keys())) pws = [] - ref = cpyrit.util.PMK_TESTVECTORS[essid].keys() - for i in xrange(random.randrange(10, 1000)): + ref = list(cpyrit.util.PMK_TESTVECTORS[essid].keys()) + for i in range(random.randrange(10, 1000)): pws.append(random.choice(ref)) workunits.append((essid, pws)) cp.enqueue(essid, pws) @@ -1355,7 +1353,7 @@ def verify(self, storage, essid=None): for key, results in storage.essids.iteritems(essid): sample = random.sample(results, int(len(results) * 0.1)) if len(sample) > 0: - pws, pmks = zip(*sample) + pws, pmks = list(zip(*sample)) workunits.append((essid, key, tuple(pmks))) cp.enqueue(essid, pws) solvedPMKs = cp.dequeue(block=False) @@ -1410,14 +1408,14 @@ def checkdb(self, storage, confirm=True): # Check passwords self.tell("Checking workunits...") wu_errors = set() - for key in storage.passwords.iterkeys(): + for key in list(storage.passwords.keys()): try: # explicit call to iter to work around swallowed # exceptions in CPython's bltinmodule.c:map_new() for l in map(len, iter(storage.passwords[key])): if l < 8 or l > 64: raise cpyrit.storage.StorageError("Invalid password") - except cpyrit.storage.StorageError, e: + except cpyrit.storage.StorageError as e: self.tell("Error in workunit %s: %s" % (key, e), \ stream=sys.stderr) wu_errors.add(key) @@ -1452,7 +1450,7 @@ def checkdb(self, storage, confirm=True): if pw not in res_passwords: raise cpyrit.storage.StorageError("Password " \ "not in resultset") - except cpyrit.storage.StorageError, e: + except cpyrit.storage.StorageError as e: self.tell("Error in results %s for ESSID '%s':" \ " %s" % (key, essid, e), stream=sys.stderr) if key not in wu_errors: diff --git a/setup.py b/setup.py index 3ae4156..1136fed 100755 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ from distutils.errors import CompileError -VERSION = '0.5.1' +VERSION = '0.5.2' UnixCCompiler.src_extensions.append('.S') @@ -53,7 +53,7 @@ def build_extension(self, ext): return build_ext.build_extension(self, ext) except CompileError: if ext.extra_compile_args and '-maes' in ext.extra_compile_args: - print "Failed to build; Compiling without AES-NI" + print("Failed to build; Compiling without AES-NI") ext.extra_compile_args.remove('-maes') ext.extra_compile_args.remove('-mpclmul') return build_ext.build_extension(self, ext) diff --git a/test/test_pyrit.py b/test/test_pyrit.py index f604e40..05b5d68 100755 --- a/test/test_pyrit.py +++ b/test/test_pyrit.py @@ -29,7 +29,7 @@ """ -from __future__ import with_statement + import os import shutil @@ -61,7 +61,7 @@ def new_f(*args, **kwds): sys.stderr.write("(Skipped: Scapy not installed) ") else: f(*args, **kwds) - new_f.func_name = f.func_name + new_f.__name__ = f.__name__ new_f.__doc__ = f.__doc__ return new_f return check_pkttools @@ -74,8 +74,8 @@ def getStorage(self): def corrupt(self, storage): # Destroy some passwords - keys = list(storage.passwords.iterkeys()) - for i in xrange(13): + keys = list(storage.passwords.keys()) + for i in range(13): key = random.choice(keys) # This is specific to storage.FSPasswordStore filename = os.path.join(storage.passwords.pwfiles[key], key) @@ -95,7 +95,7 @@ def corrupt(self, storage): break # Destroy some results keys = list(storage.essids.iterkeys('test')) - for i in xrange(13): + for i in range(13): key = random.choice(keys) # This is specific to storage.FSEssidStore filename = os.path.join(storage.essids.essids['test'][0], key) @@ -135,7 +135,7 @@ def tearDown(self): shutil.rmtree(self.storage_path) def _createPasswords(self, filename): - test_passwds = ['test123%i' % i for i in xrange(5000 - 5)] + test_passwds = ['test123%i' % i for i in range(5000 - 5)] test_passwds += ['dictionary', 'helium02', 'MOM12345', \ 'preinstall', 'password'] random.shuffle(test_passwds) @@ -150,7 +150,7 @@ def _createDatabase(self, storage): def _computeFakeDatabase(self, storage, essid): self.cli.create_essid(storage, essid) - for key, passwords in storage.passwords.iteritems(): + for key, passwords in list(storage.passwords.items()): storage.essids[essid, key] = [(pw, 'x' * 32) for pw in passwords] def _computeDatabase(self, storage, essid): @@ -164,7 +164,7 @@ def _computeDatabase(self, storage, essid): def _testHandshake(self, filename, essid, ap, sta, passwd, aes=False): parser = cpyrit.pckttools.PacketParser(filename) with cpyrit.cpyrit.PassthroughIterator(essid, (passwd,)) as cp: - solution = cp.next() + solution = next(cp) auths = parser[ap][sta].getAuthentications() for auth in parser[ap][sta].getAuthentications(): with cpyrit.pckttools.AuthCracker(auth, aes) as cracker: @@ -202,15 +202,15 @@ def testImportPasswords(self): storage = self.getStorage() self.assertEqual(len(storage.passwords), 0) # valid_passwds should get accepted, short_passwds ignored - valid_passwds = ['test123%i' % i for i in xrange(100000)] - short_passwds = ['x%i' % i for i in xrange(30000)] + valid_passwds = ['test123%i' % i for i in range(100000)] + short_passwds = ['x%i' % i for i in range(30000)] test_passwds = valid_passwds + short_passwds random.shuffle(test_passwds) with cpyrit.util.AsyncFileWriter(self.tempfile1) as f: f.write('\n'.join(test_passwds)) self.cli.import_passwords(storage, self.tempfile1) new_passwds = set() - for key, pwset in storage.passwords.iteritems(): + for key, pwset in list(storage.passwords.items()): new_passwds.update(pwset) self.assertEqual(new_passwds, set(valid_passwds)) # There should be no duplicates @@ -221,7 +221,7 @@ def testImportPasswords(self): self.cli.import_passwords(storage, self.tempfile1) new_passwds = set() i = 0 - for key, pwset in storage.passwords.iteritems(): + for key, pwset in list(storage.passwords.items()): new_passwds.update(pwset) i += len(pwset) self.assertEqual(i, len(valid_passwds)) @@ -312,7 +312,7 @@ def testVerify(self): # Should be OK self.cli.verify(storage) keys = list(storage.essids.iterkeys('test')) - for i in xrange(25): + for i in range(25): key = random.choice(keys) results = storage.essids['test', key] corrupted = tuple((pw, 'x' * 32) for pw, pmk in results) @@ -338,7 +338,7 @@ def testExportPasswords(self): self.cli.import_passwords(storage, self.tempfile1) self.cli.export_passwords(storage, self.tempfile1) with cpyrit.util.FileWrapper(self.tempfile1) as f: - new_passwds = map(str.strip, f.readlines()) + new_passwds = list(map(str.strip, f.readlines())) self.assertEqual(sorted(test_passwds), sorted(new_passwds)) def testExportCowpatty(self): @@ -392,9 +392,9 @@ def getStorage(self): def corrupt(self, storage): conn = storage.engine.connect() # Destroy some passwords - keys = list(storage.passwords.iterkeys()) + keys = list(storage.passwords.keys()) tbl = cpyrit.storage.passwords_table - for i in xrange(13): + for i in range(13): key = random.choice(keys) sql = tbl.update().where(tbl.c._key == key) if i % 2 == 0: @@ -409,7 +409,7 @@ def corrupt(self, storage): # Destroy some results keys = list(storage.essids.iterkeys('test')) tbl = cpyrit.storage.results_table - for i in xrange(13): + for i in range(13): key = random.choice(keys) if i % 3 == 0: # Delete workunit @@ -494,18 +494,18 @@ def _runTests(case): return unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() if __name__ == "__main__": - print "Testing with filesystem-storage..." + print("Testing with filesystem-storage...") if not _runTests(FilesystemTestCase): sys.exit(1) # should have been imported by cpyrit.storage if 'sqlalchemy' not in sys.modules: - print "SQLAlchemy seems to be unavailable; skipping all tests..." + print("SQLAlchemy seems to be unavailable; skipping all tests...") else: - print "Testing with database-storage..." + print("Testing with database-storage...") if not _runTests(DatabaseTestCase): sys.exit(1) - print "Testing with RPC-storage..." + print("Testing with RPC-storage...") if not _runTests(RPCTestCase): sys.exit(1)