Exemple #1
0
def get_grasshopper_plugin_path(version):
    version = compas_rhino._check_rhino_version(version)

    if compas.WINDOWS:
        version = version.split('.')[0]  # take the major only
        grasshopper_plugin_path = os.path.join(os.getenv('ProgramFiles'),
                                               'Rhino {}'.format(version),
                                               'Plug-ins', 'Grasshopper')
    elif compas.OSX:
        lib_paths = {
            '6.0': ['/', 'Applications', 'Rhinoceros.app'],
            '7.0': [
                '/',
                'Applications',
                'Rhino 7.app',
            ]
        }

        if version not in lib_paths:
            raise Exception('Unsupported Rhino version')

        grasshopper_plugin_path = os.path.join(*lib_paths.get(version) + [
            'Contents', 'Frameworks', 'RhCore.framework', 'Versions', 'A',
            'Resources', 'ManagedPlugIns', 'GrasshopperPlugin.rhp'
        ])
    else:
        raise Exception('Unsupported platform')
    return grasshopper_plugin_path
Exemple #2
0
def get_version_from_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('-v',
                        '--version',
                        choices=['5.0', '6.0', '7.0'],
                        default='6.0')
    args = parser.parse_args()
    return _check_rhino_version(args.version)
Exemple #3
0
def get_version_from_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('-v',
                        '--version',
                        choices=compas_rhino.SUPPORTED_VERSIONS,
                        default=compas_rhino.DEFAULT_VERSION)
    args = parser.parse_args()
    return _check_rhino_version(args.version)
Exemple #4
0
def uninstall_plugin(plugin, version=None):
    """Uninstall a Rhino Python Command Plugin.

    Parameters
    ----------
    plugin : str
        The name of the plugin.
    version : {'5.0', '6.0', '7.0', '8.0'}, optional
        The version of Rhino for which the plugin should be uninstalled.
        Default is ``'7.0'``.

    Notes
    -----
    The version info is only relevant for Rhino on Windows.

    Examples
    --------
    .. code-block:: bash

        python -m compas_rhino.uninstall_plugin XXX

    """
    version = compas_rhino._check_rhino_version(version)

    python_plugins_path = compas_rhino._get_rhino_pythonplugins_path(version)
    plugin_name = plugin.split('{')[0]

    symlinks = []
    dirs = []

    for name in os.listdir(python_plugins_path):
        path = os.path.join(python_plugins_path, name)

        if os.path.islink(path):
            if name.split('{')[0] == plugin_name:
                symlinks.append(name)

        elif os.path.isdir(path):
            if name.split('{')[0] == plugin_name:
                dirs.append(name)

    print('\nUninstalling PlugIn {} from Rhino PythonPlugIns:'.format(plugin_name))

    if not symlinks and not dirs:
        print('Nothing to uninstall...\n')

    else:
        for name in symlinks:
            print('- {}'.format(name))
            destination = os.path.join(python_plugins_path, name)
            remove_symlink(destination)

        for name in dirs:
            print('- {}'.format(name))
            destination = os.path.join(python_plugins_path, name)
            os.rmdir(destination)

        print('\nPlugIn {} Uninstalled.\n'.format(plugin_name))
Exemple #5
0
def get_grasshopper_managedplugin_path(version):
    version = compas_rhino._check_rhino_version(version)
    managedplugins = compas_rhino._get_rhino_managedplugins_path(version)

    if compas.WINDOWS:
        gh_managedplugin_path = os.path.join(managedplugins, 'Grasshopper')

    elif compas.OSX:
        gh_managedplugin_path = os.path.join(managedplugins, 'GrasshopperPlugin.rhp')

    if not os.path.exists(gh_managedplugin_path):
        raise Exception("The Grasshopper (managed) Plug-in folder does not exist in this location: {}".format(gh_managedplugin_path))

    return gh_managedplugin_path
