We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
MacOS onefile package, GUI does not display in High Resolution mode by default. Now it's 2019, so I suggest make the 'NSHighResolutionCapable' option a default.
Hi dear developers,

I found a small issue on mac os x, after running the command 'pyinstaller --onefile --noconsole myscript.py', there are 2 generated files, one is a Unix executable, the other one is a mac os APP PACKAGE. 

My program uses Tkinter for GUI, When the program is launched from the unix executable, it displays in the high resolution mode like a normal mac os app. But when launched from the APP Package, it will display in a low resolution mode, which looks really strange on today's Mac.

After a little search, I found this topic in Stackoverflow, https://stackoverflow.com/questions/40484659/pyinstaller-tkinter-window-low-resolution-in-app-bundle-but-not-in-app-program , added some configs as this topic suggests:

app = BUNDLE(exe,
     name='myscript.app',
     icon=None,
     bundle_identifier=None
     **info_plist={
        'NSHighResolutionCapable': 'True'
        },**
     )

and my program launched from package file now just displayed fine.
So it's all about the **NSHighResolutionCapable** option is disabled or not set by default.


Though my problem is solved, the reason why I still want to open this Issue is, **now it's 2019, in the MacWorld, Retina or High Resolution is already the mainstream,** almost all the Mac products are equipped with a Retina display, and people buy mac for its crisp display. 
Even if you are using an external display, now the 4k is the mainstream, there's no reason to hook a low resolution display especially on a Mac except you already have one and want to still use it.

So I suggest, make this option a DEFAULT in Mac OS version, since the command line executable displays in a high res mode, there's no reason why the App Package not. And high resolution is always what most folks expected. 

Make high resolution a default, no more tweaks, no more searches.

Consider this!

