prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  pkgutil.iter_modules is broken on MacOS
  ## Description of the issue
  
  I am trying to build an application on MacOS that uses pkguilt.iter_modules to dynamically find and load modules however it is not finding any modules.
  The modules are there and can be imported with importlib.import_module.
  Note that I am using PyInstaller with FBS but I don't believe the latter changes anything that would effect this.
  
  The following is an example project structure
  ```
  my_package
      my_module_1
      my_module_2
      my_module_3
  ```
  
  Here is the code that does not work
  ```py
  import importlib
  import pkgutil
  m = importlib.import_module("my_package")
  print("Found nested modules", list(pkgutil.iter_modules(m.__path__, m.__name__ + ".")))
  ```
  
  The last line prints an empty list when built with PyInstaller.
  
  I have done a bit of a dive into the code and I believe this is a rather complex mixup with paths and symbolic links.
  https://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py
  
  It looks like #6539 had a go at supporting symbolic links but it only resolves symbolic links up to the `_MEIPASS` directory.
  
  On MacOS `_MEIPASS` is equal to `"/path/to/my_package.app/Contents/MacOS/"`
  
  `my_package.__path__` is equal to `["/path/to/my_package.app/Contents/MacOS/my_package"]`
  
  `/path/to/my_package.app/Contents/MacOS/my_package` is a symbolic link to `/path/to/my_package.app/Contents/Resources/my_package` when there are data files present in that package.
  
  The `iter_modules` hook expands symbolic links in the `path` variable which converts `"/path/to/my_package.app/Contents/MacOS/my_package"` to `"/path/to/my_package.app/Contents/Resources/my_package"`
  
  The following code then skips over the directory because it does not start with `SYS_PREFIX`
  
  ```py
                  if not pkg_path.startswith(SYS_PREFIX):
                      # If the path does not start with sys._MEIPASS, it cannot be a bundled package.
                      continue
  ```
  
  I don't know how this should be implemented but we need to resolve the expected path relative to the `_MEIPASS` directory and then expand symbolic links and only then skip if the package path does not start with the directory.
  
  
  ### Context information (for bug reports)
  
  * Output of `pyinstaller --version`: ```5.13.0```
  * Version of Python: Python 3.11.4 (main, Aug 22 2023, 11:47:24) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
  * Platform: OS X
  * How you installed Python: pyenv
  * Did you also try this on another platform? Does it work there? This only effects MacOS as far as I am aware
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py`
  Content:
  ```
  1 #-----------------------------------------------------------------------------
  2 # Copyright (c) 2021-2023, PyInstaller Development Team.
  3 #
  4 # Licensed under the Apache License, Version 2.0 (the "License");
  5 # you may not use this file except in compliance with the License.
  6 #
  7 # The full license is in the file COPYING.txt, distributed with this software.
  8 #
  9 # SPDX-License-Identifier: Apache-2.0
  10 #-----------------------------------------------------------------------------
  11 #
  12 # This rthook overrides pkgutil.iter_modules with custom implementation that uses PyInstaller's PyiFrozenImporter to
  13 # list sub-modules embedded in the PYZ archive. The non-embedded modules (binary extensions, or .pyc modules in
  14 # noarchive build) are handled by original pkgutil iter_modules implementation (and consequently, python's FileFinder).
  15 #
  16 # The preferred way of adding support for iter_modules would be adding non-standard iter_modules() method to
  17 # PyiFrozenImporter itself. However, that seems to work only for path entry finders (for use with sys.path_hooks), while
  18 # PyInstaller's PyiFrozenImporter is registered as meta path finders (for use with sys.meta_path). Turning
  19 # PyiFrozenImporter into path entry finder, would seemingly require the latter to support on-filesystem resources
  20 # (e.g., extension modules) in addition to PYZ-embedded ones.
  21 #
  22 # Therefore, we instead opt for overriding pkgutil.iter_modules with custom implementation that augments the output of
  23 # original implementation with contents of PYZ archive from PyiFrozenImporter's TOC.
  24 
  25 
  26 def _pyi_rthook():
  27     import os
  28     import pkgutil
  29     import sys
  30 
  31     from pyimod02_importers import PyiFrozenImporter
  32 
  33     _orig_pkgutil_iter_modules = pkgutil.iter_modules
  34 
  35     def _pyi_pkgutil_iter_modules(path=None, prefix=''):
  36         # Use original implementation to discover on-filesystem modules (binary extensions in regular builds, or both
  37         # binary extensions and compiled pyc modules in noarchive debug builds).
  38         yield from _orig_pkgutil_iter_modules(path, prefix)
  39 
  40         # Find the instance of PyInstaller's PyiFrozenImporter.
  41         for importer in pkgutil.iter_importers():
  42             if isinstance(importer, PyiFrozenImporter):
  43                 break
  44         else:
  45             return
  46 
  47         if path is None:
  48             # Search for all top-level packages/modules. These will have no dots in their entry names.
  49             for entry in importer.toc:
  50                 if entry.count('.') != 0:
  51                     continue
  52                 is_pkg = importer.is_package(entry)
  53                 yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)
  54         else:
  55             # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.
  56             #
  57             # Use os.path.realpath() to fully resolve any symbolic links in sys._MEIPASS, in order to avoid path
  58             # mis-matches when the given search paths also contain symbolic links and are already fully resolved.
  59             # See #6537 for an example of such a problem with onefile build on macOS, where the temporary directory
  60             # is placed under /var, which is actually a symbolic link to /private/var.
  61             SYS_PREFIX = os.path.realpath(sys._MEIPASS) + os.path.sep
  62             SYS_PREFIXLEN = len(SYS_PREFIX)
  63 
  64             for pkg_path in path:
  65                 # Fully resolve the given path, in case it contains symbolic links.
  66                 pkg_path = os.path.realpath(pkg_path)
  67                 if not pkg_path.startswith(SYS_PREFIX):
  68                     # If the path does not start with sys._MEIPASS, it cannot be a bundled package.
  69                     continue
  70                 # Construct package prefix from path...
  71                 pkg_prefix = pkg_path[SYS_PREFIXLEN:]
  72                 pkg_prefix = pkg_prefix.replace(os.path.sep, '.')
  73                 # ... and ensure it ends with a dot (so we can directly filter out the package itself).
  74                 if not pkg_prefix.endswith('.'):
  75                     pkg_prefix += '.'
  76                 pkg_prefix_len = len(pkg_prefix)
  77 
  78                 for entry in importer.toc:
  79                     if not entry.startswith(pkg_prefix):
  80                         continue
  81                     name = entry[pkg_prefix_len:]
  82                     if name.count('.') != 0:
  83                         continue
  84                     is_pkg = importer.is_package(entry)
  85                     yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)
  86 
  87     pkgutil.iter_modules = _pyi_pkgutil_iter_modules
  88 
  89 
  90 _pyi_rthook()
  91 del _pyi_rthook
  92
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py b/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py
  --- a/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py
  +++ b/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py
  @@ -47,39 +47,39 @@
           if path is None:
               # Search for all top-level packages/modules. These will have no dots in their entry names.
               for entry in importer.toc:
  -                if entry.count('.') != 0:
  +                if "." in entry:
                       continue
                   is_pkg = importer.is_package(entry)
                   yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)
           else:
  -            # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.
  -            #
               # Use os.path.realpath() to fully resolve any symbolic links in sys._MEIPASS, in order to avoid path
               # mis-matches when the given search paths also contain symbolic links and are already fully resolved.
               # See #6537 for an example of such a problem with onefile build on macOS, where the temporary directory
               # is placed under /var, which is actually a symbolic link to /private/var.
  -            SYS_PREFIX = os.path.realpath(sys._MEIPASS) + os.path.sep
  -            SYS_PREFIXLEN = len(SYS_PREFIX)
  +            MEIPASS = os.path.realpath(sys._MEIPASS)
   
               for pkg_path in path:
                   # Fully resolve the given path, in case it contains symbolic links.
                   pkg_path = os.path.realpath(pkg_path)
  -                if not pkg_path.startswith(SYS_PREFIX):
  -                    # If the path does not start with sys._MEIPASS, it cannot be a bundled package.
  -                    continue
  -                # Construct package prefix from path...
  -                pkg_prefix = pkg_path[SYS_PREFIXLEN:]
  -                pkg_prefix = pkg_prefix.replace(os.path.sep, '.')
  -                # ... and ensure it ends with a dot (so we can directly filter out the package itself).
  -                if not pkg_prefix.endswith('.'):
  -                    pkg_prefix += '.'
  -                pkg_prefix_len = len(pkg_prefix)
  +                # Ensure it ends with os.path.sep (so we can directly filter out the package itself).
  +                if not pkg_path.endswith(os.path.sep):
  +                    pkg_path += os.path.sep
   
                   for entry in importer.toc:
  -                    if not entry.startswith(pkg_prefix):
  +                    # Get the path to the module, and resolve symbolic links. This implicitly solves the problem with
  +                    # macOS .app bundles and packages that contain data files, where package directory is fully
  +                    # collected into Contents/Resources, and symbolic link to directory is created in sys._MEIPASS
  +                    # (Contents/Frameworks). See #7884.
  +                    module_path = os.path.realpath(os.path.join(MEIPASS, entry.replace(".", os.path.sep)))
  +
  +                    # If the module is not in the requested path, skip it.
  +                    if not module_path.startswith(pkg_path):
                           continue
  -                    name = entry[pkg_prefix_len:]
  -                    if name.count('.') != 0:
  +
  +                    name = module_path[len(pkg_path):]
  +
  +                    if os.path.sep in name:
  +                        # Not a direct child
                           continue
                       is_pkg = importer.is_package(entry)
                       yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)
  
verification_info: {"golden_diff": "diff --git a/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py b/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py\n--- a/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py\n+++ b/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py\n@@ -47,39 +47,39 @@\n         if path is None:\n             # Search for all top-level packages/modules. These will have no dots in their entry names.\n             for entry in importer.toc:\n-                if entry.count('.') != 0:\n+                if \".\" in entry:\n                     continue\n                 is_pkg = importer.is_package(entry)\n                 yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)\n         else:\n-            # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.\n-            #\n             # Use os.path.realpath() to fully resolve any symbolic links in sys._MEIPASS, in order to avoid path\n             # mis-matches when the given search paths also contain symbolic links and are already fully resolved.\n             # See #6537 for an example of such a problem with onefile build on macOS, where the temporary directory\n             # is placed under /var, which is actually a symbolic link to /private/var.\n-            SYS_PREFIX = os.path.realpath(sys._MEIPASS) + os.path.sep\n-            SYS_PREFIXLEN = len(SYS_PREFIX)\n+            MEIPASS = os.path.realpath(sys._MEIPASS)\n \n             for pkg_path in path:\n                 # Fully resolve the given path, in case it contains symbolic links.\n                 pkg_path = os.path.realpath(pkg_path)\n-                if not pkg_path.startswith(SYS_PREFIX):\n-                    # If the path does not start with sys._MEIPASS, it cannot be a bundled package.\n-                    continue\n-                # Construct package prefix from path...\n-                pkg_prefix = pkg_path[SYS_PREFIXLEN:]\n-                pkg_prefix = pkg_prefix.replace(os.path.sep, '.')\n-                # ... and ensure it ends with a dot (so we can directly filter out the package itself).\n-                if not pkg_prefix.endswith('.'):\n-                    pkg_prefix += '.'\n-                pkg_prefix_len = len(pkg_prefix)\n+                # Ensure it ends with os.path.sep (so we can directly filter out the package itself).\n+                if not pkg_path.endswith(os.path.sep):\n+                    pkg_path += os.path.sep\n \n                 for entry in importer.toc:\n-                    if not entry.startswith(pkg_prefix):\n+                    # Get the path to the module, and resolve symbolic links. This implicitly solves the problem with\n+                    # macOS .app bundles and packages that contain data files, where package directory is fully\n+                    # collected into Contents/Resources, and symbolic link to directory is created in sys._MEIPASS\n+                    # (Contents/Frameworks). See #7884.\n+                    module_path = os.path.realpath(os.path.join(MEIPASS, entry.replace(\".\", os.path.sep)))\n+\n+                    # If the module is not in the requested path, skip it.\n+                    if not module_path.startswith(pkg_path):\n                         continue\n-                    name = entry[pkg_prefix_len:]\n-                    if name.count('.') != 0:\n+\n+                    name = module_path[len(pkg_path):]\n+\n+                    if os.path.sep in name:\n+                        # Not a direct child\n                         continue\n                     is_pkg = importer.is_package(entry)\n                     yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)\n", "issue": "pkgutil.iter_modules is broken on MacOS\n## Description of the issue\r\n\r\nI am trying to build an application on MacOS that uses pkguilt.iter_modules to dynamically find and load modules however it is not finding any modules.\r\nThe modules are there and can be imported with importlib.import_module.\r\nNote that I am using PyInstaller with FBS but I don't believe the latter changes anything that would effect this.\r\n\r\nThe following is an example project structure\r\n```\r\nmy_package\r\n    my_module_1\r\n    my_module_2\r\n    my_module_3\r\n```\r\n\r\nHere is the code that does not work\r\n```py\r\nimport importlib\r\nimport pkgutil\r\nm = importlib.import_module(\"my_package\")\r\nprint(\"Found nested modules\", list(pkgutil.iter_modules(m.__path__, m.__name__ + \".\")))\r\n```\r\n\r\nThe last line prints an empty list when built with PyInstaller.\r\n\r\nI have done a bit of a dive into the code and I believe this is a rather complex mixup with paths and symbolic links.\r\nhttps://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py\r\n\r\nIt looks like #6539 had a go at supporting symbolic links but it only resolves symbolic links up to the `_MEIPASS` directory.\r\n\r\nOn MacOS `_MEIPASS` is equal to `\"/path/to/my_package.app/Contents/MacOS/\"`\r\n\r\n`my_package.__path__` is equal to `[\"/path/to/my_package.app/Contents/MacOS/my_package\"]`\r\n\r\n`/path/to/my_package.app/Contents/MacOS/my_package` is a symbolic link to `/path/to/my_package.app/Contents/Resources/my_package` when there are data files present in that package.\r\n\r\nThe `iter_modules` hook expands symbolic links in the `path` variable which converts `\"/path/to/my_package.app/Contents/MacOS/my_package\"` to `\"/path/to/my_package.app/Contents/Resources/my_package\"`\r\n\r\nThe following code then skips over the directory because it does not start with `SYS_PREFIX`\r\n\r\n```py\r\n                if not pkg_path.startswith(SYS_PREFIX):\r\n                    # If the path does not start with sys._MEIPASS, it cannot be a bundled package.\r\n                    continue\r\n```\r\n\r\nI don't know how this should be implemented but we need to resolve the expected path relative to the `_MEIPASS` directory and then expand symbolic links and only then skip if the package path does not start with the directory.\r\n\r\n\r\n### Context information (for bug reports)\r\n\r\n* Output of `pyinstaller --version`: ```5.13.0```\r\n* Version of Python: Python 3.11.4 (main, Aug 22 2023, 11:47:24) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin\r\n* Platform: OS X\r\n* How you installed Python: pyenv\r\n* Did you also try this on another platform? Does it work there? This only effects MacOS as far as I am aware\r\n\n", "before_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2021-2023, PyInstaller Development Team.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n#\n# The full license is in the file COPYING.txt, distributed with this software.\n#\n# SPDX-License-Identifier: Apache-2.0\n#-----------------------------------------------------------------------------\n#\n# This rthook overrides pkgutil.iter_modules with custom implementation that uses PyInstaller's PyiFrozenImporter to\n# list sub-modules embedded in the PYZ archive. The non-embedded modules (binary extensions, or .pyc modules in\n# noarchive build) are handled by original pkgutil iter_modules implementation (and consequently, python's FileFinder).\n#\n# The preferred way of adding support for iter_modules would be adding non-standard iter_modules() method to\n# PyiFrozenImporter itself. However, that seems to work only for path entry finders (for use with sys.path_hooks), while\n# PyInstaller's PyiFrozenImporter is registered as meta path finders (for use with sys.meta_path). Turning\n# PyiFrozenImporter into path entry finder, would seemingly require the latter to support on-filesystem resources\n# (e.g., extension modules) in addition to PYZ-embedded ones.\n#\n# Therefore, we instead opt for overriding pkgutil.iter_modules with custom implementation that augments the output of\n# original implementation with contents of PYZ archive from PyiFrozenImporter's TOC.\n\n\ndef _pyi_rthook():\n    import os\n    import pkgutil\n    import sys\n\n    from pyimod02_importers import PyiFrozenImporter\n\n    _orig_pkgutil_iter_modules = pkgutil.iter_modules\n\n    def _pyi_pkgutil_iter_modules(path=None, prefix=''):\n        # Use original implementation to discover on-filesystem modules (binary extensions in regular builds, or both\n        # binary extensions and compiled pyc modules in noarchive debug builds).\n        yield from _orig_pkgutil_iter_modules(path, prefix)\n\n        # Find the instance of PyInstaller's PyiFrozenImporter.\n        for importer in pkgutil.iter_importers():\n            if isinstance(importer, PyiFrozenImporter):\n                break\n        else:\n            return\n\n        if path is None:\n            # Search for all top-level packages/modules. These will have no dots in their entry names.\n            for entry in importer.toc:\n                if entry.count('.') != 0:\n                    continue\n                is_pkg = importer.is_package(entry)\n                yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)\n        else:\n            # Declare SYS_PREFIX locally, to avoid clash with eponymous global symbol from pyi_rth_pkgutil hook.\n            #\n            # Use os.path.realpath() to fully resolve any symbolic links in sys._MEIPASS, in order to avoid path\n            # mis-matches when the given search paths also contain symbolic links and are already fully resolved.\n            # See #6537 for an example of such a problem with onefile build on macOS, where the temporary directory\n            # is placed under /var, which is actually a symbolic link to /private/var.\n            SYS_PREFIX = os.path.realpath(sys._MEIPASS) + os.path.sep\n            SYS_PREFIXLEN = len(SYS_PREFIX)\n\n            for pkg_path in path:\n                # Fully resolve the given path, in case it contains symbolic links.\n                pkg_path = os.path.realpath(pkg_path)\n                if not pkg_path.startswith(SYS_PREFIX):\n                    # If the path does not start with sys._MEIPASS, it cannot be a bundled package.\n                    continue\n                # Construct package prefix from path...\n                pkg_prefix = pkg_path[SYS_PREFIXLEN:]\n                pkg_prefix = pkg_prefix.replace(os.path.sep, '.')\n                # ... and ensure it ends with a dot (so we can directly filter out the package itself).\n                if not pkg_prefix.endswith('.'):\n                    pkg_prefix += '.'\n                pkg_prefix_len = len(pkg_prefix)\n\n                for entry in importer.toc:\n                    if not entry.startswith(pkg_prefix):\n                        continue\n                    name = entry[pkg_prefix_len:]\n                    if name.count('.') != 0:\n                        continue\n                    is_pkg = importer.is_package(entry)\n                    yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)\n\n    pkgutil.iter_modules = _pyi_pkgutil_iter_modules\n\n\n_pyi_rthook()\ndel _pyi_rthook\n", "path": "PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py"}], "after_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2021-2023, PyInstaller Development Team.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n#\n# The full license is in the file COPYING.txt, distributed with this software.\n#\n# SPDX-License-Identifier: Apache-2.0\n#-----------------------------------------------------------------------------\n#\n# This rthook overrides pkgutil.iter_modules with custom implementation that uses PyInstaller's PyiFrozenImporter to\n# list sub-modules embedded in the PYZ archive. The non-embedded modules (binary extensions, or .pyc modules in\n# noarchive build) are handled by original pkgutil iter_modules implementation (and consequently, python's FileFinder).\n#\n# The preferred way of adding support for iter_modules would be adding non-standard iter_modules() method to\n# PyiFrozenImporter itself. However, that seems to work only for path entry finders (for use with sys.path_hooks), while\n# PyInstaller's PyiFrozenImporter is registered as meta path finders (for use with sys.meta_path). Turning\n# PyiFrozenImporter into path entry finder, would seemingly require the latter to support on-filesystem resources\n# (e.g., extension modules) in addition to PYZ-embedded ones.\n#\n# Therefore, we instead opt for overriding pkgutil.iter_modules with custom implementation that augments the output of\n# original implementation with contents of PYZ archive from PyiFrozenImporter's TOC.\n\n\ndef _pyi_rthook():\n    import os\n    import pkgutil\n    import sys\n\n    from pyimod02_importers import PyiFrozenImporter\n\n    _orig_pkgutil_iter_modules = pkgutil.iter_modules\n\n    def _pyi_pkgutil_iter_modules(path=None, prefix=''):\n        # Use original implementation to discover on-filesystem modules (binary extensions in regular builds, or both\n        # binary extensions and compiled pyc modules in noarchive debug builds).\n        yield from _orig_pkgutil_iter_modules(path, prefix)\n\n        # Find the instance of PyInstaller's PyiFrozenImporter.\n        for importer in pkgutil.iter_importers():\n            if isinstance(importer, PyiFrozenImporter):\n                break\n        else:\n            return\n\n        if path is None:\n            # Search for all top-level packages/modules. These will have no dots in their entry names.\n            for entry in importer.toc:\n                if \".\" in entry:\n                    continue\n                is_pkg = importer.is_package(entry)\n                yield pkgutil.ModuleInfo(importer, prefix + entry, is_pkg)\n        else:\n            # Use os.path.realpath() to fully resolve any symbolic links in sys._MEIPASS, in order to avoid path\n            # mis-matches when the given search paths also contain symbolic links and are already fully resolved.\n            # See #6537 for an example of such a problem with onefile build on macOS, where the temporary directory\n            # is placed under /var, which is actually a symbolic link to /private/var.\n            MEIPASS = os.path.realpath(sys._MEIPASS)\n\n            for pkg_path in path:\n                # Fully resolve the given path, in case it contains symbolic links.\n                pkg_path = os.path.realpath(pkg_path)\n                # Ensure it ends with os.path.sep (so we can directly filter out the package itself).\n                if not pkg_path.endswith(os.path.sep):\n                    pkg_path += os.path.sep\n\n                for entry in importer.toc:\n                    # Get the path to the module, and resolve symbolic links. This implicitly solves the problem with\n                    # macOS .app bundles and packages that contain data files, where package directory is fully\n                    # collected into Contents/Resources, and symbolic link to directory is created in sys._MEIPASS\n                    # (Contents/Frameworks). See #7884.\n                    module_path = os.path.realpath(os.path.join(MEIPASS, entry.replace(\".\", os.path.sep)))\n\n                    # If the module is not in the requested path, skip it.\n                    if not module_path.startswith(pkg_path):\n                        continue\n\n                    name = module_path[len(pkg_path):]\n\n                    if os.path.sep in name:\n                        # Not a direct child\n                        continue\n                    is_pkg = importer.is_package(entry)\n                    yield pkgutil.ModuleInfo(importer, prefix + name, is_pkg)\n\n    pkgutil.iter_modules = _pyi_pkgutil_iter_modules\n\n\n_pyi_rthook()\ndel _pyi_rthook\n", "path": "PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py"}]}