Exemple #6
0
def install_plugin(plugin, version=None):
    """Install a Rhino Python Command Plugin.

    Parameters
    ----------
    plugin : str
        The path to the plugin folder.
    version : {'5.0', '6.0', '7.0', '8.0'}, optional
        The version of Rhino for which the plugin should be installed.
        Default is ``'6.0'``.

    Notes
    -----
    The version info is only relevant for Rhino on Windows.

    The function creates an *editable install*, which means that the plugin
    folder is *symlinked* into the correct location so Rhino can find and load it.
    The contents of the source folder can still be edited and next time you start
    Rhino those canges will be reflected in the loaded plugin.

    Examples
    --------
    Assuming the plugin folder is at the following location on your computer

    .. code-block:: none

        ~/Code/compas_xxx/ui/Rhino/XXX

    and contains at least a "dev" folder with a ``__plugin__.py`` file with

    * the GUID of the tool: ``id={...}``, and
    * the name of the tool: ``title="..."``,

    it can be installed with the following command,

    .. code-block:: bash

        cd ~/Code/compas_xxx
        python -m compas_rhino.install_plugin ui/Rhino/XXX

    or the following, if the plugin should be installed for Rhino 7.

    .. code-block:: bash

        cd ~/Code/compas_xxx
        python -m compas_rhino.install_plugin -v 7.0 ui/Rhino/XXX

    """
    if not os.path.isdir(plugin):
        raise Exception('Cannot find the plugin: {}'.format(plugin))

    version = compas_rhino._check_rhino_version(version)

    plugin_dir = os.path.abspath(plugin)

    # Clean up the plugin directory
    # by removing all broken symlinks
    # because ... they're broken!

    symlinks_to_remove = []

    for name in os.listdir(plugin_dir):
        path = os.path.join(plugin_dir, name)
        if os.path.islink(path):
            if not os.path.exists(path):
                symlinks_to_remove.append(dict(name=name, link=path))

    symlinks_removed = []
    symlinks_unremoved = []

    if symlinks_to_remove:
        symlinks = [link['link'] for link in symlinks_to_remove]
        removal_results = remove_symlinks(symlinks)
        for uninstall_data, success in zip(symlinks_to_remove, removal_results):
            if success:
                symlinks_removed.append(uninstall_data['name'])
            else:
                symlinks_unremoved.append(uninstall_data['name'])

    if symlinks_removed:
        print('\nThe following package symlinks are broken and were removed:\n')
        for name in symlinks_removed:
            print('   {}'.format(name.ljust(20)))

    if symlinks_unremoved:
        print('\nThe following package symlinks are broken but could not be removed:\n')
        for name in symlinks_unremoved:
            print('   {}'.format(name.ljust(20)))

    # -----------------------------
    # proceed with the installation
    # -----------------------------

    plugin_path, plugin_name = os.path.split(plugin_dir)
    plugin_path = plugin_path or os.getcwd()

    plugin_dev = os.path.join(plugin_dir, 'dev')

    if not os.path.isdir(plugin_dev):
        raise Exception('The plugin does not contain a dev folder.')

    plugin_info = os.path.join(plugin_dev, '__plugin__.py')

    if not os.path.isfile(plugin_info):
        raise Exception('The plugin does not contain plugin info.')

    __plugin__ = imp.load_source('__plugin__', plugin_info)

    if not __plugin__.id:
        raise Exception('Plugin id is not set.')

    if not __plugin__.title:
        raise Exception('Plugin title is not set.')

    plugin_fullname = "{}{}".format(__plugin__.title, __plugin__.id)

    python_plugins_path = compas_rhino._get_rhino_pythonplugins_path(version)

    if not os.path.exists(python_plugins_path):
        os.mkdir(python_plugins_path)

    source = plugin_dir
    destination = os.path.join(python_plugins_path, plugin_fullname)

    print('\nInstalling PlugIn {} to Rhino PythonPlugIns.'.format(plugin_name))

    remove_symlinks([destination])
    create_symlinks([(source, destination)])

    print('\nPlugIn {} Installed.'.format(plugin_name))
    print('\nRestart Rhino and open the Python editor at least once to make it available.')
