Repository: marcelotduarte/cx_Freeze (python)

Issue:
tkinter path error
Hi,
Got a problem with version  mingw-w64-x86_64-python-cx_Freeze-6.0-1
Can't find path to tkinter (error: [Errno 2] No such file or directory: 'C:/msys64/mingw64/tcl/tcl8.6')
I try to add path in setup-freeze.py:
...
include_files = [
    r"C:\msys64\mingw64\bin\tcl86.dll",
    r"C:\msys64\mingw64\bin\tk86.dll",]

os.environ['TCL_LIBRARY'] = r'C:\msys64\mingw64\lib\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\msys64\mingw64\lib\tk8.6'
....
Got this error: error: [Errno 2] No such file or directory: 'C:/msys64/mingw64/Dlls/tcl86t.dll'
tcl86t.dll doesn't exist, my file is tcl86.dll

Thanks for help!


Discussion:
I try the sample:
https://github.com/anthony-tuininga/cx_Freeze/tree/master/cx_Freeze/samples/Tkinter
Got:
...
copying C:/msys64/mingw64/tcl/tcl8.6 -> build/exe.mingw-3.8/tcl
error: [Errno 2] No such file or directory: 'C:/msys64/mingw64/tcl/tcl8.6'

Can bypass error doing this:

- Create С:\msys64\mingw64\tcl directory and copy into it these directories:
    C:\msys64\mingw64\lib\tcl8.6
    C:\msys64\mingw64\lib\tk8.6
- Create С:\msys64\mingw64\Dlls directory and copy into it these files:
    C:\msys64\mingw64\bin\tcl86.dll
    C:\msys64\mingw64\bin\tk86.dll
- Rename these files in С:\msys64\mingw64\Dlls directory:
    tcl86.dll -> tcl86t.dll
    tk86.dll -> tk86t.dll
