Problem with TLS_FTPHandler and py2exe ...

661 views
Skip to first unread message

somm

unread,
Sep 11, 2014, 2:57:50 AM9/11/14
to pyft...@googlegroups.com

Hello, first thing to say -> Great work !

I have tried to setup a demo ftpd server using the library and everything works as I want (I know the sample code here is missing a few things, but I have tried to track it down):

import os
import sys
import time
import threading
import logging.handlers

from pyftpdlib.log import logger, LogFormatter

from pyftpdlib._compat import b, unicode
from pyftpdlib.filesystems import AbstractedFS
from pyftpdlib.servers import ThreadedFTPServer
from pyftpdlib.handlers import FTPHandler, TLS_FTPHandler
from pyftpdlib.authorizers import DummyAuthorizer, AuthenticationFailed

class MyHandler(FTPHandler):
    def on_disconnect(self):
        pass

class MyTLSHandler(TLS_FTPHandler):
    def on_disconnect(self):
        pass

class test_ftpd(threading.Thread):
    handler = None
    server_class = ThreadedFTPServer

    def __init__(self):
        threading.Thread.__init__(self)
        self.__serving = False
        self.__lock = threading.Lock()
        self.__flag = threading.Event()

        channel = logging.handlers.RotatingFileHandler('./test_ftpd.log', maxBytes=1024, backupCount=6)
        channel.setFormatter(LogFormatter())
        logger = logging.getLogger('pyftpdlib')
        logger.addHandler(channel)
        logger.setLevel(logging.INFO)

        ftpd_usetls = 0

        authorizer = DummyAuthorizer()
        if not ftpd_usetls:
            self.handler = MyHandler
        else:
            self.handler = MyTLSHandler
            self.handler.certfile = './test_ftpd.pem'
        self.handler.authorizer = authorizer
        self.handler.abstracted_fs = AbstractedFS

        self.handler.banner = "test ftpd ready."

        self.server = self.server_class(('0.0.0.0', 21), self.handler)

    @property
    def running(self):
        return self.__serving

    def start(self, timeout=0.001):
        if self.__serving:
            logger.info('Server already started')
            raise RuntimeError("Server already started")
        self.__timeout = timeout
        threading.Thread.start(self)
        self.__flag.wait()

    def run(self):
        self.__serving = True
        self.__flag.set()
        self.server._log_start()
        while self.__serving:
            self.__lock.acquire()
            self.server.serve_forever(timeout=self.__timeout, blocking=False)
            self.__lock.release()
        logger.info(">>> shutting down FTP server (%s active fds) <<<", self.server._map_len())
        self.server.close_all()

    def stop(self):
        if not self.__serving:
            logger.info('Server not started yet')
            raise RuntimeError("Server not started yet")
        self.__serving = False
        self.join(timeout=10)
        if threading.activeCount() > 1:
            logger.info('FTP server thread is still running')

def main(argv):
    server = test_ftpd()
    server.start()
    while server.running:
        try:
            time.sleep(1.0)
        except KeyboardInterrupt:
            server.stop()

if __name__ == '__main__':
    main(sys.argv[1:])

Then I tried to compile with py2exe:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

from distutils.core import setup
import py2exe

class Target(object):
    '''Target is the baseclass for all executables that are created.
    It defines properties that are shared by all of them.
    '''
    def __init__(self, **kw):
        self.__dict__.update(kw)

        # the VersionInfo resource, uncomment and fill in those items
        # that make sense:
        
        # The 'version' attribute MUST be defined, otherwise no versioninfo will be built:
        # self.version = "1.0"
        
        self.company_name = "Test"
        self.copyright = "Copyright Test © 2014"
        # self.legal_copyright = "Copyright Company Name © 2013"
        # self.legal_trademark = ""
        # self.product_version = "1.0.0.0"
        self.product_name = "test FTP server"

        # self.private_build = "foo"
        # self.special_build = "bar"

    def copy(self):
        return Target(**self.__dict__)

    def __setitem__(self, name, value):
        self.__dict__[name] = value

test_ftpd = Target(
    # We can extend or override the VersionInfo of the base class:
    version = "1.0",
    # file_description = "File Description",
    # comments = "Some Comments",
    # internal_name = "spam",

    script="test.py", # path of the main script

    # Allows to specify the basename of the executable, if different from 'test'
    # dest_base = "test",

    # Icon resources:[(resource_id, path to .ico file), ...]
    # icon_resources=[(1, r"test.ico")]
    )

py2exe_options = dict(
    packages = [],
##    excludes = "tof_specials Tkinter".split(),
##    ignores = "dotblas gnosis.xml.pickle.parsers._cexpat mx.DateTime".split(),
##    dll_excludes = "MSVCP90.dll mswsock.dll powrprof.dll".split(),
    optimize=2,
    compressed=True, # uncompressed may or may not have a faster startup
    bundle_files=0,
    dist_dir='dist_test',
    )

setup(name="name",
      # console based executables
      console=[test_ftpd],

      # py2exe options
      zipfile=None,
      options={"py2exe": py2exe_options},
      )

The compile is ok and I get the exe, but when I try to start it I get the following error:

Traceback (most recent call last):
  File "test.py", line 13, in <module>
ImportError: cannot import name 'TLS_FTPHandler'

What is going wrong here ?

My System:
Windows 7 64 Bit
Python 3.4.1 64 Bit
py2exe for python 3

somm

unread,
Sep 12, 2014, 5:36:22 AM9/12/14
to pyft...@googlegroups.com

I have done some further tests and found out that the problem also appears when I use the standard demo from the tutorial. Exactly same problem.

Has somebody any ideas ?


Giampaolo Rodola'

unread,
Sep 12, 2014, 6:26:13 AM9/12/14
to pyft...@googlegroups.com

Almost certainly the TLS class cannot be imported because pyopenssl module is missing. You probably need to tell py2exe to include pyopenssl as part of the executable but this is all I know. Hope this helps.

Il 12/set/2014 11:36 "somm" <so...@certec.at> ha scritto:

I have done some further tests and found out that the problem also appears when I use the standard demo from the tutorial. Exactly same problem.

Has somebody any ideas ?


--
You received this message because you are subscribed to the "Python FTP server library" project group:
http://code.google.com/p/pyftpdlib/
To post to this group, send email to pyft...@googlegroups.com
To unsubscribe from this group, send email to pyftpdlib-...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/pyftpdlib
---
You received this message because you are subscribed to the Google Groups "Python FTP server library - Discussion group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyftpdlib+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

somm

unread,
Sep 13, 2014, 10:04:40 AM9/13/14
to pyft...@googlegroups.com
Have tried this - but no chance.

Tracked it down to one line of code:

from OpenSSL import SSL

So this has nothing to do with pyftplib - have posted it to the py2exe mailing list

Reply all
Reply to author
Forward
0 new messages