Пример #1
0
def make_app_bundle(dist_dir, make_lite=False):
    """
    Make macOS application bundle.

    Parameters
    ----------
    dist_dir : pathlib.Path
        Directory in which to put the application bundle.
    make_lite : bool, optional
        Whether to create the application bundle with minimal packages.
        The default is False.
    """
    from spyder.config.utils import EDIT_FILETYPES, _get_extensions

    build_type = 'lite' if make_lite else 'full'
    logger.info('Creating %s app bundle...', build_type)

    from packages import PACKAGES, INCLUDES, EXCLUDES, SCIENTIFIC

    if make_lite:
        EXCLUDES.extend(SCIENTIFIC)
    else:
        INCLUDES.extend(SCIENTIFIC)

    EDIT_EXT = [ext[1:] for ext in _get_extensions(EDIT_FILETYPES)]

    OPTIONS = {
        'optimize': 0,
        'packages': PACKAGES,
        'includes': INCLUDES,
        'excludes': EXCLUDES,
        'iconfile': ICONFILE.as_posix(),
        'dist_dir': dist_dir.as_posix(),
        'emulate_shell_environment': True,
        'plist': {
            'CFBundleDocumentTypes': [{
                'CFBundleTypeExtensions': EDIT_EXT,
                'CFBundleTypeName': 'Text File',
                'CFBundleTypeRole': 'Editor'
            }],
            'CFBundleIdentifier':
            'org.spyder-ide.Spyder',
            'CFBundleShortVersionString':
            SPYVER,
            'NSRequiresAquaSystemAppearance':
            False,  # Darkmode support
            'LSEnvironment': {
                'SPY_COMMIT': SPYCOM,
                'SPY_BRANCH': SPYBRA
            }
        }
    }

    # Build the application
    setup(name=APP_BASE_NAME,
          app=[APPSCRIPT.as_posix()],
          options={'py2app': OPTIONS})

    return
Пример #2
0
def make_app_bundle(dist_dir, make_lite=False):
    """
    Make macOS application bundle.

    Parameters
    ----------
    dist_dir : str
        Directory in which to put the application bundle.
    make_lite : bool, optional
        Whether to create the application bundle with minimal packages.
        The default is False.

    NOTES
    -----
    py2app includes all packages in Spyder.app/Contents/Resources/lib/
    python<ver>.zip, but some packages have issues when placed there.
    The following packages are included in py2app's PACKAGES option so that
    they will be placed in Spyder.app/Contents/Resources/lib/python<ver>
    instead.

    alabaster :
        Error message: [Errno 20] Not a directory: '<path>/Resources/lib/
        python38.zip/alabaster'
    astroid :
        ImportError: cannot import name 'context' from 'astroid'
        (<path>/Resources/lib/python38.zip/astroid/__init__.pyc)
    ipykernel :
        ModuleNotFoundError: No module named 'ipykernel.datapub'
    ipython :
        [IPKernelApp] WARNING | Could not copy README_STARTUP to startup dir.
        Source file
        <path>/Resources/lib/python38.zip/IPython/core/profile/README_STARTUP
        does not exist
    jedi :
        jedi.api.environment.InvalidPythonEnvironment: Could not get version
        information for '<path>/Contents/MacOS/python': InternalError("The
        subprocess <path>/Contents/MacOS/python has crashed (EOFError('Ran out
        of input'), stderr=).")
    jinja2 :
        No module named 'jinja2.ext'
    keyring :
        ModuleNotFoundError: No module named 'keyring.backends.<mod>'
    parso :
        NotADirectoryError: [Errno 20] Not a directory:
        '<path>/Resources/lib/python38.zip/parso/python/grammar38.txt'
    PIL :
        Library not loaded: @loader_path/.dylibs/libjpeg.9.dylib
        Note: only applicable to not-Lite build
    pygments :
        ModuleNotFoundError: No module named 'pygments.formatters.latex'
    pyls :
        <path>/Contents/MacOS/python: No module named pyls
        Note: still occurs in alias mode
    qtawesome :
        NotADirectoryError: [Errno 20] Not a directory: '<path>/Resourses/lib/
        python38.zip/qtawesome/fonts/fontawesome4.7-webfont.ttf'
    spyder :
        NotADirectoryError: [Errno 20] Not a directory: '<path>/Resources/lib/
        python38.zip/spyder/app/mac_stylesheet.qss'
    spyder_kernels :
        No module named spyder_kernels.console.__main__
    sphinx :
        No module named 'sphinx.builders.changes'

   """
    build_type = 'lite' if make_lite else 'full'
    logger.info('Creating %s app bundle...', build_type)

    PACKAGES = ['alabaster', 'astroid', 'ipykernel', 'IPython', 'jedi',
                'jinja2', 'keyring', 'parso', 'pygments', 'pyls', 'qtawesome',
                'spyder', 'spyder_kernels', 'sphinx']

    if make_lite:
        INCLUDES = []
        EXCLUDES = [
            'numpy', 'scipy', 'pandas', 'matplotlib', 'cython', 'sympy'
        ]
    else:
        INCLUDES = [
            'numpy', 'scipy', 'pandas', 'matplotlib', 'cython', 'sympy'
        ]
        EXCLUDES = []
        PACKAGES.append('PIL')

    EDIT_EXT = [ext[1:] for ext in _get_extensions(EDIT_FILETYPES)]

    OPTIONS = {
        'optimize': 0,
        'packages': PACKAGES,
        'includes': INCLUDES,
        'excludes': EXCLUDES,
        'iconfile': ICONFILE,
        'dist_dir': dist_dir,
        'plist': {
            'CFBundleDocumentTypes': [{'CFBundleTypeExtensions': EDIT_EXT,
                                       'CFBundleTypeName': 'Text File',
                                       'CFBundleTypeRole': 'Editor'}],
            'CFBundleIdentifier': 'org.spyder-ide',
            'CFBundleShortVersionString': SPYVER
        }
    }

    # Copy main application script
    app_script_name = MAC_APP_NAME.replace('.app', '.py')
    app_script_path = os.path.join(SPYREPO, 'scripts', app_script_name)
    shutil.copy2(os.path.join(SPYREPO, 'scripts', 'spyder'), app_script_path)

    try:
        setup(app=[app_script_path], options={'py2app': OPTIONS})
    finally:
        os.remove(app_script_path)

    # Copy egg info from site-packages: fixes pkg_resources issue for pyls
    dest_dir = os.path.join(dist_dir, MAC_APP_NAME, 'Contents', 'Resources',
                            'lib', f'python{PYVER[0]}.{PYVER[1]}')
    for dist in pkg_resources.working_set:
        if dist.egg_info is None:
            continue
        dest = os.path.join(dest_dir, os.path.basename(dist.egg_info))
        shutil.copytree(dist.egg_info, dest)

    logger.info('App bundle complete.')

    return
Пример #3
0
APP = [APP_MAIN_SCRIPT]
DEPS = ['pylint', 'logilab', 'astroid', 'pycodestyle', 'setuptools']
EXCLUDES = DEPS + ['mercurial']
PACKAGES = [
    'spyder', 'spyder_breakpoints', 'spyder_io_dcm', 'spyder_io_hdf5',
    'spyder_profiler', 'spyder_pylint', 'sphinx', 'jinja2', 'docutils',
    'alabaster', 'babel', 'snowballstemmer', 'sphinx_rtd_theme', 'IPython',
    'ipykernel', 'ipython_genutils', 'jupyter_client', 'jupyter_core',
    'traitlets', 'qtconsole', 'pexpect', 'jedi', 'jsonschema', 'nbconvert',
    'nbformat', 'qtpy', 'qtawesome', 'zmq', 'pygments', 'rope', 'distutils',
    'PIL', 'PyQt5', 'sklearn', 'skimage', 'pandas', 'sympy', 'pyflakes',
    'psutil', 'nose', 'patsy', 'statsmodels', 'seaborn', 'networkx'
]

INCLUDES = get_stdlib_modules()
EDIT_EXT = [ext[1:] for ext in _get_extensions(EDIT_FILETYPES)]