Exemple #7
0
def uninstall(version=None, packages=None):
    """Uninstall COMPAS from Rhino.

    Parameters
    ----------
    version : {'5.0', '6.0', '7.0', '8.0'}, optional
        The version number of Rhino.
        Default is ``'7.0'``.
    packages : list of str, optional
        List of packages to uninstall.
        Default is to uninstall all packages installed by the COMPAS installer.

    Examples
    --------
    .. code-block:: python

        import compas_rhino
        compas_rhino.uninstall()

    .. code-block:: bash

        python -m compas_rhino.uninstall

    """
    version = compas_rhino._check_rhino_version(version)

    # We install COMPAS packages in the scripts folder
    # instead of directly as IPy module.
    scripts_path = compas_rhino._get_rhino_scripts_path(version)

    # This is for old installs
    ipylib_path = compas_rhino._get_rhino_ironpython_lib_path(version)

    # Filter the provided list of packages
    # If no packages are provided
    # this first collects all installable packages from the environment.
    packages = _filter_installed_packages(version, packages)

    # Also remove all broken symlinks
    # because ... they're broken!
    for name in os.listdir(scripts_path):
        path = os.path.join(scripts_path, name)
        if os.path.islink(path):
            if not os.path.exists(path):
                if name not in packages:
                    packages.append(name)

    # Collect paths for removal based on package names
    symlinks_to_uninstall = []

    for package in packages:
        symlink_path = os.path.join(scripts_path, package)
        symlinks_to_uninstall.append(dict(name=package, link=symlink_path))

        # Handle legacy install location
        # This does not always work,
        # and especially not in cases where it is in any case not necessary :)
        if ipylib_path:
            legacy_path = os.path.join(ipylib_path, package)
            if os.path.exists(legacy_path):
                symlinks_to_uninstall.append(
                    dict(name=package, link=legacy_path))

    # There is nothing to uninstall
    if not symlinks_to_uninstall:
        print(
            '\nNo packages to uninstall from Rhino {0} scripts folder: \n{1}.'.
            format(version, scripts_path))
        return

    # -------------------------
    # Start uninstalling
    # -------------------------

    uninstalled_packages = []
    results = []
    exit_code = 0

    symlinks = [link['link'] for link in symlinks_to_uninstall]
    uninstall_results = compas._os.remove_symlinks(symlinks)

    for uninstall_data, success in zip(symlinks_to_uninstall,
                                       uninstall_results):
        if success:
            uninstalled_packages.append(uninstall_data['name'])
            result = 'OK'
        else:
            result = 'ERROR: Cannot remove symlink, try to run as administrator.'

        results.append((uninstall_data['name'], result))

    if not all(uninstall_results):
        exit_code = -1

    if exit_code == -1:
        results.append((
            'compas_bootstrapper',
            'WARNING: One or more packages failed, will not uninstall bootstrapper.'
        ))

    else:
        if compas_rhino._try_remove_bootstrapper(scripts_path):
            results.append(('compas_bootstrapper', 'OK'))
        else:
            results.append((
                'compas_bootstrapper',
                'ERROR: Cannot remove compas_bootstrapper, try to run as administrator.'
            ))

        # Handle legacy bootstrapper
        # Again, only if possible...
        if ipylib_path:
            if not compas_rhino._try_remove_bootstrapper(ipylib_path):
                results.append((
                    'compas_bootstrapper',
                    'ERROR: Cannot remove legacy compas_bootstrapper, try to run as administrator.'
                ))

    # -------------------------
    # Output results
    # -------------------------

    print('Uninstalling COMPAS packages from Rhino {0} scripts folder: \n{1}'.
          format(version, scripts_path))
    print(
        '\nThe following packages have been detected and will be uninstalled:\n'
    )

    for package, status in results:
        print('   {} {}'.format(package.ljust(20), status))

        if status != 'OK':
            exit_code = -1

    if exit_code == 0 and uninstalled_packages:
        print('\nRunning post-uninstallation steps...\n')

        if not _run_post_execution_steps(
                after_rhino_uninstall(uninstalled_packages)):
            exit_code = -1

    print('\nUninstall completed.')

    if exit_code != 0:
        sys.exit(exit_code)