--- 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/building/osx.py`
Content:
```
1 #-----------------------------------------------------------------------------
2 # Copyright (c) 2005-2020, PyInstaller Development Team.
3 #
4 # Distributed under the terms of the GNU General Public License (version 2
5 # or later) with exception for distributing the bootloader.
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #
9 # SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
10 #-----------------------------------------------------------------------------
11 
12 import os
13 import plistlib
14 import shutil
15 from ..compat import is_darwin
16 from .api import EXE, COLLECT
17 from .datastruct import Target, TOC, logger
18 from .utils import _check_path_overlap, _rmtree, add_suffix_to_extensions, checkCache
19 
20 
21 
22 class BUNDLE(Target):
23     def __init__(self, *args, **kws):
24         from ..config import CONF
25 
26         # BUNDLE only has a sense under Mac OS X, it's a noop on other platforms
27         if not is_darwin:
28             return
29 
30         # get a path to a .icns icon for the app bundle.
31         self.icon = kws.get('icon')
32         if not self.icon:
33             # --icon not specified; use the default in the pyinstaller folder
34             self.icon = os.path.join(os.path.dirname(os.path.dirname(__file__)),
35                 'bootloader', 'images', 'icon-windowed.icns')
36         else:
37             # user gave an --icon=path. If it is relative, make it
38             # relative to the spec file location.
39             if not os.path.isabs(self.icon):
40                 self.icon = os.path.join(CONF['specpath'], self.icon)
41         # ensure icon path is absolute
42         self.icon = os.path.abspath(self.icon)
43 
44         Target.__init__(self)
45 
46         # .app bundle is created in DISTPATH.
47         self.name = kws.get('name', None)
48         base_name = os.path.basename(self.name)
49         self.name = os.path.join(CONF['distpath'], base_name)
50 
51         self.appname = os.path.splitext(base_name)[0]
52         self.version = kws.get("version", "0.0.0")
53         self.toc = TOC()
54         self.strip = False
55         self.upx = False
56         self.console = True
57 
58         # .app bundle identifier for Code Signing
59         self.bundle_identifier = kws.get('bundle_identifier')
60         if not self.bundle_identifier:
61             # Fallback to appname.
62             self.bundle_identifier = self.appname
63 
64         self.info_plist = kws.get('info_plist', None)
65 
66         for arg in args:
67             if isinstance(arg, EXE):
68                 self.toc.append((os.path.basename(arg.name), arg.name, arg.typ))
69                 self.toc.extend(arg.dependencies)
70                 self.strip = arg.strip
71                 self.upx = arg.upx
72                 self.upx_exclude = arg.upx_exclude
73                 self.console = arg.console
74             elif isinstance(arg, TOC):
75                 self.toc.extend(arg)
76                 # TOC doesn't have a strip or upx attribute, so there is no way for us to
77                 # tell which cache we should draw from.
78             elif isinstance(arg, COLLECT):
79                 self.toc.extend(arg.toc)
80                 self.strip = arg.strip_binaries
81                 self.upx = arg.upx_binaries
82                 self.upx_exclude = arg.upx_exclude
83                 self.console = arg.console
84             else:
85                 logger.info("unsupported entry %s", arg.__class__.__name__)
86         # Now, find values for app filepath (name), app name (appname), and name
87         # of the actual executable (exename) from the first EXECUTABLE item in
88         # toc, which might have come from a COLLECT too (not from an EXE).
89         for inm, name, typ in self.toc:
90             if typ == "EXECUTABLE":
91                 self.exename = name
92                 if self.name is None:
93                     self.appname = "Mac%s" % (os.path.splitext(inm)[0],)
94                     self.name = os.path.join(CONF['specpath'], self.appname + ".app")
95                 else:
96                     self.name = os.path.join(CONF['specpath'], self.name)
97                 break
98         self.__postinit__()
99 
100     _GUTS = (
101         # BUNDLE always builds, just want the toc to be written out
102         ('toc', None),
103     )
104 
105     def _check_guts(self, data, last_build):
106         # BUNDLE always needs to be executed, since it will clean the output
107         # directory anyway to make sure there is no existing cruft accumulating
108         return 1
109 
110     def assemble(self):
111         if _check_path_overlap(self.name) and os.path.isdir(self.name):
112             _rmtree(self.name)
113         logger.info("Building BUNDLE %s", self.tocbasename)
114 
115         # Create a minimal Mac bundle structure
116         os.makedirs(os.path.join(self.name, "Contents", "MacOS"))
117         os.makedirs(os.path.join(self.name, "Contents", "Resources"))
118         os.makedirs(os.path.join(self.name, "Contents", "Frameworks"))
119 
120         # Copy icns icon to Resources directory.
121         if os.path.exists(self.icon):
122             shutil.copy(self.icon, os.path.join(self.name, 'Contents', 'Resources'))
123         else:
124             logger.warning("icon not found %s", self.icon)
125 
126         # Key/values for a minimal Info.plist file
127         info_plist_dict = {"CFBundleDisplayName": self.appname,
128                            "CFBundleName": self.appname,
129 
130                            # Required by 'codesign' utility.
131                            # The value for CFBundleIdentifier is used as the default unique
132                            # name of your program for Code Signing purposes.
133                            # It even identifies the APP for access to restricted OS X areas
134                            # like Keychain.
135                            #
136                            # The identifier used for signing must be globally unique. The usal
137                            # form for this identifier is a hierarchical name in reverse DNS
138                            # notation, starting with the toplevel domain, followed by the
139                            # company name, followed by the department within the company, and
140                            # ending with the product name. Usually in the form:
141                            #   com.mycompany.department.appname
142                            # Cli option --osx-bundle-identifier sets this value.
143                            "CFBundleIdentifier": self.bundle_identifier,
144 
145                            # Fix for #156 - 'MacOS' must be in the name - not sure why
146                            "CFBundleExecutable": 'MacOS/%s' % os.path.basename(self.exename),
147                            "CFBundleIconFile": os.path.basename(self.icon),
148                            "CFBundleInfoDictionaryVersion": "6.0",
149                            "CFBundlePackageType": "APPL",
150                            "CFBundleShortVersionString": self.version,
151 
152                            }
153 
154         # Setting EXE console=True implies LSBackgroundOnly=True.
155         # But it still can be overwrite by the user.
156         if self.console:
157             info_plist_dict['LSBackgroundOnly'] = True
158 
159         # Merge info_plist settings from spec file
160         if isinstance(self.info_plist, dict) and self.info_plist:
161             info_plist_dict.update(self.info_plist)
162 
163         plist_filename = os.path.join(self.name, "Contents", "Info.plist")
164         with open(plist_filename, "wb") as plist_fh:
165             plistlib.dump(info_plist_dict, plist_fh)
166 
167         links = []
168         toc = add_suffix_to_extensions(self.toc)
169         for inm, fnm, typ in toc:
170             # Copy files from cache. This ensures that are used files with relative
171             # paths to dynamic library dependencies (@executable_path)
172             base_path = inm.split('/', 1)[0]
173             if typ in ('EXTENSION', 'BINARY'):
174                 fnm = checkCache(fnm, strip=self.strip, upx=self.upx,
175                                  upx_exclude=self.upx_exclude, dist_nm=inm)
176             # Add most data files to a list for symlinking later.
177             if typ == 'DATA' and base_path not in ('base_library.zip', 'PySide2', 'PyQt5'):
178                 links.append((inm, fnm))
179             else:
180                 tofnm = os.path.join(self.name, "Contents", "MacOS", inm)
181                 todir = os.path.dirname(tofnm)
182                 if not os.path.exists(todir):
183                     os.makedirs(todir)
184                 if os.path.isdir(fnm):
185                     # beacuse shutil.copy2() is the default copy function
186                     # for shutil.copytree, this will also copy file metadata
187                     shutil.copytree(fnm, tofnm)
188                 else:
189                     shutil.copy(fnm, tofnm)
190 
191         logger.info('moving BUNDLE data files to Resource directory')
192 
193         # Mac OS X Code Signing does not work when .app bundle contains
194         # data files in dir ./Contents/MacOS.
195         #
196         # Put all data files in ./Resources and create symlinks in ./MacOS.
197         bin_dir = os.path.join(self.name, 'Contents', 'MacOS')
198         res_dir = os.path.join(self.name, 'Contents', 'Resources')
199         for inm, fnm in links:
200             tofnm = os.path.join(res_dir, inm)
201             todir = os.path.dirname(tofnm)
202             if not os.path.exists(todir):
203                 os.makedirs(todir)
204             if os.path.isdir(fnm):
205                 # beacuse shutil.copy2() is the default copy function
206                 # for shutil.copytree, this will also copy file metadata
207                 shutil.copytree(fnm, tofnm)
208             else:
209                 shutil.copy(fnm, tofnm)
210             base_path = os.path.split(inm)[0]
211             if base_path:
212                 if not os.path.exists(os.path.join(bin_dir, inm)):
213                     path = ''
214                     for part in iter(base_path.split(os.path.sep)):
215                         # Build path from previous path and the next part of the base path
216                         path = os.path.join(path, part)
217                         try:
218                             relative_source_path = os.path.relpath(os.path.join(res_dir, path),
219                                                                    os.path.split(os.path.join(bin_dir, path))[0])
220                             dest_path = os.path.join(bin_dir, path)
221                             os.symlink(relative_source_path, dest_path)
222                             break
223                         except FileExistsError:
224                             pass
225                     if not os.path.exists(os.path.join(bin_dir, inm)):
226                         relative_source_path = os.path.relpath(os.path.join(res_dir, inm),
227                                                                os.path.split(os.path.join(bin_dir, inm))[0])
228                         dest_path = os.path.join(bin_dir, inm)
229                         os.symlink(relative_source_path, dest_path)
230             else:  # If path is empty, e.g., a top level file, try to just symlink the file
231                 os.symlink(os.path.relpath(os.path.join(res_dir, inm),
232                                            os.path.split(os.path.join(bin_dir, inm))[0]),
233                            os.path.join(bin_dir, inm))
234
```
--- 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()

```

