source: sandbox/session.py @ 1488:6feef85c45b2

Last change on this file since 1488:6feef85c45b2 was 1488:6feef85c45b2, checked in by Stefan Schwarzer <sschwarzer@…>, 7 years ago
Support debug level when creating session factories.
File size: 3.4 KB
Line 
1# Copyright (C) 2014, Stefan Schwarzer
2
3"""
4Session factory factory (the two "factory" are intential :-) )
5for ftputil.
6"""
7
8import ftplib
9
10import ftputil.tool
11
12try:
13    import M2Crypto
14    import M2Crypto.ftpslib
15except ImportError:
16    M2Crypto = None
17
18
19def session_factory(base_class=ftplib.FTP, port=21, use_passive_mode=None,
20                    encrypt_data_channel=None, debug_level=None):
21    """
22    Create and return a session factory according to the keyword
23    arguments.
24
25    base_class: Base class to use for the session class (e. g.
26    `ftplib.FTP_TLS` or `M2Crypto.ftpslib.FTP_TLS`, default is
27    `ftplib.FTP`).
28
29    port: Port number (integer) for the command channel (default 21).
30    If you don't know what "command channel" means, use the default or
31    use what the provider gave you as "the FTP port".
32
33    use_passive_mode: If `True`, explicitly use passive mode. If
34    `False`, explicitly don't use passive mode. If `None` (default),
35    let the `base_class` decide whether it wants to use active or
36    passive mode.
37
38    encrypt_data_channel: If `True`, call the `prot_p` method of the
39    base class. If `False` or `None` (`None` is the default), don't
40    call the method.
41
42    debug_level: Debug level (integer) to be set on a session
43    instance. The default is `None`, meaning no debugging output.
44
45    This function should work the base classes for `ftplib.FTP`,
46    `ftplib.FTP_TLS` and `M2Crypto.ftpslib.FTP_TLS` with TLS security.
47    Other base classes should work if they use the same API as
48    `ftplib.FTP`.
49
50    Usage example:
51
52      my_session_factory = session_factory(
53                             base_class=M2Crypto.ftpslib.FTP_TLS,
54                             use_passive_mode=True,
55                             encrypt_data_channel=True)
56      with ftputil.FTPHost(host, user, password,
57                           session_factory=my_session_factory) as host:
58        ...
59    """
60    class Session(base_class):
61        """Session factory class created by `session_factory`."""
62
63        def __init__(self, host, user, password):
64            base_class.__init__(self)
65            self.connect(host, port)
66            if self._use_m2crypto_ftpslib():
67                self.auth_tls()
68                self._fix_socket()
69            if debug_level is not None:
70                self.set_debuglevel(debug_level)
71            self.login(user, password)
72            if use_passive_mode is not None:
73                self.set_pasv(use_passive_mode)
74            if encrypt_data_channel:
75                self.prot_p()
76
77        def _use_m2crypto_ftpslib(self):
78            """
79            Return `True` if the base class to use is
80            `M2Crypto.ftpslib.FTP_TLS`, else return `False`.
81            """
82            return (M2Crypto is not None and
83                    issubclass(base_class, M2Crypto.ftpslib.FTP_TLS))
84
85        def _fix_socket(self):
86            """
87            Change the socket object so that arguments to `sendall`
88            are converted to byte strings before being used.
89
90            See the ftputil ticket #78 for details:
91            http://ftputil.sschwarzer.net/trac/ticket/78
92            """
93            original_sendall = self.sock.sendall
94            # Bound method, therefore no `self` argument.
95            def sendall(data):
96                data = ftputil.tool.as_bytes(data)
97                return original_sendall(data)
98            self.sock.sendall = sendall
99
100    return Session
Note: See TracBrowser for help on using the repository browser.