* test_*.py: new lambda syntax (also affects tests for filter, map,
reduce) * ftplib.py: added default callback for retrlines; added dir() method * ftplib.py: don't return self in self.connect(); added hack so that if 'CDUP' is not understood, 'CWD ..' is tried. * ftplib.py: second method called init() should have been called connect(); if __init__ sees more than one argument, it will also try to login().
This commit is contained in:
parent
590baa4a7a
commit
ae3b3a33d8
|
@ -0,0 +1,18 @@
|
|||
# A more or less complete user-defined wrapper around dictionary objects
|
||||
|
||||
class UserDict:
|
||||
def __init__(self): self.data = {}
|
||||
def __repr__(self): return repr(self.data)
|
||||
def __cmp__(self, dict):
|
||||
if type(dict) == type(self.data):
|
||||
return cmp(self.data, dict)
|
||||
else:
|
||||
return cmp(self.data, dict.data)
|
||||
def __len__(self): return len(self.data)
|
||||
def __getitem__(self, key): return self.data[key]
|
||||
def __setitem__(self, key, item): self.data[key] = item
|
||||
def __delitem__(self, key): del self.data[key]
|
||||
def keys(self): return self.data.keys()
|
||||
def items(self): return self.data.items()
|
||||
def values(self): return self.data.values()
|
||||
def has_key(self, key): return self.data.has_key(key)
|
|
@ -0,0 +1,39 @@
|
|||
# A more or less complete user-defined wrapper around list objects
|
||||
|
||||
class UserList:
|
||||
def __init__(self, *args):
|
||||
if len(args) > 1: raise TypeError, 'too many args'
|
||||
self.data = []
|
||||
if args:
|
||||
list = args[0]
|
||||
if type(list) == type(self.data):
|
||||
self.data[:] = list
|
||||
else:
|
||||
self.data[:] = list.data[:]
|
||||
def __repr__(self): return repr(self.data)
|
||||
def __cmp__(self, list):
|
||||
if type(list) == type(self.data):
|
||||
return cmp(self.data, list)
|
||||
else:
|
||||
return cmp(self.data, list.data)
|
||||
def __len__(self): return len(self.data)
|
||||
def __getitem__(self, i): return self.data[i]
|
||||
def __setitem__(self, i, item): self.data[i] = item
|
||||
def __delitem__(self, i): del self.data[i]
|
||||
def __getslice__(self, i, j):
|
||||
userlist = UserList()
|
||||
userlist.data[:] = self.data[i:j]
|
||||
return userlist
|
||||
def __setslice__(self, i, j, list):
|
||||
if type(list) == type(self.data):
|
||||
self.data[i:j] = list
|
||||
else:
|
||||
self.data[i:j] = list.data
|
||||
def __delslice__(self, i, j): del self.data[i:j]
|
||||
def append(self, item): self.data.append(item)
|
||||
def insert(self, i, item): self.data.insert(i, item)
|
||||
def remove(self, item): self.data.remove(item)
|
||||
def count(self, item): return self.data.count(item)
|
||||
def index(self, item): return self.data.index(item)
|
||||
def reverse(self): self.data.reverse()
|
||||
def sort(self, *args): apply(self.data.sort, args)
|
|
@ -1,6 +1,8 @@
|
|||
# An FTP client class. Based on RFC 959: File Transfer Protocol
|
||||
# (FTP), by J. Postel and J. Reynolds
|
||||
|
||||
# Changes and improvements suggested by Steve Majewski
|
||||
|
||||
|
||||
# Example:
|
||||
#
|
||||
|
@ -70,6 +72,8 @@ class FTP:
|
|||
|
||||
# New initialization method (called by class instantiation)
|
||||
# Initialize host to localhost, port to standard ftp port
|
||||
# Optional arguments are host (for connect()),
|
||||
# and user, passwd, acct (for login())
|
||||
def __init__(self, *args):
|
||||
# Initialize the instance to something mostly harmless
|
||||
self.debugging = 0
|
||||
|
@ -79,7 +83,9 @@ class FTP:
|
|||
self.file = None
|
||||
self.welcome = None
|
||||
if args:
|
||||
apply(self.connect, args)
|
||||
self.connect(args[0])
|
||||
if args[1:]:
|
||||
apply(self.login, args[1:])
|
||||
|
||||
# Old init method (explicitly called by caller)
|
||||
def init(self, *args):
|
||||
|
@ -89,7 +95,7 @@ class FTP:
|
|||
# Connect to host. Arguments:
|
||||
# - host: hostname to connect to (default previous host)
|
||||
# - port: port to connect to (default previous port)
|
||||
def init(self, *args):
|
||||
def connect(self, *args):
|
||||
if args: self.host = args[0]
|
||||
if args[1:]: self.port = args[1]
|
||||
if args[2:]: raise TypeError, 'too many args'
|
||||
|
@ -97,7 +103,6 @@ class FTP:
|
|||
self.sock.connect(self.host, self.port)
|
||||
self.file = self.sock.makefile('r')
|
||||
self.welcome = self.getresp()
|
||||
return self
|
||||
|
||||
# Get the welcome message from the server
|
||||
# (this is read and squirreled away by init())
|
||||
|
@ -276,8 +281,14 @@ class FTP:
|
|||
# Retrieve data in line mode.
|
||||
# The argument is a RETR or LIST command.
|
||||
# The callback function is called for each line, with trailing
|
||||
# CRLF stripped. This creates a new port for you
|
||||
def retrlines(self, cmd, callback):
|
||||
# CRLF stripped. This creates a new port for you.
|
||||
# print_lines is the default callback
|
||||
def retrlines(self, cmd, args):
|
||||
callback = None
|
||||
if args:
|
||||
callback = args[0]
|
||||
if args[1:]: raise TypeError, 'too many args'
|
||||
if not callback: callback = print_line
|
||||
resp = self.sendcmd('TYPE A')
|
||||
conn = self.transfercmd(cmd)
|
||||
fp = conn.makefile('r')
|
||||
|
@ -328,6 +339,20 @@ class FTP:
|
|||
self.retrlines(cmd, files.append)
|
||||
return files
|
||||
|
||||
# List a directory in long form. By default list current directory
|
||||
# to stdout. Optional last argument is callback function;
|
||||
# all non-empty arguments before it are concatenated to the
|
||||
# LIST command. (This *should* only be used for a pathname.)
|
||||
def dir(self, *args):
|
||||
cmd = 'LIST'
|
||||
func = None
|
||||
if args[-1:] and type(args[-1]) != type(''):
|
||||
args, func = args[:-1], args[-1]
|
||||
for arg in args:
|
||||
if arg:
|
||||
cmd = cmd + (' ' + arg)
|
||||
self.retrlines(cmd, func)
|
||||
|
||||
# Rename a file
|
||||
def rename(self, fromname, toname):
|
||||
resp = self.sendcmd('RNFR ' + fromname)
|
||||
|
@ -338,9 +363,13 @@ class FTP:
|
|||
# Change to a directory
|
||||
def cwd(self, dirname):
|
||||
if dirname == '..':
|
||||
cmd = 'CDUP'
|
||||
else:
|
||||
cmd = 'CWD ' + dirname
|
||||
try:
|
||||
self.voidcmd('CDUP')
|
||||
return
|
||||
except error_perm, msg:
|
||||
if msg[:3] != '500':
|
||||
raise error_perm, msg
|
||||
cmd = 'CWD ' + dirname
|
||||
self.voidcmd(cmd)
|
||||
|
||||
# Retrieve the size of a file
|
||||
|
@ -390,6 +419,10 @@ def parse257(resp):
|
|||
dirname = dirname + c
|
||||
return dirname
|
||||
|
||||
# Default retrlines callback to print a line
|
||||
def print_line(line):
|
||||
print line
|
||||
|
||||
|
||||
# Test program.
|
||||
# Usage: ftp [-d] host [-l[dir]] [-d[dir]] [file] ...
|
||||
|
@ -409,12 +442,9 @@ def test():
|
|||
ftp = FTP(host)
|
||||
ftp.set_debuglevel(debugging)
|
||||
ftp.login()
|
||||
def writeln(line): print line
|
||||
for file in sys.argv[2:]:
|
||||
if file[:2] == '-l':
|
||||
cmd = 'LIST'
|
||||
if file[2:]: cmd = cmd + ' ' + file[2:]
|
||||
ftp.retrlines(cmd, writeln)
|
||||
ftp.dir(file[2:])
|
||||
elif file[:2] == '-d':
|
||||
cmd = 'CWD'
|
||||
if file[2:]: cmd = cmd + ' ' + file[2:]
|
||||
|
|
|
@ -91,11 +91,11 @@ execfile(TESTFN)
|
|||
unlink(TESTFN)
|
||||
|
||||
print 'filter'
|
||||
if filter("c: 'a' <= c <= 'z'", 'Hello World') <> 'elloorld':
|
||||
if filter(lambda c: 'a' <= c <= 'z', 'Hello World') <> 'elloorld':
|
||||
raise TestFailed, 'filter (filter a string)'
|
||||
if filter(None, [1, 'hello', [], [3], '', None, 9, 0]) <> [1, 'hello', [3], 9]:
|
||||
raise TestFailed, 'filter (remove false values)'
|
||||
if filter('x: x > 0', [1, -3, 9, 0, 2]) <> [1, 9, 2]:
|
||||
if filter(lambda x: x > 0, [1, -3, 9, 0, 2]) <> [1, 9, 2]:
|
||||
raise TestFailed, 'filter (keep positives)'
|
||||
|
||||
print 'float'
|
||||
|
@ -120,11 +120,6 @@ if int(314) <> 314: raise TestFailed, 'int(314)'
|
|||
if int(3.14) <> 3: raise TestFailed, 'int(3.14)'
|
||||
if int(314L) <> 314: raise TestFailed, 'int(314L)'
|
||||
|
||||
print 'lambda'
|
||||
binary_plus = lambda('x, y: x+y')
|
||||
if binary_plus(2, 10) <> 12:
|
||||
raise TestFailed, 'binary_plus(2, 10)'
|
||||
|
||||
print 'len'
|
||||
if len('123') <> 3: raise TestFailed, 'len(\'123\')'
|
||||
if len(()) <> 0: raise TestFailed, 'len(())'
|
||||
|
@ -146,13 +141,13 @@ if map(None, 'abcd', 'efg') <> \
|
|||
raise TestFailed, 'map(None, \'abcd\', \'efg\')'
|
||||
if map(None, range(10)) <> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
|
||||
raise TestFailed, 'map(None, range(10))'
|
||||
if map('x: x*x', range(1,4)) <> [1, 4, 9]:
|
||||
raise TestFailed, 'map(\'x: x*x\', range(1,4))'
|
||||
if map(lambda x: x*x, range(1,4)) <> [1, 4, 9]:
|
||||
raise TestFailed, 'map(lambda x: x*x, range(1,4))'
|
||||
from math import sqrt
|
||||
if map('x: map(sqrt,x)', [[16, 4], [81, 9]]) <> [[4.0, 2.0], [9.0, 3.0]]:
|
||||
raise TestFailed, map('x: map(sqrt,x)', [[16, 4], [81, 9]])
|
||||
if map('x,y: x+y', [1,3,2], [9,1,4]) <> [10, 4, 6]:
|
||||
raise TestFailed, 'map(\'x,y: x+y\', [1,3,2], [9,1,4])'
|
||||
if map(lambda x: map(sqrt,x), [[16, 4], [81, 9]]) <> [[4.0, 2.0], [9.0, 3.0]]:
|
||||
raise TestFailed, 'map(lambda x: map(sqrt,x), [[16, 4], [81, 9]])'
|
||||
if map(lambda x, y: x+y, [1,3,2], [9,1,4]) <> [10, 4, 6]:
|
||||
raise TestFailed, 'map(lambda x,y: x+y, [1,3,2], [9,1,4])'
|
||||
def plus(*v):
|
||||
accu = 0
|
||||
for i in v: accu = accu + i
|
||||
|
|
|
@ -112,13 +112,14 @@ finally:
|
|||
fp.close()
|
||||
|
||||
print 'reduce'
|
||||
if reduce('x,y:x+y', ['a', 'b', 'c'], '') <> 'abc':
|
||||
if reduce(lambda x, y: x+y, ['a', 'b', 'c'], '') <> 'abc':
|
||||
raise TestFailed, 'reduce(): implode a string'
|
||||
if reduce('x,y:x+y', [['a', 'c'], [], ['d', 'w']], []) <> ['a','c','d','w']:
|
||||
if reduce(lambda x, y: x+y,
|
||||
[['a', 'c'], [], ['d', 'w']], []) <> ['a','c','d','w']:
|
||||
raise TestFailed, 'reduce(): append'
|
||||
if reduce('x,y: x*y', range(2,8), 1) <> 5040:
|
||||
if reduce(lambda x, y: x*y, range(2,8), 1) <> 5040:
|
||||
raise TestFailed, 'reduce(): compute 7!'
|
||||
if reduce('x,y:x*y', range(2,21), 1L) <> 2432902008176640000L:
|
||||
if reduce(lambda x, y: x*y, range(2,21), 1L) <> 2432902008176640000L:
|
||||
raise TestFailed, 'reduce(): compute 20!, use long'
|
||||
|
||||
print 'reload'
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# Testing select module
|
||||
|
||||
from test_support import *
|
||||
|
||||
def test():
|
||||
import select
|
||||
import os
|
||||
|
|
|
@ -79,7 +79,6 @@ float
|
|||
getattr
|
||||
hex
|
||||
int
|
||||
lambda
|
||||
len
|
||||
long
|
||||
map
|
||||
|
|
Loading…
Reference in New Issue