A while back we added tests to make sure we weren't leaking hiwire keys. As a special case of this, we also were testing that we weren't leaking JsProxies. In the future, I would like to add tests to show that we aren't leaking PyProxies either. Currently we leak quite a lot of them.

Before we actually add any tests to show that we aren't leaking proxies, I'd like to rework the model of the PyProxy lifetime. The planned changes should make it far easier to actually avoid these leaks while still using a reasonably natural coding style.

This change has no user-facing effect: the tracing is disabled by default and the API to enable it is private and always will be.
Add support for pyproxy allocation tracing. A while back we added tests to make sure we weren't leaking hiwire keys. As a special case of this, we also were testing that we weren't leaking JsProxies. In the future, I would like to add tests to show that we aren't leaking PyProxies either. Currently we leak quite a lot of them.

Before we actually add any tests to show that we aren't leaking proxies, I'd like to rework the model of the PyProxy lifetime. The planned changes should make it far easier to actually avoid these leaks while still using a reasonably natural coding style.

This change has no user-facing effect: the tracing is disabled by default and the API to enable it is private and always will be.
diff --git a/setuptools/glibc.py b/setuptools/glibc.py
index a134591c..c31fc78a 100644
--- a/setuptools/glibc.py
+++ b/setuptools/glibc.py
@@ -2,13 +2,13 @@
 # https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/utils/glibc.py
 from __future__ import absolute_import
 
-import ctypes
 import re
 import warnings
 
 
 def glibc_version_string():
     "Returns glibc version string, or None if not using glibc."
+    import ctypes
 
     # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
     # manpage says, "If filename is NULL, then the returned handle is for the
diff --git a/setuptools/windows_support.py b/setuptools/windows_support.py
index cb977cff..1ca64fbb 100644
--- a/setuptools/windows_support.py
+++ b/setuptools/windows_support.py
@@ -1,5 +1,4 @@
 import platform
-import ctypes
 
 
 def windows_only(func):
@@ -17,6 +16,7 @@ def hide_file(path):
 
     `path` must be text.
     """
+    import ctypes
     __import__('ctypes.wintypes')
     SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW
     SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD

diff --git a/setuptools/glibc.py b/setuptools/glibc.py
index a134591c..c31fc78a 100644
--- a/setuptools/glibc.py
+++ b/setuptools/glibc.py
@@ -2,13 +2,13 @@
 # https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/utils/glibc.py
 from __future__ import absolute_import
 
-import ctypes
 import re
 import warnings
 
 
 def glibc_version_string():
     "Returns glibc version string, or None if not using glibc."
+    import ctypes
 
     # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
     # manpage says, "If filename is NULL, then the returned handle is for the
diff --git a/setuptools/windows_support.py b/setuptools/windows_support.py
index cb977cff..1ca64fbb 100644
--- a/setuptools/windows_support.py
+++ b/setuptools/windows_support.py
@@ -1,5 +1,4 @@
 import platform
-import ctypes
 
 
 def windows_only(func):
@@ -17,6 +16,7 @@ def hide_file(path):
 
     `path` must be text.
     """
+    import ctypes
     __import__('ctypes.wintypes')
     SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW
     SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD
