source: ftputil/session_adapter.py @ 1713:f146a1ea66aa

Last change on this file since 1713:f146a1ea66aa was 1713:f146a1ea66aa, checked in by Stefan Schwarzer <sschwarzer@…>, 8 months ago
Remove `__future__` imports With the switch to Python 3.x-only, the `__future__` imports are no longer needed. Update copyright years along with the `__future__` import removal.
File size: 3.5 KB
Line 
1# Copyright (C) 2015-2018, Stefan Schwarzer <sschwarzer@sschwarzer.net>
2# and ftputil contributors (see `doc/contributors.txt`)
3# See the file LICENSE for licensing terms.
4
5"""
6Session adapter for `ftplib.FTP`-compatible session factories
7to make them usable with ftputil under Python 2.
8
9`ftplib.FTP` under Python 2 doesn't work with unicode strings
10that contain non-ASCII characters (see ticket #100). Since ftputil
11converts string arguments to unicode strings as soon as possible,
12this even affects calls to `ftputil.FTPHost` methods when the string
13arguments are byte strings.
14
15ftputil client code
16          V
17          V
18`ftputil.FTPHost` methods
19          V
20          V
21convert byte strings to unicode (inside `FTPHost` methods)
22          V
23          V
24session adapter converts from unicode to byte strings
25          V
26          V
27`ftplib.FTP` (or other session) methods
28
29You may wonder why we convert byte strings to unicode strings in
30`ftputil.FTPHost` and unicode strings back to byte strings in the
31adapter. To make the string handling in ftputil consistent for Python
322 and 3, ftputil tries to work everywhere with the same string type.
33Because the focus of ftputil is on modern Python (i. e. Python 3),
34this universal string type is unicode. Indeed the string arguments
35for `ftplib.FTP` under Python 3 are all unicode strings.
36
37Having different code for Python 2 and Python 3 all over in ftputil
38would be bad for maintainability. (ftputil is complicated enough as it
39is.) Therefore, this adapter is the only place to deal with the
40preferred string type of `ftplib` under Python 2 vs. Python 3.
41"""
42
43import ftputil.compat
44import ftputil.tool
45
46
47# Shouldn't be used by ftputil client code
48__all__ = []
49
50
51# Shortcut
52as_bytes = ftputil.tool.as_bytes
53
54
55# We only have to adapt the methods that are directly called by
56# ftputil and only those that take string arguments.
57#
58# Keep the call signature of each adaptor method the same as the
59# signature of the adapted method so that code that introspects
60# the signature of the method still works.
61
62class SessionAdapter(object):
63
64    def __init__(self, session):
65        self._session = session
66
67    def voidcmd(self, cmd):
68        cmd = as_bytes(cmd)
69        return self._session.voidcmd(cmd)
70
71    def transfercmd(self, cmd, rest=None):
72        cmd = as_bytes(cmd)
73        return self._session.transfercmd(cmd, rest)
74
75    def dir(self, *args):
76        # This is somewhat tricky, since some of the args may not
77        # be strings. The last argument may be a callback.
78        args = list(args)
79        for index, arg in enumerate(args):
80            # Replace only unicode strings with a corresponding
81            # byte string.
82            if isinstance(arg, ftputil.compat.unicode_type):
83                args[index] = as_bytes(arg)
84        return self._session.dir(*args)
85
86    def rename(self, fromname, toname):
87        fromname = as_bytes(fromname)
88        toname = as_bytes(toname)
89        return self._session.rename(fromname, toname)
90
91    def delete(self, filename):
92        filename = as_bytes(filename)
93        return self._session.delete(filename)
94
95    def cwd(self, dirname):
96        dirname = as_bytes(dirname)
97        return self._session.cwd(dirname)
98
99    def mkd(self, dirname):
100        dirname = as_bytes(dirname)
101        return self._session.mkd(dirname)
102
103    def rmd(self, dirname):
104        dirname = as_bytes(dirname)
105        return self._session.rmd(dirname)
106
107    # Dispatch to session itself for methods that don't need string
108    # conversions.
109    def __getattr__(self, name):
110        return getattr(self._session, name)
Note: See TracBrowser for help on using the repository browser.