Skip to content

Commit

Permalink
Add hardcoded paths to macOS frameworks for Big Sur compatibility. (#…
Browse files Browse the repository at this point in the history
…1905)

* Add hardcoded paths to macOS frameworks for Big Sur compatibility.

ctypes.util.find_library is checking for the presence of the framework
files, which will fail due to macOS Big Sur's "dynamic linker cache".
Since these files really can't be anywhere else, we just hardcode the
path and load them.

See: https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11-beta-release-notes
(relevent excerpt provided below)

This update takes the approach of leaving the existing behavior as is
for macOS 10.8 (lowest supported version) through 10.15.

Allegedly Apple is going to number Big Sur as macOS 11, although right
now the beta returns a version of "10.16", so this code handles both as
being greater than or equal to "10.16".

| New in macOS Big Sur 11 beta, the system ships with a built-in dynamic
linker cache of all system-provided libraries. As part of this change,
copies of dynamic libraries are no longer present on the filesystem.
Code that attempts to check for dynamic library presence by looking for
a file at a path or enumerating a directory will fail. Instead, check
for library presence by attempting to dlopen() the path, which will
correctly check for the library in the cache. (62986286)

* Raise an OSError if not on macOS and trying to import securetransport

* Just use hardcoded paths for Security and CoreFoundation libs.

This should never be anything but these paths. Instead of checking for
`os.path.isfile` with `ctypes.util.find_library`, we just try to load
with `ctypes.CDLL` and catch the `OSError` if it fails, add context, and
reraise.

* Updated to preserve pre-10.16 behavior.

* Bail early on non-macOS.

* Restore find_library import, OSError -> ImportError

* ImportError

* OSError

* Delete test_securetransport_big_sur.py

Co-authored-by: Seth Michael Larson <sethmichaellarson@gmail.com>
  • Loading branch information
sheagcraig and sethmlarson committed Jul 19, 2020
1 parent 42ec81d commit 6bd33f6
Showing 1 changed file with 28 additions and 11 deletions.
39 changes: 28 additions & 11 deletions src/urllib3/contrib/_securetransport/bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,11 @@
c_bool,
)
from ctypes import CDLL, POINTER, CFUNCTYPE
from urllib3.packages.six import raise_from


security_path = find_library("Security")
if not security_path:
raise ImportError("The library Security could not be found")


core_foundation_path = find_library("CoreFoundation")
if not core_foundation_path:
raise ImportError("The library CoreFoundation could not be found")

if platform.system() != "Darwin":
raise ImportError("Only macOS is supported")

version = platform.mac_ver()[0]
version_info = tuple(map(int, version.split(".")))
Expand All @@ -65,8 +59,31 @@
% (version_info[0], version_info[1])
)

Security = CDLL(security_path, use_errno=True)
CoreFoundation = CDLL(core_foundation_path, use_errno=True)

def load_cdll(name, macos10_16_path):
"""Loads a CDLL by name, falling back to known path on 10.16+"""
try:
# Big Sur is technically 11 but we use 10.16 due to the Big Sur
# beta being labeled as 10.16.
if version_info >= (10, 16):
path = macos10_16_path
else:
path = find_library(name)
if not path:
raise OSError # Caught and reraised as 'ImportError'
return CDLL(path, use_errno=True)
except OSError:
raise_from(ImportError("The library %s failed to load" % name), None)


Security = load_cdll(
"Security", "/System/Library/Frameworks/Security.framework/Security"
)
CoreFoundation = load_cdll(
"CoreFoundation",
"/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation",
)


Boolean = c_bool
CFIndex = c_long
Expand Down

0 comments on commit 6bd33f6

Please sign in to comment.