OPTIONS = {
    'argv_emulation': True,
    'compressed': False,
    'optimize': 0,
    'packages': PACKAGES,
    'includes': INCLUDES,
    'excludes': EXCLUDES,
    'iconfile': 'img_src/spyder.icns',
    'plist': {
        'CFBundleDocumentTypes': [{
            'CFBundleTypeExtensions': EDIT_EXT,
            'CFBundleTypeName': 'Text File',
            'CFBundleTypeRole': 'Editor'
        }],
Пример #4
0
def make_app_bundle(dist_dir, make_lite=False):
    """
    Make macOS application bundle.

    Parameters
    ----------
    dist_dir : str
        Directory in which to put the application bundle.
    make_lite : bool, optional
        Whether to create the application bundle with minimal packages.
        The default is False.

    NOTES
    -----
    py2app includes all packages in Spyder.app/Contents/Resources/lib/
    python<ver>.zip, but some packages have issues when placed there.
    The following packages are included in py2app's PACKAGES option so that
    they will be placed in Spyder.app/Contents/Resources/lib/python<ver>
    instead.

    alabaster :
        Error message: [Errno 20] Not a directory: '<path>/Resources/lib/
        python38.zip/alabaster'
    astroid :
        ImportError: cannot import name 'context' from 'astroid'
        (<path>/Resources/lib/python38.zip/astroid/__init__.pyc)
    blib2to3 :
        File "<frozen zipimport>", line 177, in get_data
        KeyError: 'blib2to3/Users/rclary/Library/Caches/black/20.8b1/
        Grammar3.8.6.final.0.pickle'
    jedi :
        jedi.api.environment.InvalidPythonEnvironment: Could not get version
        information for '<path>/Contents/MacOS/python': InternalError("The
        subprocess <path>/Contents/MacOS/python has crashed (EOFError('Ran out
        of input'), stderr=).")
    jinja2 :
        No module named 'jinja2.ext'
    keyring :
        ModuleNotFoundError: No module named 'keyring.backends.<mod>'
    pandas :
        From Variable explorer: KeyError('pandas._libs.interval')
    parso :
        jedi.api.environment.InvalidPythonEnvironment: Could not get version
        information for '/Users/rclary/opt/miniconda3/envs/c2w_37/bin/python':
        InternalError("The subprocess /Users/rclary/opt/miniconda3/envs/c2w_37/
        bin/python has crashed (EOFError('Ran out of input'), stderr=).")
    PIL :
        Library not loaded: @loader_path/.dylibs/libjpeg.9.dylib
        Note: only applicable to not-Lite build
    pygments :
        ModuleNotFoundError: No module named 'pygments.formatters.latex'
    pyls :
        <path>/Contents/MacOS/python: No module named pyls
        Note: still occurs in alias mode
    pyls_black :
        Mandatory: pyls_black >=0.4.6 : None (NOK)
    pyls_spyder :
        Mandatory: pyls_spyder >=0.1.1 : None (NOK)
    qtawesome :
        NotADirectoryError: [Errno 20] Not a directory: '<path>/Resourses/lib/
        python38.zip/qtawesome/fonts/fontawesome4.7-webfont.ttf'
    setuptools :
        Mandatory: setuptools >=39.0.0 : None (NOK)
    sphinx :
        No module named 'sphinx.builders.changes'
    spyder :
        NotADirectoryError: [Errno 20] Not a directory: '<path>/Resources/lib/
        python38.zip/spyder/app/mac_stylesheet.qss'
    textdistance :
        NotADirectoryError: [Errno 20] Not a directory: '<path>/Resources/lib/
        python39.zip/textdistance/libraries.json'
    """
    import shutil
    import pkg_resources

    from spyder import __version__ as SPYVER
    from spyder.config.utils import EDIT_FILETYPES, _get_extensions
    from spyder.config.base import MAC_APP_NAME

    build_type = 'lite' if make_lite else 'full'
    logger.info('Creating %s app bundle...', build_type)

    PACKAGES = [
        'alabaster',
        'astroid',
        'blib2to3',
        'jedi',
        'jinja2',
        'keyring',
        'parso',
        'pygments',
        'pyls',
        'pyls_black',
        'pyls_spyder',
        'qtawesome',
        'setuptools',
        'sphinx',
        'spyder',
        'textdistance',
    ]

    EXCLUDE_EGG = ['py2app']

    if make_lite:
        INCLUDES = []
        EXCLUDES = [
            'numpy', 'scipy', 'pandas', 'matplotlib', 'cython', 'sympy', 'PIL'
        ]
        EXCLUDE_EGG.append('pillow')
    else:
        INCLUDES = [
            'numpy', 'scipy', 'pandas', 'matplotlib', 'cython', 'sympy'
        ]
        EXCLUDES = []
        PACKAGES.extend(['pandas', 'PIL'])

    EXCLUDE_EGG.extend(EXCLUDES)
    EDIT_EXT = [ext[1:] for ext in _get_extensions(EDIT_FILETYPES)]

    FRAMEWORKS = [
        '/usr/local/lib/libspatialindex.dylib',
        '/usr/local/lib/libspatialindex_c.dylib'
    ]  # for rtree

    OPTIONS = {
        'optimize': 0,
        'packages': PACKAGES,
        'includes': INCLUDES,
        'excludes': EXCLUDES,
        'iconfile': ICONFILE,
        'dist_dir': dist_dir,
        'frameworks': FRAMEWORKS,
        'plist': {
            'CFBundleDocumentTypes': [{
                'CFBundleTypeExtensions': EDIT_EXT,
                'CFBundleTypeName': 'Text File',
                'CFBundleTypeRole': 'Editor'
            }],
            'CFBundleIdentifier':
            'org.spyder-ide',
            'CFBundleShortVersionString':
            SPYVER
        }
    }

    # Copy main application script
    app_script_name = MAC_APP_NAME.replace('.app', '.py')
    app_script_path = os.path.join(SPYREPO, 'scripts', app_script_name)
    shutil.copy2(os.path.join(SPYREPO, 'scripts', 'spyder'), app_script_path)

    try:
        os.symlink(os.path.join(SPYREPO, 'spyder'), SPYLINK)
        setup(app=[app_script_path], options={'py2app': OPTIONS})
    finally:
        os.remove(app_script_path)
        os.remove(SPYLINK)

    # Copy egg info from site-packages: fixes several pkg_resources issues
    dest_dir = os.path.join(dist_dir, MAC_APP_NAME, 'Contents', 'Resources',
                            'lib', f'python{PYVER[0]}.{PYVER[1]}')
    for dist in pkg_resources.working_set:
        if (dist.egg_info is None or dist.key.startswith('pyobjc')
                or dist.key in EXCLUDE_EGG):
            logger.info(f'Skipping egg {dist.key}')
            continue
        egg = os.path.basename(dist.egg_info)
        dest = os.path.join(dest_dir, egg)
        shutil.copytree(dist.egg_info, dest)
        logger.info(f'Copied {egg}')

    logger.info('App bundle complete.')

    return
Пример #5
0
APP = [APP_MAIN_SCRIPT]
DEPS = ['pylint', 'logilab', 'astroid', 'pycodestyle', 'setuptools']
EXCLUDES = DEPS + ['mercurial']
PACKAGES = ['spyder', 'spyder_breakpoints', 'spyder_io_dcm', 'spyder_io_hdf5',
            'spyder_profiler', 'spyder_pylint', 'sphinx', 'jinja2', 'docutils',
            'alabaster', 'babel', 'snowballstemmer', 'sphinx_rtd_theme',
            'IPython', 'ipykernel', 'ipython_genutils', 'jupyter_client',
            'jupyter_core', 'traitlets', 'qtconsole', 'pexpect', 'jedi',
            'jsonschema', 'nbconvert', 'nbformat', 'qtpy', 'qtawesome',
            'zmq', 'pygments', 'rope', 'distutils', 'PIL', 'PyQt5',
            'sklearn', 'skimage', 'pandas', 'sympy', 'pyflakes', 'psutil',
            'nose', 'patsy','statsmodels', 'seaborn', 'networkx']

INCLUDES = get_stdlib_modules()
EDIT_EXT = [ext[1:] for ext in _get_extensions(EDIT_FILETYPES)]

OPTIONS = {
    'argv_emulation': True,
    'compressed' : False,
    'optimize': 0,
    'packages': PACKAGES,
    'includes': INCLUDES,
    'excludes': EXCLUDES,
    'iconfile': 'img_src/spyder.icns',
    'plist': {'CFBundleDocumentTypes': [{'CFBundleTypeExtensions': EDIT_EXT,
                                         'CFBundleTypeName': 'Text File',
                                         'CFBundleTypeRole': 'Editor'}],
              'CFBundleIdentifier': 'org.spyder-ide',
              'CFBundleShortVersionString': spy_version}
}
Пример #6
0
def make_app_bundle(dist_dir, make_lite=False):
    """
    Make macOS application bundle.

    Parameters
    ----------
    dist_dir : str
        Directory in which to put the application bundle.
    make_lite : bool, optional
        Whether to create the application bundle with minimal packages.
        The default is False.

    NOTES
    -----
    py2app includes all packages in Spyder.app/Contents/Resources/lib/
    python<ver>.zip, but some packages have issues when placed there.
    The following packages are included in py2app's PACKAGES option so that
    they will be placed in Spyder.app/Contents/Resources/lib/python<ver>
    instead.

    alabaster :
        Error message: [Errno 20] Not a directory: '<path>/Resources/lib/
        python38.zip/alabaster'
    astroid :
        ImportError: cannot import name 'context' from 'astroid'
        (<path>/Resources/lib/python38.zip/astroid/__init__.pyc)
    blib2to3 :
        File "<frozen zipimport>", line 177, in get_data
        KeyError: 'blib2to3/Users/rclary/Library/Caches/black/20.8b1/
        Grammar3.8.6.final.0.pickle'
    docutils :
        [Errno 20] Not a directory: '<path>/Resources/lib/python39.zip/
        docutils/writers/latex2e/docutils.sty'
    IPython :
        [IPKernelApp] WARNING | Could not copy README_STARTUP to startup dir.
        Source file
        <path>/Resources/lib/python38.zip/IPython/core/profile/README_STARTUP
        does not exist
    jedi :
        jedi.api.environment.InvalidPythonEnvironment: Could not get version
        information for '<path>/Contents/MacOS/python': InternalError("The
        subprocess <path>/Contents/MacOS/python has crashed (EOFError('Ran out
        of input'), stderr=).")
    jinja2 :
        No module named 'jinja2.ext'
    keyring :
        ModuleNotFoundError: No module named 'keyring.backends.<mod>'
    pandas :
        From Variable explorer: KeyError('pandas._libs.interval')
    parso :
        jedi.api.environment.InvalidPythonEnvironment: Could not get version
        information for '/Users/rclary/opt/miniconda3/envs/c2w_37/bin/python':
        InternalError("The subprocess /Users/rclary/opt/miniconda3/envs/c2w_37/
        bin/python has crashed (EOFError('Ran out of input'), stderr=).")
    PIL :
        Library not loaded: @loader_path/.dylibs/libjpeg.9.dylib
        Note: only applicable to not-Lite build
    pygments :
        ModuleNotFoundError: No module named 'pygments.formatters.latex'
    pylint :
        <path>/Contents/MacOS/python: No module named pylint.__main__
    pylsp :
        <path>/Contents/MacOS/python: No module named pylsp
        Note: still occurs in alias mode
    pylsp_black :
        Mandatory: python-pyls-black >=1.0.0 : None (NOK)
    pyls_spyder :
        Mandatory: pyls_spyder >=0.1.1 : None (NOK)
    qtawesome :
        NotADirectoryError: [Errno 20] Not a directory: '<path>/Resourses/lib/
        python38.zip/qtawesome/fonts/fontawesome4.7-webfont.ttf'
    setuptools :
        Mandatory: setuptools >=49.6.0 : None (NOK)
    sphinx :
        No module named 'sphinx.builders.changes'
    spyder :
        NotADirectoryError: [Errno 20] Not a directory: '<path>/Resources/lib/
        python38.zip/spyder/app/mac_stylesheet.qss'
    spyder_kernels :
        No module named spyder_kernels.console.__main__
    textdistance :
        NotADirectoryError: [Errno 20] Not a directory: '<path>/Resources/lib/
        python39.zip/textdistance/libraries.json'
    """
    import shutil
    import pkg_resources

    from spyder import __version__ as SPYVER
    from spyder.config.utils import EDIT_FILETYPES, _get_extensions
    from spyder.config.base import MAC_APP_NAME

    # Patch py2app for IPython help()
    py2app_file = pkg_resources.pkgutil.get_loader('py2app').get_filename()
    site_file = os.path.join(os.path.dirname(py2app_file), 'apptemplate',
                             'lib', 'site.py')
    logger.info('Patching %s...', site_file)
    with open(site_file, 'a+') as f:
        f.seek(0)
        content = f.read()
        if 'builtins.help = _sitebuiltins._Helper()' not in content:
            f.write('\nimport builtins'
                    '\nimport _sitebuiltins'
                    '\nbuiltins.help = _sitebuiltins._Helper()\n')

    build_type = 'lite' if make_lite else 'full'
    logger.info('Creating %s app bundle...', build_type)

    PACKAGES = [
        'alabaster',
        'astroid',
        'blib2to3',
        'docutils',
        'IPython',
        'jedi',
        'jinja2',
        'keyring',
        'parso',
        'pygments',
        'pylint',
        'pylsp',
        'pylsp_black',
        'pyls_spyder',
        'qtawesome',
        'setuptools',
        'sphinx',
        'spyder',
        'spyder_kernels',
        'textdistance',
    ]
    INCLUDES = [
        '_sitebuiltins',  # required for IPython help()
        # required for sphinx
        'sphinxcontrib.applehelp',
        'sphinxcontrib.devhelp',
        'sphinxcontrib.htmlhelp',
        'sphinxcontrib.jsmath',
        'sphinxcontrib.qthelp',
        'sphinxcontrib.serializinghtml'
    ]
    EXCLUDES = []
    EXCLUDE_EGG = ['py2app']

    if make_lite:
        EXCLUDES.extend([
            'numpy', 'scipy', 'pandas', 'matplotlib', 'cython', 'sympy', 'PIL'
        ])
        EXCLUDE_EGG.extend(['pillow'])
    else:
        INCLUDES.extend(
            ['numpy', 'scipy', 'pandas', 'matplotlib', 'cython', 'sympy'])
        PACKAGES.extend(['pandas', 'PIL'])

    EXCLUDE_EGG.extend(EXCLUDES)
    EDIT_EXT = [ext[1:] for ext in _get_extensions(EDIT_FILETYPES)]

    # Get rtree dylibs
    rtree_loc = pkg_resources.get_distribution('rtree').module_path
    rtree_dylibs = os.scandir(os.path.join(rtree_loc, 'rtree', 'lib'))
    FRAMEWORKS = [lib.path for lib in rtree_dylibs]

    OPTIONS = {
        'optimize': 0,
        'packages': PACKAGES,
        'includes': INCLUDES,
        'excludes': EXCLUDES,
        'iconfile': ICONFILE,
        'dist_dir': dist_dir,
        'frameworks': FRAMEWORKS,
        'plist': {
            'CFBundleDocumentTypes': [{
                'CFBundleTypeExtensions': EDIT_EXT,
                'CFBundleTypeName': 'Text File',
                'CFBundleTypeRole': 'Editor'
            }],
            'CFBundleIdentifier':
            'org.spyder-ide',
            'CFBundleShortVersionString':
            SPYVER,
            'NSRequiresAquaSystemAppearance':
            False  # Darkmode support
        }
    }

    # Copy main application script
    app_script_name = MAC_APP_NAME.replace('.app', '.py')
    app_script_path = os.path.join(SPYREPO, 'scripts', app_script_name)
    shutil.copy2(os.path.join(SPYREPO, 'scripts', 'spyder'), app_script_path)

    # Build the application
    try:
        os.symlink(os.path.join(SPYREPO, 'spyder'), SPYLINK)
        setup(app=[app_script_path], options={'py2app': OPTIONS})
    finally:
        os.remove(app_script_path)
        os.remove(SPYLINK)

    # Copy egg info from site-packages: fixes several pkg_resources issues
    dest_dir = os.path.join(dist_dir, MAC_APP_NAME, 'Contents', 'Resources',
                            'lib', f'python{PYVER[0]}.{PYVER[1]}')
    pkg_resources.working_set.add_entry(SPYREPO)
    for dist in pkg_resources.working_set:
        if (dist.egg_info is None or dist.key.startswith('pyobjc')
                or dist.key in EXCLUDE_EGG):
            logger.info(f'Skipping egg {dist.key}')
            continue
        egg = os.path.basename(dist.egg_info)
        dest = os.path.join(dest_dir, egg)
        shutil.copytree(dist.egg_info, dest)
        logger.info(f'Copied {egg}')

    logger.info('App bundle complete.')

    return