diff --git a/PyInstaller/building/osx.py b/PyInstaller/building/osx.py
--- a/PyInstaller/building/osx.py
+++ b/PyInstaller/building/osx.py
@@ -151,10 +151,14 @@
 
                            }
 
-        # Setting EXE console=True implies LSBackgroundOnly=True.
-        # But it still can be overwrite by the user.
+        # Set some default values.
+        # But they still can be overwritten by the user.
         if self.console:
+            # Setting EXE console=True implies LSBackgroundOnly=True.
             info_plist_dict['LSBackgroundOnly'] = True
+        else:
+            # Let's use high resolution by default.
+            info_plist_dict['NSHighResolutionCapable'] = True
 
         # Merge info_plist settings from spec file
         if isinstance(self.info_plist, dict) and self.info_plist:

{"golden_diff": "diff --git a/PyInstaller/building/osx.py b/PyInstaller/building/osx.py\n--- a/PyInstaller/building/osx.py\n+++ b/PyInstaller/building/osx.py\n@@ -151,10 +151,14 @@\n \n                            }\n \n-        # Setting EXE console=True implies LSBackgroundOnly=True.\n-        # But it still can be overwrite by the user.\n+        # Set some default values.\n+        # But they still can be overwritten by the user.\n         if self.console:\n+            # Setting EXE console=True implies LSBackgroundOnly=True.\n             info_plist_dict['LSBackgroundOnly'] = True\n+        else:\n+            # Let's use high resolution by default.\n+            info_plist_dict['NSHighResolutionCapable'] = True\n \n         # Merge info_plist settings from spec file\n         if isinstance(self.info_plist, dict) and self.info_plist:\n", "issue": "MacOS onefile package, GUI does not display in High Resolution mode by default. Now it's 2019, so I suggest make the 'NSHighResolutionCapable' option a default.\nHi dear developers,\r\n\r\nI found a small issue on mac os x, after running the command 'pyinstaller --onefile --noconsole myscript.py', there are 2 generated files, one is a Unix executable, the other one is a mac os APP PACKAGE. \r\n\r\nMy program uses Tkinter for GUI, When the program is launched from the unix executable, it displays in the high resolution mode like a normal mac os app. But when launched from the APP Package, it will display in a low resolution mode, which looks really strange on today's Mac.\r\n\r\nAfter a little search, I found this topic in Stackoverflow, https://stackoverflow.com/questions/40484659/pyinstaller-tkinter-window-low-resolution-in-app-bundle-but-not-in-app-program , added some configs as this topic suggests:\r\n\r\napp = BUNDLE(exe,\r\n     name='myscript.app',\r\n     icon=None,\r\n     bundle_identifier=None\r\n     **info_plist={\r\n        'NSHighResolutionCapable': 'True'\r\n        },**\r\n     )\r\n\r\nand my program launched from package file now just displayed fine.\r\nSo it's all about the **NSHighResolutionCapable** option is disabled or not set by default.\r\n\r\n\r\nThough my problem is solved, the reason why I still want to open this Issue is, **now it's 2019, in the MacWorld, Retina or High Resolution is already the mainstream,** almost all the Mac products are equipped with a Retina display, and people buy mac for its crisp display. \r\nEven if you are using an external display, now the 4k is the mainstream, there's no reason to hook a low resolution display especially on a Mac except you already have one and want to still use it.\r\n\r\nSo I suggest, make this option a DEFAULT in Mac OS version, since the command line executable displays in a high res mode, there's no reason why the App Package not. And high resolution is always what most folks expected. \r\n\r\nMake high resolution a default, no more tweaks, no more searches.\r\n\r\nConsider this!\n", "before_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2005-2020, PyInstaller Development Team.\n#\n# Distributed under the terms of the GNU General Public License (version 2\n# or later) with exception for distributing the bootloader.\n#\n# The full license is in the file COPYING.txt, distributed with this software.\n#\n# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)\n#-----------------------------------------------------------------------------\n\nimport os\nimport plistlib\nimport shutil\nfrom ..compat import is_darwin\nfrom .api import EXE, COLLECT\nfrom .datastruct import Target, TOC, logger\nfrom .utils import _check_path_overlap, _rmtree, add_suffix_to_extensions, checkCache\n\n\n\nclass BUNDLE(Target):\n    def __init__(self, *args, **kws):\n        from ..config import CONF\n\n        # BUNDLE only has a sense under Mac OS X, it's a noop on other platforms\n        if not is_darwin:\n            return\n\n        # get a path to a .icns icon for the app bundle.\n        self.icon = kws.get('icon')\n        if not self.icon:\n            # --icon not specified; use the default in the pyinstaller folder\n            self.icon = os.path.join(os.path.dirname(os.path.dirname(__file__)),\n                'bootloader', 'images', 'icon-windowed.icns')\n        else:\n            # user gave an --icon=path. If it is relative, make it\n            # relative to the spec file location.\n            if not os.path.isabs(self.icon):\n                self.icon = os.path.join(CONF['specpath'], self.icon)\n        # ensure icon path is absolute\n        self.icon = os.path.abspath(self.icon)\n\n        Target.__init__(self)\n\n        # .app bundle is created in DISTPATH.\n        self.name = kws.get('name', None)\n        base_name = os.path.basename(self.name)\n        self.name = os.path.join(CONF['distpath'], base_name)\n\n        self.appname = os.path.splitext(base_name)[0]\n        self.version = kws.get(\"version\", \"0.0.0\")\n        self.toc = TOC()\n        self.strip = False\n        self.upx = False\n        self.console = True\n\n        # .app bundle identifier for Code Signing\n        self.bundle_identifier = kws.get('bundle_identifier')\n        if not self.bundle_identifier:\n            # Fallback to appname.\n            self.bundle_identifier = self.appname\n\n        self.info_plist = kws.get('info_plist', None)\n\n        for arg in args:\n            if isinstance(arg, EXE):\n                self.toc.append((os.path.basename(arg.name), arg.name, arg.typ))\n                self.toc.extend(arg.dependencies)\n                self.strip = arg.strip\n                self.upx = arg.upx\n                self.upx_exclude = arg.upx_exclude\n                self.console = arg.console\n            elif isinstance(arg, TOC):\n                self.toc.extend(arg)\n                # TOC doesn't have a strip or upx attribute, so there is no way for us to\n                # tell which cache we should draw from.\n            elif isinstance(arg, COLLECT):\n                self.toc.extend(arg.toc)\n                self.strip = arg.strip_binaries\n                self.upx = arg.upx_binaries\n                self.upx_exclude = arg.upx_exclude\n                self.console = arg.console\n            else:\n                logger.info(\"unsupported entry %s\", arg.__class__.__name__)\n        # Now, find values for app filepath (name), app name (appname), and name\n        # of the actual executable (exename) from the first EXECUTABLE item in\n        # toc, which might have come from a COLLECT too (not from an EXE).\n        for inm, name, typ in self.toc:\n            if typ == \"EXECUTABLE\":\n                self.exename = name\n                if self.name is None:\n                    self.appname = \"Mac%s\" % (os.path.splitext(inm)[0],)\n                    self.name = os.path.join(CONF['specpath'], self.appname + \".app\")\n                else:\n                    self.name = os.path.join(CONF['specpath'], self.name)\n                break\n        self.__postinit__()\n\n    _GUTS = (\n        # BUNDLE always builds, just want the toc to be written out\n        ('toc', None),\n    )\n\n    def _check_guts(self, data, last_build):\n        # BUNDLE always needs to be executed, since it will clean the output\n        # directory anyway to make sure there is no existing cruft accumulating\n        return 1\n\n    def assemble(self):\n        if _check_path_overlap(self.name) and os.path.isdir(self.name):\n            _rmtree(self.name)\n        logger.info(\"Building BUNDLE %s\", self.tocbasename)\n\n        # Create a minimal Mac bundle structure\n        os.makedirs(os.path.join(self.name, \"Contents\", \"MacOS\"))\n        os.makedirs(os.path.join(self.name, \"Contents\", \"Resources\"))\n        os.makedirs(os.path.join(self.name, \"Contents\", \"Frameworks\"))\n\n        # Copy icns icon to Resources directory.\n        if os.path.exists(self.icon):\n            shutil.copy(self.icon, os.path.join(self.name, 'Contents', 'Resources'))\n        else:\n            logger.warning(\"icon not found %s\", self.icon)\n\n        # Key/values for a minimal Info.plist file\n        info_plist_dict = {\"CFBundleDisplayName\": self.appname,\n                           \"CFBundleName\": self.appname,\n\n                           # Required by 'codesign' utility.\n                           # The value for CFBundleIdentifier is used as the default unique\n                           # name of your program for Code Signing purposes.\n                           # It even identifies the APP for access to restricted OS X areas\n                           # like Keychain.\n                           #\n                           # The identifier used for signing must be globally unique. The usal\n                           # form for this identifier is a hierarchical name in reverse DNS\n                           # notation, starting with the toplevel domain, followed by the\n                           # company name, followed by the department within the company, and\n                           # ending with the product name. Usually in the form:\n                           #   com.mycompany.department.appname\n                           # Cli option --osx-bundle-identifier sets this value.\n                           \"CFBundleIdentifier\": self.bundle_identifier,\n\n                           # Fix for #156 - 'MacOS' must be in the name - not sure why\n                           \"CFBundleExecutable\": 'MacOS/%s' % os.path.basename(self.exename),\n                           \"CFBundleIconFile\": os.path.basename(self.icon),\n                           \"CFBundleInfoDictionaryVersion\": \"6.0\",\n                           \"CFBundlePackageType\": \"APPL\",\n                           \"CFBundleShortVersionString\": self.version,\n\n                           }\n\n        # Setting EXE console=True implies LSBackgroundOnly=True.\n        # But it still can be overwrite by the user.\n        if self.console:\n            info_plist_dict['LSBackgroundOnly'] = True\n\n        # Merge info_plist settings from spec file\n        if isinstance(self.info_plist, dict) and self.info_plist:\n            info_plist_dict.update(self.info_plist)\n\n        plist_filename = os.path.join(self.name, \"Contents\", \"Info.plist\")\n        with open(plist_filename, \"wb\") as plist_fh:\n            plistlib.dump(info_plist_dict, plist_fh)\n\n        links = []\n        toc = add_suffix_to_extensions(self.toc)\n        for inm, fnm, typ in toc:\n            # Copy files from cache. This ensures that are used files with relative\n            # paths to dynamic library dependencies (@executable_path)\n            base_path = inm.split('/', 1)[0]\n            if typ in ('EXTENSION', 'BINARY'):\n                fnm = checkCache(fnm, strip=self.strip, upx=self.upx,\n                                 upx_exclude=self.upx_exclude, dist_nm=inm)\n            # Add most data files to a list for symlinking later.\n            if typ == 'DATA' and base_path not in ('base_library.zip', 'PySide2', 'PyQt5'):\n                links.append((inm, fnm))\n            else:\n                tofnm = os.path.join(self.name, \"Contents\", \"MacOS\", inm)\n                todir = os.path.dirname(tofnm)\n                if not os.path.exists(todir):\n                    os.makedirs(todir)\n                if os.path.isdir(fnm):\n                    # beacuse shutil.copy2() is the default copy function\n                    # for shutil.copytree, this will also copy file metadata\n                    shutil.copytree(fnm, tofnm)\n                else:\n                    shutil.copy(fnm, tofnm)\n\n        logger.info('moving BUNDLE data files to Resource directory')\n\n        # Mac OS X Code Signing does not work when .app bundle contains\n        # data files in dir ./Contents/MacOS.\n        #\n        # Put all data files in ./Resources and create symlinks in ./MacOS.\n        bin_dir = os.path.join(self.name, 'Contents', 'MacOS')\n        res_dir = os.path.join(self.name, 'Contents', 'Resources')\n        for inm, fnm in links:\n            tofnm = os.path.join(res_dir, inm)\n            todir = os.path.dirname(tofnm)\n            if not os.path.exists(todir):\n                os.makedirs(todir)\n            if os.path.isdir(fnm):\n                # beacuse shutil.copy2() is the default copy function\n                # for shutil.copytree, this will also copy file metadata\n                shutil.copytree(fnm, tofnm)\n            else:\n                shutil.copy(fnm, tofnm)\n            base_path = os.path.split(inm)[0]\n            if base_path:\n                if not os.path.exists(os.path.join(bin_dir, inm)):\n                    path = ''\n                    for part in iter(base_path.split(os.path.sep)):\n                        # Build path from previous path and the next part of the base path\n                        path = os.path.join(path, part)\n                        try:\n                            relative_source_path = os.path.relpath(os.path.join(res_dir, path),\n                                                                   os.path.split(os.path.join(bin_dir, path))[0])\n                            dest_path = os.path.join(bin_dir, path)\n                            os.symlink(relative_source_path, dest_path)\n                            break\n                        except FileExistsError:\n                            pass\n                    if not os.path.exists(os.path.join(bin_dir, inm)):\n                        relative_source_path = os.path.relpath(os.path.join(res_dir, inm),\n                                                               os.path.split(os.path.join(bin_dir, inm))[0])\n                        dest_path = os.path.join(bin_dir, inm)\n                        os.symlink(relative_source_path, dest_path)\n            else:  # If path is empty, e.g., a top level file, try to just symlink the file\n                os.symlink(os.path.relpath(os.path.join(res_dir, inm),\n                                           os.path.split(os.path.join(bin_dir, inm))[0]),\n                           os.path.join(bin_dir, inm))\n", "path": "PyInstaller/building/osx.py"}], "after_files": [{"content": "#-----------------------------------------------------------------------------\n# Copyright (c) 2005-2020, PyInstaller Development Team.\n#\n# Distributed under the terms of the GNU General Public License (version 2\n# or later) with exception for distributing the bootloader.\n#\n# The full license is in the file COPYING.txt, distributed with this software.\n#\n# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)\n#-----------------------------------------------------------------------------\n\nimport os\nimport plistlib\nimport shutil\nfrom ..compat import is_darwin\nfrom .api import EXE, COLLECT\nfrom .datastruct import Target, TOC, logger\nfrom .utils import _check_path_overlap, _rmtree, add_suffix_to_extensions, checkCache\n\n\n\nclass BUNDLE(Target):\n    def __init__(self, *args, **kws):\n        from ..config import CONF\n\n        # BUNDLE only has a sense under Mac OS X, it's a noop on other platforms\n        if not is_darwin:\n            return\n\n        # get a path to a .icns icon for the app bundle.\n        self.icon = kws.get('icon')\n        if not self.icon:\n            # --icon not specified; use the default in the pyinstaller folder\n            self.icon = os.path.join(os.path.dirname(os.path.dirname(__file__)),\n                'bootloader', 'images', 'icon-windowed.icns')\n        else:\n            # user gave an --icon=path. If it is relative, make it\n            # relative to the spec file location.\n            if not os.path.isabs(self.icon):\n                self.icon = os.path.join(CONF['specpath'], self.icon)\n        # ensure icon path is absolute\n        self.icon = os.path.abspath(self.icon)\n\n        Target.__init__(self)\n\n        # .app bundle is created in DISTPATH.\n        self.name = kws.get('name', None)\n        base_name = os.path.basename(self.name)\n        self.name = os.path.join(CONF['distpath'], base_name)\n\n        self.appname = os.path.splitext(base_name)[0]\n        self.version = kws.get(\"version\", \"0.0.0\")\n        self.toc = TOC()\n        self.strip = False\n        self.upx = False\n        self.console = True\n\n        # .app bundle identifier for Code Signing\n        self.bundle_identifier = kws.get('bundle_identifier')\n        if not self.bundle_identifier:\n            # Fallback to appname.\n            self.bundle_identifier = self.appname\n\n        self.info_plist = kws.get('info_plist', None)\n\n        for arg in args:\n            if isinstance(arg, EXE):\n                self.toc.append((os.path.basename(arg.name), arg.name, arg.typ))\n                self.toc.extend(arg.dependencies)\n                self.strip = arg.strip\n                self.upx = arg.upx\n                self.upx_exclude = arg.upx_exclude\n                self.console = arg.console\n            elif isinstance(arg, TOC):\n                self.toc.extend(arg)\n                # TOC doesn't have a strip or upx attribute, so there is no way for us to\n                # tell which cache we should draw from.\n            elif isinstance(arg, COLLECT):\n                self.toc.extend(arg.toc)\n                self.strip = arg.strip_binaries\n                self.upx = arg.upx_binaries\n                self.upx_exclude = arg.upx_exclude\n                self.console = arg.console\n            else:\n                logger.info(\"unsupported entry %s\", arg.__class__.__name__)\n        # Now, find values for app filepath (name), app name (appname), and name\n        # of the actual executable (exename) from the first EXECUTABLE item in\n        # toc, which might have come from a COLLECT too (not from an EXE).\n        for inm, name, typ in self.toc:\n            if typ == \"EXECUTABLE\":\n                self.exename = name\n                if self.name is None:\n                    self.appname = \"Mac%s\" % (os.path.splitext(inm)[0],)\n                    self.name = os.path.join(CONF['specpath'], self.appname + \".app\")\n                else:\n                    self.name = os.path.join(CONF['specpath'], self.name)\n                break\n        self.__postinit__()\n\n    _GUTS = (\n        # BUNDLE always builds, just want the toc to be written out\n        ('toc', None),\n    )\n\n    def _check_guts(self, data, last_build):\n        # BUNDLE always needs to be executed, since it will clean the output\n        # directory anyway to make sure there is no existing cruft accumulating\n        return 1\n\n    def assemble(self):\n        if _check_path_overlap(self.name) and os.path.isdir(self.name):\n            _rmtree(self.name)\n        logger.info(\"Building BUNDLE %s\", self.tocbasename)\n\n        # Create a minimal Mac bundle structure\n        os.makedirs(os.path.join(self.name, \"Contents\", \"MacOS\"))\n        os.makedirs(os.path.join(self.name, \"Contents\", \"Resources\"))\n        os.makedirs(os.path.join(self.name, \"Contents\", \"Frameworks\"))\n\n        # Copy icns icon to Resources directory.\n        if os.path.exists(self.icon):\n            shutil.copy(self.icon, os.path.join(self.name, 'Contents', 'Resources'))\n        else:\n            logger.warning(\"icon not found %s\", self.icon)\n\n        # Key/values for a minimal Info.plist file\n        info_plist_dict = {\"CFBundleDisplayName\": self.appname,\n                           \"CFBundleName\": self.appname,\n\n                           # Required by 'codesign' utility.\n                           # The value for CFBundleIdentifier is used as the default unique\n                           # name of your program for Code Signing purposes.\n                           # It even identifies the APP for access to restricted OS X areas\n                           # like Keychain.\n                           #\n                           # The identifier used for signing must be globally unique. The usal\n                           # form for this identifier is a hierarchical name in reverse DNS\n                           # notation, starting with the toplevel domain, followed by the\n                           # company name, followed by the department within the company, and\n                           # ending with the product name. Usually in the form:\n                           #   com.mycompany.department.appname\n                           # Cli option --osx-bundle-identifier sets this value.\n                           \"CFBundleIdentifier\": self.bundle_identifier,\n\n                           # Fix for #156 - 'MacOS' must be in the name - not sure why\n                           \"CFBundleExecutable\": 'MacOS/%s' % os.path.basename(self.exename),\n                           \"CFBundleIconFile\": os.path.basename(self.icon),\n                           \"CFBundleInfoDictionaryVersion\": \"6.0\",\n                           \"CFBundlePackageType\": \"APPL\",\n                           \"CFBundleShortVersionString\": self.version,\n\n                           }\n\n        # Set some default values.\n        # But they still can be overwritten by the user.\n        if self.console:\n            # Setting EXE console=True implies LSBackgroundOnly=True.\n            info_plist_dict['LSBackgroundOnly'] = True\n        else:\n            # Let's use high resolution by default.\n            info_plist_dict['NSHighResolutionCapable'] = True\n\n        # Merge info_plist settings from spec file\n        if isinstance(self.info_plist, dict) and self.info_plist:\n            info_plist_dict.update(self.info_plist)\n\n        plist_filename = os.path.join(self.name, \"Contents\", \"Info.plist\")\n        with open(plist_filename, \"wb\") as plist_fh:\n            plistlib.dump(info_plist_dict, plist_fh)\n\n        links = []\n        toc = add_suffix_to_extensions(self.toc)\n        for inm, fnm, typ in toc:\n            # Copy files from cache. This ensures that are used files with relative\n            # paths to dynamic library dependencies (@executable_path)\n            base_path = inm.split('/', 1)[0]\n            if typ in ('EXTENSION', 'BINARY'):\n                fnm = checkCache(fnm, strip=self.strip, upx=self.upx,\n                                 upx_exclude=self.upx_exclude, dist_nm=inm)\n            # Add most data files to a list for symlinking later.\n            if typ == 'DATA' and base_path not in ('base_library.zip', 'PySide2', 'PyQt5'):\n                links.append((inm, fnm))\n            else:\n                tofnm = os.path.join(self.name, \"Contents\", \"MacOS\", inm)\n                todir = os.path.dirname(tofnm)\n                if not os.path.exists(todir):\n                    os.makedirs(todir)\n                if os.path.isdir(fnm):\n                    # beacuse shutil.copy2() is the default copy function\n                    # for shutil.copytree, this will also copy file metadata\n                    shutil.copytree(fnm, tofnm)\n                else:\n                    shutil.copy(fnm, tofnm)\n\n        logger.info('moving BUNDLE data files to Resource directory')\n\n        # Mac OS X Code Signing does not work when .app bundle contains\n        # data files in dir ./Contents/MacOS.\n        #\n        # Put all data files in ./Resources and create symlinks in ./MacOS.\n        bin_dir = os.path.join(self.name, 'Contents', 'MacOS')\n        res_dir = os.path.join(self.name, 'Contents', 'Resources')\n        for inm, fnm in links:\n            tofnm = os.path.join(res_dir, inm)\n            todir = os.path.dirname(tofnm)\n            if not os.path.exists(todir):\n                os.makedirs(todir)\n            if os.path.isdir(fnm):\n                # beacuse shutil.copy2() is the default copy function\n                # for shutil.copytree, this will also copy file metadata\n                shutil.copytree(fnm, tofnm)\n            else:\n                shutil.copy(fnm, tofnm)\n            base_path = os.path.split(inm)[0]\n            if base_path:\n                if not os.path.exists(os.path.join(bin_dir, inm)):\n                    path = ''\n                    for part in iter(base_path.split(os.path.sep)):\n                        # Build path from previous path and the next part of the base path\n                        path = os.path.join(path, part)\n                        try:\n                            relative_source_path = os.path.relpath(os.path.join(res_dir, path),\n                                                                   os.path.split(os.path.join(bin_dir, path))[0])\n                            dest_path = os.path.join(bin_dir, path)\n                            os.symlink(relative_source_path, dest_path)\n                            break\n                        except FileExistsError:\n                            pass\n                    if not os.path.exists(os.path.join(bin_dir, inm)):\n                        relative_source_path = os.path.relpath(os.path.join(res_dir, inm),\n                                                               os.path.split(os.path.join(bin_dir, inm))[0])\n                        dest_path = os.path.join(bin_dir, inm)\n                        os.symlink(relative_source_path, dest_path)\n            else:  # If path is empty, e.g., a top level file, try to just symlink the file\n                os.symlink(os.path.relpath(os.path.join(res_dir, inm),\n                                           os.path.split(os.path.join(bin_dir, inm))[0]),\n                           os.path.join(bin_dir, inm))\n", "path": "PyInstaller/building/osx.py"}]}