|
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 |
|
@@ -1714,6 +1714,46 @@ def __repr__(self):
|
1714 | 1714 | return f'FileFinder({self.path!r})'
|
1715 | 1715 |
|
1716 | 1716 |
|
| 1717 | +class AppleFrameworkLoader(ExtensionFileLoader): |
| 1718 | + """A loader for modules that have been packaged as frameworks for |
| 1719 | + compatibility with Apple's iOS App Store policies. |
| 1720 | + """ |
| 1721 | + def create_module(self, spec): |
| 1722 | + # If the ModuleSpec has been created by the FileFinder, it will have |
| 1723 | + # been created with an origin pointing to the .fwork file. We need to |
| 1724 | + # redirect this to the location in the Frameworks folder, using the |
| 1725 | + # content of the .fwork file. |
| 1726 | + if spec.origin.endswith(".fwork"): |
| 1727 | + with _io.FileIO(spec.origin, 'r') as file: |
| 1728 | + framework_binary = file.read().decode().strip() |
| 1729 | + bundle_path = _path_split(sys.executable)[0] |
| 1730 | + spec.origin = _path_join(bundle_path, framework_binary) |
| 1731 | + |
| 1732 | + # If the loader is created based on the spec for a loaded module, the |
| 1733 | + # path will be pointing at the Framework location. If this occurs, |
| 1734 | + # get the original .fwork location to use as the module's __file__. |
| 1735 | + if self.path.endswith(".fwork"): |
| 1736 | + path = self.path |
| 1737 | + else: |
| 1738 | + with _io.FileIO(self.path + ".origin", 'r') as file: |
| 1739 | + origin = file.read().decode().strip() |
| 1740 | + bundle_path = _path_split(sys.executable)[0] |
| 1741 | + path = _path_join(bundle_path, origin) |
| 1742 | + |
| 1743 | + module = _bootstrap._call_with_frames_removed(_imp.create_dynamic, spec) |
| 1744 | + |
| 1745 | + _bootstrap._verbose_message( |
| 1746 | + "Apple framework extension module {!r} loaded from {!r} (path {!r})", |
| 1747 | + spec.name, |
| 1748 | + spec.origin, |
| 1749 | + path, |
| 1750 | + ) |
| 1751 | + |
| 1752 | + # Ensure that the __file__ points at the .fwork location |
| 1753 | + module.__file__ = path |
| 1754 | + |
| 1755 | + return module |
| 1756 | + |
1717 | 1757 | # Import setup ###############################################################
|
1718 | 1758 |
|
1719 | 1759 | def _fix_up_module(ns, name, pathname, cpathname=None):
|
@@ -1746,10 +1786,17 @@ def _get_supported_file_loaders():
|
1746 | 1786 |
|
1747 | 1787 | Each item is a tuple (loader, suffixes).
|
1748 | 1788 | """
|
1749 |
| - extensions = ExtensionFileLoader, _imp.extension_suffixes() |
| 1789 | + if sys.platform in {"ios", "tvos", "watchos"}: |
| 1790 | + extension_loaders = [(AppleFrameworkLoader, [ |
| 1791 | + suffix.replace(".so", ".fwork") |
| 1792 | + for suffix in _imp.extension_suffixes() |
| 1793 | + ])] |
| 1794 | + else: |
| 1795 | + extension_loaders = [] |
| 1796 | + extension_loaders.append((ExtensionFileLoader, _imp.extension_suffixes())) |
1750 | 1797 | source = SourceFileLoader, SOURCE_SUFFIXES
|
1751 | 1798 | bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
|
1752 |
| - return [extensions, source, bytecode] |
| 1799 | + return extension_loaders + [source, bytecode] |
1753 | 1800 |
|
1754 | 1801 |
|
1755 | 1802 | def _set_bootstrap_module(_bootstrap_module):
|
|
0 commit comments