Exemple #8
0
def install(version=None, packages=None, clean=False):
    """Install COMPAS for Rhino.

    Parameters
    ----------
    version : {'5.0', '6.0', '7.0', '8.0'}, optional
        The version number of Rhino.
        Default is ``'7.0'``.
    packages : list of str, optional
        List of packages to install or None to use default package list.
        Default is the result of ``installable_rhino_packages``,
        which collects all installable packages in the current environment.
    clean : bool, optional
        If ``True``, this will clean up the entire scripts folder and remove
        also existing symlinks that are not importable in the current environment.

    Examples
    --------
    .. code-block:: python

        import compas_rhino.install
        compas_rhino.install.install()

    .. code-block:: bash

        python -m compas_rhino.install

    """
    version = compas_rhino._check_rhino_version(version)

    # We install COMPAS packages in the scripts folder
    # instead of directly as IPy module.
    scripts_path = compas_rhino._get_rhino_scripts_path(version)

    # This is for old installs
    ipylib_path = compas_rhino._get_rhino_ironpython_lib_path(version)

    # Filter the provided list of packages
    # If no packages are provided
    # this first collects all installable packages from the environment.
    packages = _filter_installable_packages(version, packages)

    results = []
    symlinks_to_install = []
    symlinks_to_uninstall = []
    exit_code = 0

    # check all installable packages
    # add the packages that can't be imported from the current env to the list of symlinks to uninstall
    # and remove the package name from the list of installable packages
    # make a copy of the list to avoid problems with removing items
    # note: perhaps this should already happen in the filter function...
    for name in packages[:]:
        try:
            importlib.import_module(name)
        except ImportError:
            path = os.path.join(scripts_path, name)
            symlinks_to_uninstall.append(dict(name=name, link=path))
            packages.remove(name)

    # Also remove all broken symlinks from the scripts folder
    # because ... they're broken!
    # If it is an actual folder or a file, leave it alone
    # because probably someone put it there on purpose.
    for name in os.listdir(scripts_path):
        path = os.path.join(scripts_path, name)
        if os.path.islink(path):
            if not os.path.exists(path):
                symlinks_to_uninstall.append(dict(name=name, link=path))
                try:
                    importlib.import_module(name)
                except ImportError:
                    pass
                else:
                    if name not in packages:
                        packages.append(name)

    # If the scripts folder is supposed to be cleaned
    # also remove all existing symlinks that cannot be imported
    # and reinstall symlinks that can be imported
    if clean:
        for name in os.listdir(scripts_path):
            path = os.path.join(scripts_path, name)
            if os.path.islink(path):
                if os.path.exists(path):
                    try:
                        importlib.import_module(name)
                    except ImportError:
                        path = os.path.join(scripts_path, name)
                        symlinks_to_uninstall.append(dict(name=name,
                                                          link=path))
                    else:
                        if name not in packages:
                            packages.append(name)

    # add all of the packages in the list of installable packages
    # to the list of symlinks to uninstall
    # and to the list of symlinks to install
    for package in packages:
        symlink_path = os.path.join(scripts_path, package)
        symlinks_to_uninstall.append(dict(name=package, link=symlink_path))

        package_path = compas_rhino._get_package_path(
            importlib.import_module(package))
        symlinks_to_install.append(
            dict(name=package, source_path=package_path, link=symlink_path))

        # Handle legacy install location
        # This does not always work,
        # and especially not in cases where it is not necessary :)
        if ipylib_path:
            legacy_path = os.path.join(ipylib_path, package)
            if os.path.exists(legacy_path):
                symlinks_to_uninstall.append(
                    dict(name=package, link=legacy_path))

    # -------------------------
    # Uninstall first
    # -------------------------

    symlinks = [link['link'] for link in symlinks_to_uninstall]
    uninstall_results = compas._os.remove_symlinks(symlinks)

    # Let the user know if some symlinks could not be removed.
    for uninstall_data, success in zip(symlinks_to_uninstall,
                                       uninstall_results):
        if not success:
            results.append(
                (uninstall_data['name'],
                 'ERROR: Cannot remove symlink, try to run as administrator.'))

    # Handle legacy bootstrapper
    # Again, only if possible...
    if ipylib_path:
        if not compas_rhino._try_remove_bootstrapper(ipylib_path):
            results.append((
                'compas_bootstrapper',
                'ERROR: Cannot remove legacy compas_bootstrapper, try to run as administrator.'
            ))

    # -------------------------
    # Ready to start installing
    # -------------------------

    # create new symlinks and register the results
    symlinks = [(link['source_path'], link['link'])
                for link in symlinks_to_install]
    install_results = compas._os.create_symlinks(symlinks)

    # set the exit code based on the installation results
    if not all(install_results):
        exit_code = -1

    # make a list of installed packages
    # based on the installation results
    # and update the general results list
    installed_packages = []
    for install_data, success in zip(symlinks_to_install, install_results):
        if success:
            installed_packages.append(install_data['name'])
            result = 'OK'
        else:
            result = 'ERROR: Cannot create symlink, try to run as administrator.'
        results.append((install_data['name'], result))

    # finalize the general results list with info about the bootstrapper
    if exit_code == -1:
        results.append((
            'compas_bootstrapper',
            'WARNING: One or more packages failed, will not install bootstrapper, try uninstalling first'
        ))
    else:
        try:
            _update_bootstrapper(scripts_path, packages)
            results.append(('compas_bootstrapper', 'OK'))
        except:  # noqa: E722
            results.append((
                'compas_bootstrapper',
                'ERROR: Could not create compas_bootstrapper to auto-determine Python environment'
            ))

    # output the outcome of the installation process
    # perhaps we should more info here
    print('Installing COMPAS packages to Rhino {0} scripts folder:'.format(
        version))
    print('{}\n'.format(scripts_path))

    for package, status in results:
        print('   {} {}'.format(package.ljust(20), status))
        if status != 'OK':
            exit_code = -1

    if exit_code == 0 and len(installed_packages):
        print('\nRunning post-installation steps...\n')
        if not _run_post_execution_steps(
                after_rhino_install(installed_packages)):
            exit_code = -1

    print('\nInstall completed.')
    if exit_code != 0:
        sys.exit(exit_code)

    global INSTALLED_VERSION
    INSTALLED_VERSION = version