Repository: SCons/scons

Issue:
Remove pywin32 dependency in favour of ctypes
This issue was originally created at: 2009-01-12 14:36:07.
This issue was reported by: `ephelon`.
ephelon said at 2009-01-12 14:36:07
>The builtin file and open methods are augmented by SCons.Platform.win32 to unset 
>the HANDLE_FLAG_INHERIT flag.  Rather than using pywin32 to do this, I've loaded 
>the appropriate methods using ctypes and removed the pywin32 dependency.
> 
>I've not added any unit tests for this, because I'm not sure how to reproduce 
>the problems that unsetting this flag cause.

ephelon said at 2009-01-12 14:37:41
>Created an attachment (id=568)
>Patch removing pywin32 in favour of ctypes

gregnoel said at 2009-01-23 01:48:31
>Bug party triage.  Since ctypes is not available on all the Python versions we
>support, Brandon to research and figure out the fallback strategy.

azverkan said at 2009-03-01 23:43:52
>The patch doesn't actually work for me.  I have a script that can reproduce the
>HANDLE_FLAG_INHERIT problems in under 30 seconds and the ctypes patch below
>doesn't seem to be disabling handle inheritance correctly.
> 
>The problem isn't even completely solvable at the moment as Bug 2124 is still an
>issue.

stevenknight said at 2009-03-03 06:56:40
>Reset target milestone to -unspecified- for Bug Party re-triaging.

gregnoel said at 2009-03-05 14:25:54
>Bug party triage.  Good idea, but the ctypes module isn't standard until Python
>2.5.  The ctypes module isn't a candidate for forward-compatibility support as
>it requires C code in order to function.  Apply a tag so we'll look at it again
>when our floor becomes Python 2.5, but shelve this issue for now.

bdbaddog said at 2016-01-13 15:53:03
>Taking this issue. Related to dropping pywin32


ephelon attached [ctypes_win32.patch](https://github.com/SCons/tigris-issue-attachments/blob/master/2291/568/ctypes_win32.patch) at 2009-01-12 14:37:41.
>Patch removing pywin32 in favour of ctypes

gregnoel said this issue depends on #2124 at 2009-03-05 14:25:54.



Discussion:

Resolving patch:
diff --git a/SCons/Platform/win32.py b/SCons/Platform/win32.py
--- a/SCons/Platform/win32.py
+++ b/SCons/Platform/win32.py
@@ -43,22 +43,6 @@
     r'C:\ProgramData\chocolatey\bin'
 ]
 
-try:
-    import msvcrt
-    import win32api
-    import win32con
-except ImportError:
-    parallel_msg = \
-        "you do not seem to have the pywin32 extensions installed;\n" + \
-        "\tparallel (-j) builds may not work reliably with open Python files."
-except AttributeError:
-    parallel_msg = \
-        "your pywin32 extensions do not support file handle operations;\n" + \
-        "\tparallel (-j) builds may not work reliably with open Python files."
-else:
-    parallel_msg = None
-
-
 if False:
     # Now swap out shutil.filecopy and filecopy2 for win32 api native CopyFile
     try:
diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py
--- a/SCons/Script/Main.py
+++ b/SCons/Script/Main.py
@@ -46,6 +46,7 @@
 import traceback
 import sysconfig
 import platform
+import threading
 
 import SCons.CacheDir
 import SCons.Debug
@@ -80,17 +81,6 @@
 delayed_warnings = []
 
 
-def fetch_win32_parallel_msg():
-    # A subsidiary function that exists solely to isolate this import
-    # so we don't have to pull it in on all platforms, and so that an
-    # in-line "import" statement in the _main() function below doesn't
-    # cause warnings about local names shadowing use of the 'SCons'
-    # global in nest scopes and UnboundLocalErrors and the like in some
-    # versions (2.1) of Python.
-    import SCons.Platform.win32
-    return SCons.Platform.win32.parallel_msg
-
-
 def revert_io():
     # This call is added to revert stderr and stdout to the original
     # ones just in case some build rule or something else in the system
@@ -1281,16 +1271,19 @@ def tmtrace_cleanup(tfile):
     # As of 3.7, python removed support for threadless platforms.
     # See https://www.python.org/dev/peps/pep-0011/
     is_37_or_later = sys.version_info >= (3, 7)
-    python_has_threads = sysconfig.get_config_var('WITH_THREAD') or is_pypy or is_37_or_later
+    # python_has_threads = sysconfig.get_config_var('WITH_THREAD') or is_pypy or is_37_or_later
+
+    # As of python 3.4 threading has a dummy_threading module for use when there is no threading
+    # it's get_ident() will allways return -1, while real threading modules get_ident() will
+    # always return a positive integer
+    python_has_threads = threading.get_ident() != -1
     # to check if python configured with threads.
     global num_jobs
     num_jobs = options.num_jobs
     jobs = SCons.Job.Jobs(num_jobs, taskmaster)
     if num_jobs > 1:
         msg = None
-        if sys.platform == 'win32':
-            msg = fetch_win32_parallel_msg()
-        elif jobs.num_jobs == 1 or not python_has_threads:
+        if jobs.num_jobs == 1 or not python_has_threads:
             msg = "parallel builds are unsupported by this version of Python;\n" + \
                   "\tignoring -j or num_jobs option.\n"
         if msg:


Test patch:
diff --git a/test/option/debug-memory.py b/test/option/debug-memory.py
--- a/test/option/debug-memory.py
+++ b/test/option/debug-memory.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
+# MIT License
 #
-# __COPYRIGHT__
+# Copyright The SCons Foundation
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
@@ -22,8 +23,6 @@
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #
 
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
 """
 Test that the --debug=memory option works.
 """
@@ -31,21 +30,18 @@
 import re
 
 import TestSCons
+from TestCmd import IS_WINDOWS
 
 test = TestSCons.TestSCons()
 
-try:
-    import resource
-except ImportError:
+if not IS_WINDOWS:
     try:
-        import win32process
-        import win32api
+        import resource  # noqa: F401
     except ImportError:
-        x = "Python version has no 'resource' or 'win32api/win32process' module; skipping tests.\n"
+        x = "Python version has no 'resource' skipping tests.\n"
         test.skip_test(x)
 
 
-
 test.write('SConstruct', """
 DefaultEnvironment(tools=[])
 def cat(target, source, env):