summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Mahn <dan@mahns.com>2011-03-02 09:06:18 -0500
committerMichael P. Soulier <msoulier@digitaltorque.ca>2011-03-02 09:06:18 -0500
commit83ab4377deebc712666416fae42c15ad1c3838ac (patch)
tree458547553a3e0d9972cea49ae3e2e1b575ca9681
parenta6cff4f0b23068218849e44718e7255b634a9872 (diff)
downloadtftpy-py3k-dan.tar.gz
Taking initial py3k work from Dan Mahn.py3k-dan
-rw-r--r--tftpy/TftpClient.py12
-rw-r--r--tftpy/TftpPacketFactory.py6
-rw-r--r--tftpy/TftpPacketTypes.py50
-rw-r--r--tftpy/TftpServer.py39
-rw-r--r--tftpy/TftpShared.py8
-rw-r--r--tftpy/TftpStates.py94
-rw-r--r--tftpy/__init__.py16
7 files changed, 114 insertions, 111 deletions
diff --git a/tftpy/TftpClient.py b/tftpy/TftpClient.py
index 5fbe733..de565da 100644
--- a/tftpy/TftpClient.py
+++ b/tftpy/TftpClient.py
@@ -3,9 +3,9 @@ instance of the client, and then use its upload or download method. Logging is
performed via a standard logging object set in TftpShared."""
import time, types
-from TftpShared import *
-from TftpPacketFactory import *
-from TftpStates import TftpContextClientDownload, TftpContextClientUpload
+from .TftpShared import *
+from .TftpPacketFactory import *
+from .TftpStates import TftpContextClientDownload, TftpContextClientUpload
class TftpClient(TftpSession):
"""This class is an implementation of a tftp client. Once instantiated, a
@@ -21,11 +21,11 @@ class TftpClient(TftpSession):
self.options = options
# FIXME: If the blksize is DEF_BLKSIZE, we should just skip sending
# it.
- if self.options.has_key('blksize'):
+ if 'blksize' in self.options:
size = self.options['blksize']
- tftpassert(types.IntType == type(size), "blksize must be an int")
+ tftpassert(int == type(size), "blksize must be an int")
if size < MIN_BLKSIZE or size > MAX_BLKSIZE:
- raise TftpException, "Invalid blksize: %d" % size
+ raise TftpException("Invalid blksize: %d" % size)
else:
self.options['blksize'] = DEF_BLKSIZE
diff --git a/tftpy/TftpPacketFactory.py b/tftpy/TftpPacketFactory.py
index d689185..b47bcd3 100644
--- a/tftpy/TftpPacketFactory.py
+++ b/tftpy/TftpPacketFactory.py
@@ -2,8 +2,8 @@
buffer, and return the appropriate TftpPacket object to represent it, via the
parse() method."""
-from TftpShared import *
-from TftpPacketTypes import *
+from .TftpShared import *
+from .TftpPacketTypes import *
class TftpPacketFactory(object):
"""This class generates TftpPacket objects. It is responsible for parsing
@@ -33,7 +33,7 @@ class TftpPacketFactory(object):
def __create(self, opcode):
"""This method returns the appropriate class object corresponding to
the passed opcode."""
- tftpassert(self.classes.has_key(opcode),
+ tftpassert(opcode in self.classes,
"Unsupported opcode: %d" % opcode)
packet = self.classes[opcode]()
diff --git a/tftpy/TftpPacketTypes.py b/tftpy/TftpPacketTypes.py
index 14cbd90..acc8108 100644
--- a/tftpy/TftpPacketTypes.py
+++ b/tftpy/TftpPacketTypes.py
@@ -2,7 +2,7 @@
corresponding encode and decode methods for them."""
import struct
-from TftpShared import *
+from .TftpShared import *
class TftpSession(object):
"""This class is the base class for the tftp client and server. Any shared
@@ -59,17 +59,17 @@ class TftpPacketWithOptions(object):
length = 0
for c in buffer:
#log.debug("iterating this byte: " + repr(c))
- if ord(c) == 0:
+ if c == 0:
log.debug("found a null at length %d" % length)
if length > 0:
format += "%dsx" % length
length = -1
else:
- raise TftpException, "Invalid options in buffer"
+ raise TftpException("Invalid options in buffer")
length += 1
log.debug("about to unpack, format is: %s" % format)
- mystruct = struct.unpack(format, buffer)
+ mystruct = list(x.decode('latin-1') for x in struct.unpack(format, buffer))
tftpassert(len(mystruct) % 2 == 0,
"packet with odd number of option/value pairs")
@@ -94,7 +94,7 @@ class TftpPacket(object):
order suitable for sending over the wire.
This is an abstract method."""
- raise NotImplementedError, "Abstract method"
+ raise NotImplementedError("Abstract method")
def decode(self):
"""The decode method of a TftpPacket takes a buffer off of the wire in
@@ -104,7 +104,7 @@ class TftpPacket(object):
datagram.
This is an abstract method."""
- raise NotImplementedError, "Abstract method"
+ raise NotImplementedError("Abstract method")
class TftpPacketInitial(TftpPacket, TftpPacketWithOptions):
"""This class is a common parent class for the RRQ and WRQ packets, as
@@ -133,18 +133,18 @@ class TftpPacketInitial(TftpPacket, TftpPacketWithOptions):
if self.mode == "octet":
format += "5sx"
else:
- raise AssertionError, "Unsupported mode: %s" % mode
+ raise AssertionError("Unsupported mode: %s" % mode)
# Add options.
options_list = []
- if self.options.keys() > 0:
+ if len(list(self.options.keys())) > 0:
log.debug("there are options to encode")
for key in self.options:
# Populate the option name
format += "%dsx" % len(key)
- options_list.append(key)
+ options_list.append(key.encode('latin-1'))
# Populate the option value
format += "%dsx" % len(str(self.options[key]))
- options_list.append(str(self.options[key]))
+ options_list.append(str(self.options[key]).encode('latin-1'))
log.debug("format is %s" % format)
log.debug("options_list is %s" % options_list)
@@ -152,8 +152,8 @@ class TftpPacketInitial(TftpPacket, TftpPacketWithOptions):
self.buffer = struct.pack(format,
self.opcode,
- self.filename,
- self.mode,
+ self.filename.encode('latin-1'),
+ self.mode.encode('latin-1'),
*options_list)
log.debug("buffer is " + repr(self.buffer))
@@ -170,7 +170,7 @@ class TftpPacketInitial(TftpPacket, TftpPacketWithOptions):
subbuf = self.buffer[2:]
for c in subbuf:
log.debug("iterating this byte: " + repr(c))
- if ord(c) == 0:
+ if c == 0:
nulls += 1
log.debug("found a null at length %d, now have %d"
% (length, nulls))
@@ -188,13 +188,13 @@ class TftpPacketInitial(TftpPacket, TftpPacketWithOptions):
shortbuf = subbuf[:tlength+1]
log.debug("about to unpack buffer with format: %s" % format)
log.debug("unpacking buffer: " + repr(shortbuf))
- mystruct = struct.unpack(format, shortbuf)
+ mystruct = list(x.decode('latin-1') for x in struct.unpack(format, shortbuf))
tftpassert(len(mystruct) == 2, "malformed packet")
+ log.debug("setting filename to %s" % mystruct[0])
+ log.debug("setting mode to %s" % mystruct[1])
self.filename = mystruct[0]
- self.mode = mystruct[1].lower() # force lc - bug 17
- log.debug("set filename to %s" % self.filename)
- log.debug("set mode to %s" % self.mode)
+ self.mode = mystruct[1]
self.options = self.decode_options(subbuf[tlength+1:])
return self
@@ -370,7 +370,7 @@ class TftpPacketERR(TftpPacket):
self.buffer = struct.pack(format,
self.opcode,
self.errorcode,
- self.errmsgs[self.errorcode])
+ self.errmsgs[self.errorcode].encode('latin-1'))
return self
def decode(self):
@@ -419,8 +419,8 @@ class TftpPacketOACK(TftpPacket, TftpPacketWithOptions):
log.debug("value is %s" % self.options[key])
format += "%dsx" % len(key)
format += "%dsx" % len(self.options[key])
- options_list.append(key)
- options_list.append(self.options[key])
+ options_list.append(key.encode('latin-1'))
+ options_list.append(self.options[key].encode('latin-1'))
self.buffer = struct.pack(format, self.opcode, *options_list)
return self
@@ -435,13 +435,13 @@ class TftpPacketOACK(TftpPacket, TftpPacketWithOptions):
the options so that the session can update itself to the negotiated
options."""
for name in self.options:
- if options.has_key(name):
+ if name in options:
if name == 'blksize':
# We can accept anything between the min and max values.
- size = self.options[name]
- if size >= MIN_BLKSIZE and size <= MAX_BLKSIZE:
+ size = int(self.options[name])
+ if (size >= MIN_BLKSIZE) and (size <= MAX_BLKSIZE):
log.debug("negotiated blksize of %d bytes" % size)
- options[blksize] = size
+ options['blksize'] = size
else:
- raise TftpException, "Unsupported option: %s" % name
+ raise TftpException("Unsupported option: %s" % name)
return True
diff --git a/tftpy/TftpServer.py b/tftpy/TftpServer.py
index 9e64d83..591d7a9 100644
--- a/tftpy/TftpServer.py
+++ b/tftpy/TftpServer.py
@@ -5,10 +5,10 @@ TftpShared."""
import socket, os, re, time, random
import select
-from TftpShared import *
-from TftpPacketTypes import *
-from TftpPacketFactory import *
-from TftpStates import *
+from .TftpShared import *
+from .TftpPacketTypes import *
+from .TftpPacketFactory import *
+from .TftpStates import *
class TftpServer(TftpSession):
"""This class implements a tftp server object. Run the listen() method to
@@ -18,13 +18,14 @@ class TftpServer(TftpSession):
read from during downloads. This permits the serving of dynamic
content."""
- def __init__(self, tftproot='/tftpboot', dyn_file_func=None):
+ def __init__(self, tftproot='/tftpboot', dyn_file_func=None, write_mode=TftpServerWriteMode.Overwrite):
self.listenip = None
self.listenport = None
self.sock = None
# FIXME: What about multiple roots?
self.root = os.path.abspath(tftproot)
self.dyn_file_func = dyn_file_func
+ self.write_mode = write_mode
# A dict of sessions, where each session is keyed by a string like
# ip:tid for the remote end.
self.sessions = {}
@@ -32,19 +33,19 @@ class TftpServer(TftpSession):
if os.path.exists(self.root):
log.debug("tftproot %s does exist" % self.root)
if not os.path.isdir(self.root):
- raise TftpException, "The tftproot must be a directory."
+ raise TftpException("The tftproot must be a directory.")
else:
log.debug("tftproot %s is a directory" % self.root)
if os.access(self.root, os.R_OK):
log.debug("tftproot %s is readable" % self.root)
else:
- raise TftpException, "The tftproot must be readable"
+ raise TftpException("The tftproot must be readable")
if os.access(self.root, os.W_OK):
log.debug("tftproot %s is writable" % self.root)
else:
log.warning("The tftproot %s is not writable" % self.root)
else:
- raise TftpException, "The tftproot does not exist."
+ raise TftpException("The tftproot does not exist.")
def listen(self,
listenip="",
@@ -64,7 +65,7 @@ class TftpServer(TftpSession):
# FIXME - sockets should be non-blocking
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((listenip, listenport))
- except socket.error, err:
+ except socket.error as err:
# Reraise it for now.
raise
@@ -99,25 +100,21 @@ class TftpServer(TftpSession):
# which should safely work through NAT.
key = "%s:%s" % (raddress, rport)
- if not self.sessions.has_key(key):
+ if key not in self.sessions:
log.debug("Creating new server context for "
"session key = %s" % key)
self.sessions[key] = TftpContextServer(raddress,
rport,
timeout,
self.root,
- self.dyn_file_func)
- try:
- self.sessions[key].start(buffer)
- except TftpException, err:
- deletion_list.append(key)
- log.error("Fatal exception thrown from "
- "session %s: %s" % (key, str(err)))
+ self.dyn_file_func,
+ self.write_mode)
+ self.sessions[key].start(buffer)
else:
log.warn("received traffic on main socket for "
"existing session??")
log.info("Currently handling these sessions:")
- for session_key, session in self.sessions.items():
+ for session_key, session in list(self.sessions.items()):
log.info(" %s" % session)
else:
@@ -131,7 +128,7 @@ class TftpServer(TftpSession):
if self.sessions[key].state == None:
log.info("Successful transfer.")
deletion_list.append(key)
- except TftpException, err:
+ except TftpException as err:
deletion_list.append(key)
log.error("Fatal exception thrown from "
"session %s: %s"
@@ -149,7 +146,7 @@ class TftpServer(TftpSession):
for key in self.sessions:
try:
self.sessions[key].checkTimeout(now)
- except TftpException, err:
+ except TftpException as err:
log.error(str(err))
deletion_list.append(key)
@@ -157,7 +154,7 @@ class TftpServer(TftpSession):
for key in deletion_list:
log.info('')
log.info("Session %s complete" % key)
- if self.sessions.has_key(key):
+ if key in self.sessions:
log.debug("Gathering up metrics from session before deleting")
self.sessions[key].end()
metrics = self.sessions[key].metrics
diff --git a/tftpy/TftpShared.py b/tftpy/TftpShared.py
index 69ade90..167beb1 100644
--- a/tftpy/TftpShared.py
+++ b/tftpy/TftpShared.py
@@ -23,7 +23,7 @@ def tftpassert(condition, msg):
with the message passed. This just makes the code throughout cleaner
by refactoring."""
if not condition:
- raise TftpException, msg
+ raise TftpException(msg)
def setLogLevel(level):
"""This function is a utility function for setting the internal log level.
@@ -49,3 +49,9 @@ class TftpException(Exception):
"""This class is the parent class of all exceptions regarding the handling
of the TFTP protocol."""
pass
+
+class TftpServerWriteMode(object):
+ """This class defines the server write modes."""
+ Overwrite = 0
+ WriteNew = 1
+ DenyWrite = 2
diff --git a/tftpy/TftpStates.py b/tftpy/TftpStates.py
index 142029c..5362fa1 100644
--- a/tftpy/TftpStates.py
+++ b/tftpy/TftpStates.py
@@ -9,9 +9,9 @@ the next packet in the transfer, and returns a state object until the transfer
is complete, at which point it returns None. That is, unless there is a fatal
error, in which case a TftpException is returned instead."""
-from TftpShared import *
-from TftpPacketTypes import *
-from TftpPacketFactory import *
+from .TftpShared import *
+from .TftpPacketTypes import *
+from .TftpPacketFactory import *
import socket, time, os, sys
###############################################################################
@@ -53,7 +53,7 @@ class TftpMetrics(object):
def add_dup(self, blocknumber):
"""This method adds a dup for a block number to the metrics."""
log.debug("Recording a dup for block %d" % blocknumber)
- if self.dups.has_key(blocknumber):
+ if blocknumber in self.dups:
self.dups[blocknumber] += 1
else:
self.dups[blocknumber] = 1
@@ -67,7 +67,7 @@ class TftpMetrics(object):
class TftpContext(object):
"""The base class of the contexts."""
- def __init__(self, host, port, timeout, dyn_file_func=None):
+ def __init__(self, host, port, timeout, dyn_file_func=None, write_mode=TftpServerWriteMode.Overwrite):
"""Constructor for the base context, setting shared instance
variables."""
self.file_to_transfer = None
@@ -94,6 +94,7 @@ class TftpContext(object):
# The last DAT packet we sent, if applicable, to make resending easy.
self.last_dat_pkt = None
self.dyn_file_func = dyn_file_func
+ self.write_mode = write_mode
def __del__(self):
"""Simple destructor to try to call housekeeping in the end method if
@@ -105,17 +106,17 @@ class TftpContext(object):
"""Compare current time with last_update time, and raise an exception
if we're over SOCK_TIMEOUT time."""
if now - self.last_update > SOCK_TIMEOUT:
- raise TftpException, "Timeout waiting for traffic"
+ raise TftpException("Timeout waiting for traffic")
def start(self):
- raise NotImplementedError, "Abstract method"
+ raise NotImplementedError("Abstract method")
def end(self):
"""Perform session cleanup, since the end method should always be
called explicitely by the calling code, this works better than the
destructor."""
log.debug("in TftpContext.end")
- if self.fileobj is not None and not self.fileobj.closed:
+ if not self.fileobj.closed:
log.debug("self.fileobj is open - closing")
self.fileobj.close()
@@ -132,7 +133,7 @@ class TftpContext(object):
host = property(gethost, sethost)
def setNextBlock(self, block):
- if block >= 2 ** 16:
+ if block > 2 ** 16:
log.debug("Block number rollover to 0 again")
block = 0
self.__eblock = block
@@ -151,12 +152,12 @@ class TftpContext(object):
log.debug("In cycle, receive attempt %d" % i)
try:
(buffer, (raddress, rport)) = self.sock.recvfrom(MAX_BLKSIZE)
- except socket.timeout, err:
+ except socket.timeout as err:
log.warn("Timeout waiting for traffic, retrying...")
continue
break
else:
- raise TftpException, "Hit max timeouts, giving up."
+ raise TftpException("Hit max timeouts, giving up.")
# Ok, we've received a packet. Log it.
log.debug("Received %d bytes from %s:%s"
@@ -190,18 +191,20 @@ class TftpContext(object):
class TftpContextServer(TftpContext):
"""The context for the server."""
- def __init__(self, host, port, timeout, root, dyn_file_func=None):
+ def __init__(self, host, port, timeout, root, dyn_file_func=None, write_mode=TftpServerWriteMode.Overwrite):
TftpContext.__init__(self,
host,
port,
timeout,
- dyn_file_func
+ dyn_file_func,
+ write_mode
)
# At this point we have no idea if this is a download or an upload. We
# need to let the start state determine that.
self.state = TftpStateServerStart(self)
self.root = root
self.dyn_file_func = dyn_file_func
+ self.write_mode = write_mode
def __str__(self):
return "%s:%s %s" % (self.host, self.port, self.state)
@@ -372,12 +375,12 @@ class TftpState(object):
def handle(self, pkt, raddress, rport):
"""An abstract method for handling a packet. It is expected to return
a TftpState object, either itself or a new state."""
- raise NotImplementedError, "Abstract method"
+ raise NotImplementedError("Abstract method")
def handleOACK(self, pkt):
"""This method handles an OACK from the server, syncing any accepted
options."""
- if pkt.options.keys() > 0:
+ if len(list(pkt.options.keys())) > 0:
if pkt.match_options(self.context.options):
log.info("Successful negotiation of options")
# Set options to OACK options
@@ -386,9 +389,9 @@ class TftpState(object):
log.info(" %s = %s" % (key, self.context.options[key]))
else:
log.error("Failed to negotiate options")
- raise TftpException, "Failed to negotiate options"
+ raise TftpException("Failed to negotiate options")
else:
- raise TftpException, "No options found in OACK"
+ raise TftpException("No options found in OACK")
def returnSupportedOptions(self, options):
"""This method takes a requested options list from a client, and
@@ -441,8 +444,7 @@ class TftpState(object):
# FIXME - only octet mode is supported at this time.
if pkt.mode != 'octet':
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, \
- "Only octet transfers are supported at this time."
+ raise TftpException("Only octet transfers are supported at this time.")
# test host/port of client end
if self.context.host != raddress or self.context.port != rport:
@@ -462,7 +464,7 @@ class TftpState(object):
# FIXME: Should we allow subdirectories?
if pkt.filename.find(os.sep) >= 0:
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "%s found in filename, not permitted" % os.sep
+ raise TftpException("%s found in filename, not permitted" % os.sep)
self.context.file_to_transfer = pkt.filename
@@ -560,7 +562,7 @@ class TftpState(object):
if pkt.blocknumber == 0:
log.warn("There is no block zero!")
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "There is no block zero!"
+ raise TftpException("There is no block zero!")
log.warn("Dropping duplicate block %d" % pkt.blocknumber)
self.context.metrics.add_dup(pkt.blocknumber)
log.debug("ACKing block %d again, just in case" % pkt.blocknumber)
@@ -571,7 +573,7 @@ class TftpState(object):
msg = "Whoa! Received future block %d but expected %d" \
% (pkt.blocknumber, self.context.next_block)
log.error(msg)
- raise TftpException, msg
+ raise TftpException(msg)
# Default is to ack
return TftpStateExpectDAT(self.context)
@@ -593,15 +595,9 @@ class TftpStateServerRecvRRQ(TftpState):
log.debug("No such file %s but using dyn_file_func" % path)
self.context.fileobj = \
self.context.dyn_file_func(self.context.file_to_transfer)
-
- if self.context.fileobj is None:
- log.debug("dyn_file_func returned 'None', treating as "
- "FileNotFound")
- self.sendError(TftpErrors.FileNotFound)
- raise TftpException, "File not found: %s" % path
else:
self.sendError(TftpErrors.FileNotFound)
- raise TftpException, "File not found: %s" % path
+ raise TftpException("File not found: %s" % path)
# Options negotiation.
if sendoack:
@@ -629,6 +625,12 @@ class TftpStateServerRecvWRQ(TftpState):
log.debug("In TftpStateServerRecvWRQ.handle")
sendoack = self.serverInitial(pkt, raddress, rport)
path = self.context.root + os.sep + self.context.file_to_transfer
+ if (self.context.write_mode == TftpServerWriteMode.WriteNew) and os.path.exists(path):
+ self.sendError(TftpErrors.FileAlreadyExists)
+ raise TftpException("File already exists: %s" % path)
+ elif self.context.write_mode == TftpServerWriteMode.DenyWrite:
+ self.sendError(TftpErrors.DiskFull)
+ raise TftpException("Configured for read only operation: %s" % path)
log.info("Opening file %s for writing" % path)
if os.path.exists(path):
# FIXME: correct behavior?
@@ -674,8 +676,7 @@ class TftpStateServerStart(TftpState):
rport)
else:
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, \
- "Invalid packet to begin up/download: %s" % pkt
+ raise TftpException("Invalid packet to begin up/download: %s" % pkt)
class TftpStateExpectACK(TftpState):
"""This class represents the state of the transfer when a DAT was just
@@ -708,8 +709,7 @@ class TftpStateExpectACK(TftpState):
return self
elif isinstance(pkt, TftpPacketERR):
log.error("Received ERR packet from peer: %s" % str(pkt))
- raise TftpException, \
- "Received ERR packet from peer: %s" % str(pkt)
+ raise TftpException("Received ERR packet from peer: %s" % str(pkt))
else:
log.warn("Discarding unsupported packet: %s" % str(pkt))
return self
@@ -725,19 +725,19 @@ class TftpStateExpectDAT(TftpState):
elif isinstance(pkt, TftpPacketACK):
# Umm, we ACK, you don't.
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ACK from peer when expecting DAT"
+ raise TftpException("Received ACK from peer when expecting DAT")
elif isinstance(pkt, TftpPacketWRQ):
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received WRQ from peer when expecting DAT"
+ raise TftpException("Received WRQ from peer when expecting DAT")
elif isinstance(pkt, TftpPacketERR):
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ERR from peer: " + str(pkt)
+ raise TftpException("Received ERR from peer: " + str(pkt))
else:
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received unknown packet type from peer: " + str(pkt)
+ raise TftpException("Received unknown packet type from peer: " + str(pkt))
class TftpStateSentWRQ(TftpState):
"""Just sent an WRQ packet for an upload."""
@@ -753,7 +753,7 @@ class TftpStateSentWRQ(TftpState):
log.info("Received OACK from server")
try:
self.handleOACK(pkt)
- except TftpException, err:
+ except TftpException as err:
log.error("Failed to negotiate options")
self.sendError(TftpErrors.FailedNegotiation)
raise
@@ -780,19 +780,19 @@ class TftpStateSentWRQ(TftpState):
elif isinstance(pkt, TftpPacketERR):
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ERR from server: " + str(pkt)
+ raise TftpException("Received ERR from server: " + str(pkt))
elif isinstance(pkt, TftpPacketRRQ):
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received RRQ from server while in upload"
+ raise TftpException("Received RRQ from server while in upload")
elif isinstance(pkt, TftpPacketDAT):
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received DAT from server while in upload"
+ raise TftpException("Received DAT from server while in upload")
else:
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received unknown packet type from server: " + str(pkt)
+ raise TftpException("Received unknown packet type from server: " + str(pkt))
# By default, no state change.
return self
@@ -810,7 +810,7 @@ class TftpStateSentRRQ(TftpState):
log.info("Received OACK from server")
try:
self.handleOACK(pkt)
- except TftpException, err:
+ except TftpException as err:
log.error("Failed to negotiate options: %s" % str(err))
self.sendError(TftpErrors.FailedNegotiation)
raise
@@ -835,19 +835,19 @@ class TftpStateSentRRQ(TftpState):
elif isinstance(pkt, TftpPacketACK):
# Umm, we ACK, the server doesn't.
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ACK from server while in download"
+ raise TftpException("Received ACK from server while in download")
elif isinstance(pkt, TftpPacketWRQ):
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received WRQ from server while in download"
+ raise TftpException("Received WRQ from server while in download")
elif isinstance(pkt, TftpPacketERR):
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received ERR from server: " + str(pkt)
+ raise TftpException("Received ERR from server: " + str(pkt))
else:
self.sendError(TftpErrors.IllegalTftpOp)
- raise TftpException, "Received unknown packet type from server: " + str(pkt)
+ raise TftpException("Received unknown packet type from server: " + str(pkt))
# By default, no state change.
return self
diff --git a/tftpy/__init__.py b/tftpy/__init__.py
index b1400df..9a13121 100644
--- a/tftpy/__init__.py
+++ b/tftpy/__init__.py
@@ -10,13 +10,13 @@ directly. The TftpClient and TftpServer classes can be reached through it.
import sys
-# Make sure that this is at least Python 2.3
+# Make sure that this is at least Python 3.1
verlist = sys.version_info
-if not verlist[0] >= 2 or not verlist[1] >= 3:
- raise AssertionError, "Requires at least Python 2.3"
+if not verlist[0] >= 3 or not verlist[1] >= 1:
+ raise AssertionError("Requires at least Python 3.1")
-from TftpShared import *
-from TftpPacketTypes import *
-from TftpPacketFactory import *
-from TftpClient import *
-from TftpServer import *
+from .TftpShared import *
+from .TftpPacketTypes import *
+from .TftpPacketFactory import *
+from .TftpClient import *
+from .TftpServer import *