Same here, any basic MSYS2 installation triggers this bug.
Edit: I can exclude tcl and tk by spelling them correctly (case sensitive under mingw): [xpra changeset 25138](http://xpra.org/trac/changeset/25138/xpra)

Patch:
diff --git a/cx_Freeze/hooks.py b/cx_Freeze/hooks.py
--- a/cx_Freeze/hooks.py
+++ b/cx_Freeze/hooks.py
@@ -5,6 +5,9 @@
 
 from cx_Freeze.common import rebuild_code_object
 
+MINGW = sysconfig.get_platform() == "mingw"
+WIN32 = sys.platform == "win32"
+
 def initialize(finder):
     """upon initialization of the finder, this routine is called to set up some
        automatic exclusions for various platforms."""
@@ -219,9 +222,9 @@ def load_cryptography_hazmat_bindings__padding(finder, module):
 
 
 def load__ctypes(finder, module):
-    """In Windows, the _ctypes module in Python >= 3.8 requires an additional dll
+    """In Windows, the _ctypes module in Python 3.8+ requires an additional dll
        libffi-7.dll to be present in the build directory."""
-    if sys.platform == "win32" and sys.version_info >= (3, 8) and sysconfig.get_platform() != "mingw":
+    if WIN32 and sys.version_info >= (3, 8) and not MINGW:
         dll_name = "libffi-7.dll"
         dll_path = os.path.join(sys.base_prefix, "DLLs", dll_name)
         finder.IncludeFiles(dll_path, os.path.join("lib", dll_name))
@@ -683,7 +686,7 @@ def load_PyQt4_phonon(finder, module):
     """In Windows, phonon4.dll requires an additional dll phonon_ds94.dll to
        be present in the build directory inside a folder phonon_backend."""
     name, QtCore = _qt_implementation(module)
-    if sys.platform == "win32":
+    if WIN32:
         copy_qt_plugins("phonon_backend", finder, QtCore)
 
 load_PySide_phonon = load_PyQt5_phonon = load_PyQt4_phonon
@@ -837,9 +840,9 @@ def load_site(finder, module):
 
 
 def load_ssl(finder, module):
-    """In Windows, the SSL module in Python >= 3.7 requires additional dlls to
+    """In Windows, the SSL module in Python 3.7+ requires additional dlls to
        be present in the build directory."""
-    if sys.platform == "win32" and sys.version_info >= (3, 7):
+    if WIN32 and sys.version_info >= (3, 7) and not MINGW:
         for dll_search in ["libcrypto-*.dll", "libssl-*.dll"]:
             for dll_path in glob.glob(os.path.join(sys.base_prefix, "DLLs", dll_search)):
                 dll_name = os.path.basename(dll_path)
@@ -850,24 +853,28 @@ def load_tkinter(finder, module):
     """the tkinter module has data files that are required to be loaded so
        ensure that they are copied into the directory that is expected at
        runtime."""
-    if sys.platform == "win32":
+    if WIN32:
         import tkinter
         root_names = "tcl", "tk"
         environ_names = "TCL_LIBRARY", "TK_LIBRARY"
         version_vars = tkinter.TclVersion, tkinter.TkVersion
         zipped = zip(environ_names, version_vars, root_names)
         for env_name, ver_var, mod_name in zipped:
+            dir_name = mod_name + str(ver_var)
             try:
                 lib_texts = os.environ[env_name]
             except KeyError:
-                lib_texts = os.path.join(sys.base_prefix, "tcl",
-                        mod_name + str(ver_var))
-            targetPath = os.path.join("lib", "tkinter", mod_name)
+                if MINGW:
+                    lib_texts = os.path.join(sys.base_prefix, "lib", dir_name)
+                else:
+                    lib_texts = os.path.join(sys.base_prefix, "tcl", dir_name)
+            targetPath = os.path.join("lib", "tkinter", dir_name)
             finder.AddConstant(env_name, targetPath)
             finder.IncludeFiles(lib_texts, targetPath)
-            dll_name = mod_name + str(ver_var).replace(".", "") + "t.dll"
-            dll_path = os.path.join(sys.base_prefix, "DLLs", dll_name)
-            finder.IncludeFiles(dll_path, os.path.join("lib", dll_name))
+            if not MINGW:
+                dll_name = dir_name.replace(".", "") + "t.dll"
+                dll_path = os.path.join(sys.base_prefix, "DLLs", dll_name)
+                finder.IncludeFiles(dll_path, os.path.join("lib", dll_name))
 
 
 def load_tempfile(finder, module):
@@ -1006,7 +1013,7 @@ def missing_readline(finder, caller):
     """the readline module is not normally present on Windows but it also may
        be so instead of excluding it completely, ignore it if it can't be
        found"""
-    if sys.platform == "win32":
+    if WIN32:
         caller.IgnoreName("readline")
 
 
@@ -1014,7 +1021,7 @@ def load_zmq(finder, module):
     """the zmq package loads zmq.backend.cython dynamically and links
     dynamically to zmq.libzmq."""
     finder.IncludePackage("zmq.backend.cython")
-    if sys.platform == "win32":
+    if WIN32:
         # Not sure yet if this is cross platform
         # Include the bundled libzmq library, if it exists
         try:
@@ -1038,11 +1045,13 @@ def load_clr(finder, module):
 def load_sqlite3(finder, module):
     """In Windows, the sqlite3 module requires an additional dll sqlite3.dll to
        be present in the build directory."""
-    if sys.platform == "win32":
+    if WIN32 and not MINGW:
         dll_name = "sqlite3.dll"
         dll_path = os.path.join(sys.base_prefix, "DLLs", dll_name)
+        if not os.path.exists(dll_path):
+            dll_path = os.path.join(sys.base_prefix, "Library", "bin", dll_name)
         finder.IncludeFiles(dll_path, os.path.join("lib", dll_name))
-    finder.IncludePackage('sqlite3')
+    finder.IncludePackage("sqlite3")
 
 def load_pytest(finder, module):
     import pytest
diff --git a/cx_Freeze/samples/bcrypt/setup.py b/cx_Freeze/samples/bcrypt/setup.py
--- a/cx_Freeze/samples/bcrypt/setup.py
+++ b/cx_Freeze/samples/bcrypt/setup.py
@@ -1,4 +1,4 @@
-'''A setup script to demonstrate build using bcrypt'''
+"""A setup script to demonstrate build using bcrypt"""
 #
 # Run the build process by running the command 'python setup.py build'
 #
@@ -7,13 +7,10 @@
 
 from cx_Freeze import setup, Executable
 
-setup(name='test_bcrypt',
-      version='0.1',
-      description='cx_Freeze script to test bcrypt',
+setup(name="test_bcrypt",
+      version="0.2",
+      description="cx_Freeze script to test bcrypt",
       executables=[Executable("test_bcrypt.py")],
-      options={
-          'build_exe': {'zip_include_packages': ["*"],
-                        'zip_exclude_packages': [],
-                        #'includes': ['_cffi_backend']
-                        }
-          })
+      options={"build_exe": {"excludes": ["tkinter"],
+                             "zip_include_packages": ["*"],
+                             "zip_exclude_packages": []}})
diff --git a/cx_Freeze/samples/cryptography/setup.py b/cx_Freeze/samples/cryptography/setup.py
--- a/cx_Freeze/samples/cryptography/setup.py
+++ b/cx_Freeze/samples/cryptography/setup.py
@@ -1,4 +1,4 @@
-# A setup script to demonstrate build using cffi (inside a cryptography pkg)
+"""A setup script to demonstrate build using cffi (used by cryptography)"""
 #
 # Run the build process by running the command 'python setup.py build'
 #
@@ -7,11 +7,10 @@
 
 from cx_Freeze import setup, Executable
 
-buildOptions = dict(zip_include_packages=["*"], zip_exclude_packages=[])
-executables = [Executable("test_crypt.py")]
-
-setup(name='test_crypt',
-      version='0.1',
-      description='cx_Freeze script to test cryptography',
-      executables=executables,
-      options=dict(build_exe=buildOptions))
+setup(name="test_crypt",
+      version="0.2",
+      description="cx_Freeze script to test cryptography",
+      executables=[Executable("test_crypt.py")],
+      options={"build_exe": {"excludes": ["tkinter"],
+                             "zip_include_packages": ["*"],
+                             "zip_exclude_packages": []}})
diff --git a/cx_Freeze/samples/sqlite/setup.py b/cx_Freeze/samples/sqlite/setup.py
--- a/cx_Freeze/samples/sqlite/setup.py
+++ b/cx_Freeze/samples/sqlite/setup.py
@@ -1,4 +1,4 @@
-# A setup script to demonstrate the use of sqlite3
+"""A setup script to demonstrate the use of sqlite3"""
 #
 # Run the build process by running the command 'python setup.py build'
 #
@@ -7,11 +7,11 @@
 
 from cx_Freeze import setup, Executable
 
-buildOptions = {"replace_paths": [("*", "")]}
-executables = [Executable("test_sqlite3.py")]
-
-setup(name='test_sqlite3',
-      version='0.2',
-      description='cx_Freeze script to test sqlite3',
-      executables=executables,
-      options=dict(build_exe=buildOptions))
+setup(name="test_sqlite3",
+      version="0.3",
+      description="cx_Freeze script to test sqlite3",
+      executables=[Executable("test_sqlite3.py")],
+      options={"build_exe": {"excludes": ["tkinter"],
+                             "replace_paths": [("*", "")],
+                             "zip_include_packages": ["*"],
+                             "zip_exclude_packages": []}})


Test patch:
diff --git a/cx_Freeze/samples/cryptography/test_crypt.py b/cx_Freeze/samples/cryptography/test_crypt.py
--- a/cx_Freeze/samples/cryptography/test_crypt.py
+++ b/cx_Freeze/samples/cryptography/test_crypt.py
@@ -1,3 +1,3 @@
 from cryptography.fernet import Fernet
 
-print('Hello cryptography', Fernet)
+print("Hello cryptography", Fernet)
diff --git a/cx_Freeze/samples/sqlite/test_sqlite3.py b/cx_Freeze/samples/sqlite/test_sqlite3.py
--- a/cx_Freeze/samples/sqlite/test_sqlite3.py
+++ b/cx_Freeze/samples/sqlite/test_sqlite3.py
@@ -29,4 +29,4 @@
         f.write('%s\n' % line)
 
 print('dump.sql created')
-con.close()
\ No newline at end of file
+con.close()