Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
d78def94
Kaydet (Commit)
d78def94
authored
May 06, 2011
tarafından
Giampaolo Rodola'
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #11072: added MLSD command (RFC-3659) support to ftplib.
üst
0872816d
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
139 additions
and
8 deletions
+139
-8
ftplib.rst
Doc/library/ftplib.rst
+23
-6
ftplib.py
Lib/ftplib.py
+29
-1
test_ftplib.py
Lib/test/test_ftplib.py
+85
-1
NEWS
Misc/NEWS
+2
-0
No files found.
Doc/library/ftplib.rst
Dosyayı görüntüle @
d78def94
...
...
@@ -254,13 +254,12 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
Retrieve a file or directory listing in ASCII transfer mode. *cmd* should be
an appropriate ``RETR`` command (see :meth:`retrbinary`) or a command such as
``LIST``
, ``NLST`` or ``MLSD
`` (usually just the string ``'LIST'``).
``LIST``
or ``NLST
`` (usually just the string ``'LIST'``).
``LIST`` retrieves a list of files and information about those files.
``NLST`` retrieves a list of file names. On some servers, ``MLSD`` retrieves
a machine readable list of files and information about those files. The
*callback* function is called for each line with a string argument containing
the line with the trailing CRLF stripped. The default *callback* prints the
line to ``sys.stdout``.
``NLST`` retrieves a list of file names.
The *callback* function is called for each line with a string argument
containing the line with the trailing CRLF stripped. The default *callback*
prints the line to ``sys.stdout``.
.. method:: FTP.set_pasv(boolean)
...
...
@@ -320,6 +319,20 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
in :meth:`transfercmd`.
.. method:: FTP.mlsd(path="", facts=[])
List a directory in a standardized format by using MLSD command
(:rfc:`3659`). If *path* is omitted the current directory is assumed.
*facts* is a list of strings representing the type of information desired
(e.g. *["type", "size", "perm"]*). Return a generator object yielding a
tuple of two elements for every file found in path. First element is the
file name, the second one is a dictionary including a variable number of
"facts" depending on the server and whether *facts* argument has been
provided.
.. versionadded:: 3.3
.. method:: FTP.nlst(argument[, ...])
Return a list of file names as returned by the ``NLST`` command. The
...
...
@@ -327,6 +340,8 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
directory). Multiple arguments can be used to pass non-standard options to
the ``NLST`` command.
.. deprecated:: 3.3 use :meth:`mlsd` instead
.. method:: FTP.dir(argument[, ...])
...
...
@@ -337,6 +352,8 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
as a *callback* function as for :meth:`retrlines`; the default prints to
``sys.stdout``. This method returns ``None``.
.. deprecated:: 3.3 use :meth:`mlsd` instead
.. method:: FTP.rename(fromname, toname)
...
...
Lib/ftplib.py
Dosyayı görüntüle @
d78def94
...
...
@@ -426,7 +426,7 @@ class FTP:
"""Retrieve data in line mode. A new port is created for you.
Args:
cmd: A RETR, LIST,
NLST, or MLSD
command.
cmd: A RETR, LIST,
or NLST
command.
callback: An optional single parameter callable that is called
for each line with the trailing CRLF stripped.
[default: print_line()]
...
...
@@ -527,6 +527,34 @@ class FTP:
cmd
=
cmd
+
(
' '
+
arg
)
self
.
retrlines
(
cmd
,
func
)
def
mlsd
(
self
,
path
=
""
,
facts
=
[]):
'''List a directory in a standardized format by using MLSD
command (RFC-3659). If path is omitted the current directory
is assumed. "facts" is a list of strings representing the type
of information desired (e.g. ["type", "size", "perm"]).
Return a generator object yielding a tuple of two elements
for every file found in path.
First element is the file name, the second one is a dictionary
including a variable number of "facts" depending on the server
and whether "facts" argument has been provided.
'''
if
facts
:
self
.
sendcmd
(
"OPTS MLST "
+
";"
.
join
(
facts
)
+
";"
)
if
path
:
cmd
=
"MLSD
%
s"
%
path
else
:
cmd
=
"MLSD"
lines
=
[]
self
.
retrlines
(
cmd
,
lines
.
append
)
for
line
in
lines
:
facts_found
,
_
,
name
=
line
.
rstrip
(
CRLF
)
.
partition
(
' '
)
entry
=
{}
for
fact
in
facts_found
[:
-
1
]
.
split
(
";"
):
key
,
_
,
value
=
fact
.
partition
(
"="
)
entry
[
key
.
lower
()]
=
value
yield
(
name
,
entry
)
def
rename
(
self
,
fromname
,
toname
):
'''Rename a file.'''
resp
=
self
.
sendcmd
(
'RNFR '
+
fromname
)
...
...
Lib/test/test_ftplib.py
Dosyayı görüntüle @
d78def94
...
...
@@ -22,10 +22,25 @@ from test.support import HOST
threading
=
support
.
import_module
(
'threading'
)
# the dummy data returned by server over the data channel when
# RETR, LIST
and NLST
commands are issued
# RETR, LIST
, NLST, MLSD
commands are issued
RETR_DATA
=
'abcde12345
\r\n
'
*
1000
LIST_DATA
=
'foo
\r\n
bar
\r\n
'
NLST_DATA
=
'foo
\r\n
bar
\r\n
'
MLSD_DATA
=
(
"type=cdir;perm=el;unique==keVO1+ZF4; test
\r\n
"
"type=pdir;perm=e;unique==keVO1+d?3; ..
\r\n
"
"type=OS.unix=slink:/foobar;perm=;unique==keVO1+4G4; foobar
\r\n
"
"type=OS.unix=chr-13/29;perm=;unique==keVO1+5G4; device
\r\n
"
"type=OS.unix=blk-11/108;perm=;unique==keVO1+6G4; block
\r\n
"
"type=file;perm=awr;unique==keVO1+8G4; writable
\r\n
"
"type=dir;perm=cpmel;unique==keVO1+7G4; promiscuous
\r\n
"
"type=dir;perm=;unique==keVO1+1t2; no-exec
\r\n
"
"type=file;perm=r;unique==keVO1+EG4; two words
\r\n
"
"type=file;perm=r;unique==keVO1+IH4; leading space
\r\n
"
"type=file;perm=r;unique==keVO1+1G4; file1
\r\n
"
"type=dir;perm=cpmel;unique==keVO1+7G4; incoming
\r\n
"
"type=file;perm=r;unique==keVO1+1G4; file2
\r\n
"
"type=file;perm=r;unique==keVO1+1G4; file3
\r\n
"
"type=file;perm=r;unique==keVO1+1G4; file4
\r\n
"
)
class
DummyDTPHandler
(
asynchat
.
async_chat
):
...
...
@@ -49,6 +64,11 @@ class DummyDTPHandler(asynchat.async_chat):
self
.
dtp_conn_closed
=
True
def
push
(
self
,
what
):
if
self
.
baseclass
.
next_data
is
not
None
:
what
=
self
.
baseclass
.
next_data
self
.
baseclass
.
next_data
=
None
if
not
what
:
return
self
.
close_when_done
()
super
(
DummyDTPHandler
,
self
)
.
push
(
what
.
encode
(
'ascii'
))
def
handle_error
(
self
):
...
...
@@ -67,6 +87,7 @@ class DummyFTPHandler(asynchat.async_chat):
self
.
last_received_cmd
=
None
self
.
last_received_data
=
''
self
.
next_response
=
''
self
.
next_data
=
None
self
.
rest
=
None
self
.
push
(
'220 welcome'
)
...
...
@@ -208,6 +229,14 @@ class DummyFTPHandler(asynchat.async_chat):
self
.
dtp
.
push
(
NLST_DATA
)
self
.
dtp
.
close_when_done
()
def
cmd_opts
(
self
,
arg
):
self
.
push
(
'200 opts ok'
)
def
cmd_mlsd
(
self
,
arg
):
self
.
push
(
'125 mlsd ok'
)
self
.
dtp
.
push
(
MLSD_DATA
)
self
.
dtp
.
close_when_done
()
class
DummyFTPServer
(
asyncore
.
dispatcher
,
threading
.
Thread
):
...
...
@@ -550,6 +579,61 @@ class TestFTPClass(TestCase):
self
.
client
.
dir
(
lambda
x
:
l
.
append
(
x
))
self
.
assertEqual
(
''
.
join
(
l
),
LIST_DATA
.
replace
(
'
\r\n
'
,
''
))
def
test_mlsd
(
self
):
list
(
self
.
client
.
mlsd
())
list
(
self
.
client
.
mlsd
(
path
=
'/'
))
list
(
self
.
client
.
mlsd
(
path
=
'/'
,
facts
=
[
'size'
,
'type'
]))
ls
=
list
(
self
.
client
.
mlsd
())
for
name
,
facts
in
ls
:
self
.
assertTrue
(
name
)
self
.
assertTrue
(
'type'
in
facts
)
self
.
assertTrue
(
'perm'
in
facts
)
self
.
assertTrue
(
'unique'
in
facts
)
def
set_data
(
data
):
self
.
server
.
handler_instance
.
next_data
=
data
def
test_entry
(
line
,
type
=
None
,
perm
=
None
,
unique
=
None
,
name
=
None
):
type
=
'type'
if
type
is
None
else
type
perm
=
'perm'
if
perm
is
None
else
perm
unique
=
'unique'
if
unique
is
None
else
unique
name
=
'name'
if
name
is
None
else
name
set_data
(
line
)
_name
,
facts
=
next
(
self
.
client
.
mlsd
())
self
.
assertEqual
(
_name
,
name
)
self
.
assertEqual
(
facts
[
'type'
],
type
)
self
.
assertEqual
(
facts
[
'perm'
],
perm
)
self
.
assertEqual
(
facts
[
'unique'
],
unique
)
# plain
test_entry
(
'type=type;perm=perm;unique=unique; name
\r\n
'
)
# "=" in fact value
test_entry
(
'type=ty=pe;perm=perm;unique=unique; name
\r\n
'
,
type
=
"ty=pe"
)
test_entry
(
'type==type;perm=perm;unique=unique; name
\r\n
'
,
type
=
"=type"
)
test_entry
(
'type=t=y=pe;perm=perm;unique=unique; name
\r\n
'
,
type
=
"t=y=pe"
)
test_entry
(
'type=====;perm=perm;unique=unique; name
\r\n
'
,
type
=
"===="
)
# spaces in name
test_entry
(
'type=type;perm=perm;unique=unique; na me
\r\n
'
,
name
=
"na me"
)
test_entry
(
'type=type;perm=perm;unique=unique; name
\r\n
'
,
name
=
"name "
)
test_entry
(
'type=type;perm=perm;unique=unique; name
\r\n
'
,
name
=
" name"
)
test_entry
(
'type=type;perm=perm;unique=unique; n am e
\r\n
'
,
name
=
"n am e"
)
# ";" in name
test_entry
(
'type=type;perm=perm;unique=unique; na;me
\r\n
'
,
name
=
"na;me"
)
test_entry
(
'type=type;perm=perm;unique=unique; ;name
\r\n
'
,
name
=
";name"
)
test_entry
(
'type=type;perm=perm;unique=unique; ;name;
\r\n
'
,
name
=
";name;"
)
test_entry
(
'type=type;perm=perm;unique=unique; ;;;;
\r\n
'
,
name
=
";;;;"
)
# case sensitiveness
set_data
(
'Type=type;TyPe=perm;UNIQUE=unique; name
\r\n
'
)
_name
,
facts
=
next
(
self
.
client
.
mlsd
())
[
self
.
assertTrue
(
x
.
islower
())
for
x
in
facts
.
keys
()]
# no data (directory empty)
set_data
(
''
)
self
.
assertRaises
(
StopIteration
,
next
,
self
.
client
.
mlsd
())
set_data
(
''
)
for
x
in
self
.
client
.
mlsd
():
self
.
fail
(
"unexpected data
%
s"
%
data
)
def
test_makeport
(
self
):
with
self
.
client
.
makeport
():
# IPv4 is in use, just make sure send_eprt has not been used
...
...
Misc/NEWS
Dosyayı görüntüle @
d78def94
...
...
@@ -140,6 +140,8 @@ Core and Builtins
Library
-------
- Issue #11072: added MLSD command (RFC-3659) support to ftplib.
- Issue #8808: The IMAP4_SSL constructor now allows passing an SSLContext
parameter to control parameters of the secure channel. Patch by Sijin
Joseph.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment