|
52 | 52 |
|
53 | 53 | # Bootstrap-related code ######################################################
|
54 | 54 | _CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win',
|
55 |
| -_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin' |
| 55 | +_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin', 'ios', 'tvos', 'watchos' |
56 | 56 | _CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY
|
57 | 57 | + _CASE_INSENSITIVE_PLATFORMS_STR_KEY)
|
58 | 58 |
|
@@ -1694,6 +1694,46 @@ def __repr__(self):
|
1694 | 1694 | return f'FileFinder({self.path!r})'
|
1695 | 1695 |
|
1696 | 1696 |
|
| 1697 | +class AppleFrameworkLoader(ExtensionFileLoader): |
| 1698 | + """A loader for modules that have been packaged as frameworks for |
| 1699 | + compatibility with Apple's iOS App Store policies. |
| 1700 | + """ |
| 1701 | + def create_module(self, spec): |
| 1702 | + # If the ModuleSpec has been created by the FileFinder, it will have |
| 1703 | + # been created with an origin pointing to the .fwork file. We need to |
| 1704 | + # redirect this to the location in the Frameworks folder, using the |
| 1705 | + # content of the .fwork file. |
| 1706 | + if spec.origin.endswith(".fwork"): |
| 1707 | + with _io.FileIO(spec.origin, 'r') as file: |
| 1708 | + framework_binary = file.read().decode().strip() |
| 1709 | + bundle_path = _path_split(sys.executable)[0] |
| 1710 | + spec.origin = _path_join(bundle_path, framework_binary) |
| 1711 | + |
| 1712 | + # If the loader is created based on the spec for a loaded module, the |
| 1713 | + # path will be pointing at the Framework location. If this occurs, |
| 1714 | + # get the original .fwork location to use as the module's __file__. |
| 1715 | + if self.path.endswith(".fwork"): |
| 1716 | + path = self.path |
| 1717 | + else: |
| 1718 | + with _io.FileIO(self.path + ".origin", 'r') as file: |
| 1719 | + origin = file.read().decode().strip() |
| 1720 | + bundle_path = _path_split(sys.executable)[0] |
| 1721 | + path = _path_join(bundle_path, origin) |
| 1722 | + |
| 1723 | + module = _bootstrap._call_with_frames_removed(_imp.create_dynamic, spec) |
| 1724 | + |
| 1725 | + _bootstrap._verbose_message( |
| 1726 | + "Apple framework extension module {!r} loaded from {!r} (path {!r})", |
| 1727 | + spec.name, |
| 1728 | + spec.origin, |
| 1729 | + path, |
| 1730 | + ) |
| 1731 | + |
| 1732 | + # Ensure that the __file__ points at the .fwork location |
| 1733 | + module.__file__ = path |
| 1734 | + |
| 1735 | + return module |
| 1736 | + |
1697 | 1737 | # Import setup ###############################################################
|
1698 | 1738 |
|
1699 | 1739 | def _fix_up_module(ns, name, pathname, cpathname=None):
|
@@ -1726,10 +1766,17 @@ def _get_supported_file_loaders():
|
1726 | 1766 |
|
1727 | 1767 | Each item is a tuple (loader, suffixes).
|
1728 | 1768 | """
|
1729 |
| - extensions = ExtensionFileLoader, _imp.extension_suffixes() |
| 1769 | + if sys.platform in {"ios", "tvos", "watchos"}: |
| 1770 | + extension_loaders = [(AppleFrameworkLoader, [ |
| 1771 | + suffix.replace(".so", ".fwork") |
| 1772 | + for suffix in _imp.extension_suffixes() |
| 1773 | + ])] |
| 1774 | + else: |
| 1775 | + extension_loaders = [] |
| 1776 | + extension_loaders.append((ExtensionFileLoader, _imp.extension_suffixes())) |
1730 | 1777 | source = SourceFileLoader, SOURCE_SUFFIXES
|
1731 | 1778 | bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
|
1732 |
| - return [extensions, source, bytecode] |
| 1779 | + return extension_loaders + [source, bytecode] |
1733 | 1780 |
|
1734 | 1781 |
|
1735 | 1782 | def _set_bootstrap_module(_bootstrap_module):
|
|
0 commit comments