예제 #1
0
    def handle(self, *args, **options):
        """
        Symbolically link the static directories of each app into the static/public directory specified by the
        STATIC_ROOT parameter of the settings.py. Do this prior to running Django's collectstatic method.
        """
        if not hasattr(settings, 'TETHYS_WORKSPACES_ROOT') or (hasattr(settings, 'TETHYS_WORKSPACES_ROOT')
                                                               and not settings.TETHYS_WORKSPACES_ROOT):
            print('WARNING: Cannot find the TETHYS_WORKSPACES_ROOT setting in the settings.py file. '
                  'Please provide the path to the static directory using the TETHYS_WORKSPACES_ROOT '
                  'setting and try again.')
            exit(1)
        # Get optional force arg
        force = options['force']

        # Read settings
        workspaces_root = settings.TETHYS_WORKSPACES_ROOT

        # Get a list of installed apps
        installed_apps = get_installed_tethys_apps()

        # Provide feedback to user
        print('INFO: Moving workspace directories of apps to "{0}" and linking back.'.format(workspaces_root))

        for app, path in installed_apps.items():
            # Check for both variants of the static directory (public and static)
            app_ws_path = os.path.join(path, 'workspaces')
            tethys_ws_root_path = os.path.join(workspaces_root, app)

            # Only perform if workspaces_path is a directory
            if not os.path.isdir(app_ws_path):
                print('WARNING: The workspace_path for app "{}" is not a directory. Skipping...'.format(app))
                continue

            if not os.path.islink(app_ws_path):
                if not os.path.exists(tethys_ws_root_path):
                    # Move the directory to workspace root path
                    shutil.move(app_ws_path, tethys_ws_root_path)
                else:
                    if force:
                        # Clear out old symbolic links/directories in workspace root if necessary
                        try:
                            # Remove link
                            os.remove(tethys_ws_root_path)
                        except OSError:
                            shutil.rmtree(tethys_ws_root_path, ignore_errors=True)

                        # Move the directory to workspace root path
                        shutil.move(app_ws_path, tethys_ws_root_path)
                    else:
                        print('WARNING: Workspace directory for app "{}" already exists in the TETHYS_WORKSPACES_ROOT '
                              'directory. A symbolic link is being created to the existing directory. '
                              'To force overwrite '
                              'the existing directory, re-run the command with the "-f" argument.'.format(app))
                        shutil.rmtree(app_ws_path, ignore_errors=True)

                # Create appropriate symbolic link
                if os.path.isdir(tethys_ws_root_path):
                    os.symlink(tethys_ws_root_path, app_ws_path)
                    print('INFO: Successfully linked "workspaces" directory to TETHYS_WORKSPACES_ROOT for app '
                          '"{0}".'.format(app))
예제 #2
0
 def test_get_installed_tethys_apps_mock(self, mock_dir, mock_listdir, mock_isdir):
     # Get list of apps installed in the mock directory
     mock_dir.return_value = '/foo/bar'
     mock_listdir.return_value = ['.gitignore', 'foo_app', '__init__.py', '__init__.pyc']
     mock_isdir.side_effect = [False, True, False, False]
     result = helpers.get_installed_tethys_apps()
     self.assertTrue('foo_app' in result)
예제 #3
0
    def test_get_installed_tethys_apps_exception(self, mock_harvester):
        mock_harvester().app_modules = {
            'foo_invalid_foo': 'tethys_app.foo_invalid_foo'
        }

        result = helpers.get_installed_tethys_apps()
        self.assertEqual({}, result)
예제 #4
0
파일: __init__.py 프로젝트: zhiyuli/tethys
def list_apps_command(args):
    """
    List installed apps.
    """
    installed_apps = get_installed_tethys_apps()

    for app in installed_apps:
        print(app)
예제 #5
0
    def handle(self, *args, **options):
        """
        Remove the app from disk and in the database
        """
        PREFIX = 'tethysapp'
        app_name = options['app_name'][0]
        installed_apps = get_installed_tethys_apps()

        if PREFIX in app_name:
            prefix_length = len(PREFIX) + 1
            app_name = app_name[prefix_length:]

        if app_name not in installed_apps:
            warnings.warn('WARNING: App with name "{0}" cannot be uninstalled, because it is not installed.'.format(app_name))
            exit(0)

        app_with_prefix = '{0}-{1}'.format(PREFIX, app_name)

        # Confirm
        valid_inputs = ('y', 'n', 'yes', 'no')
        no_inputs = ('n', 'no')

        overwrite_input = raw_input('Are you sure you want to uninstall "{0}"? (y/n): '.format(app_with_prefix)).lower()

        while overwrite_input not in valid_inputs:
            overwrite_input = raw_input('Invalid option. Are you sure you want to '
                                        'uninstall "{0}"? (y/n): '.format(app_with_prefix)).lower()

        if overwrite_input in no_inputs:
            self.stdout.write('Uninstall cancelled by user.')
            exit(0)

        # Remove app from database
        from tethys_apps.models import TethysApp
        try:
            db_app = TethysApp.objects.get(package=app_name)
            db_app.delete()
        except TethysApp.DoesNotExist:
            warnings.warn('WARNING: The app was not found in the database.')

        try:
            # Remove directory
            shutil.rmtree(installed_apps[app_name])
        except OSError:
            # Remove symbolic link
            os.remove(installed_apps[app_name])

        # Uninstall using pip
        process = ['pip', 'uninstall', '-y', '{0}-{1}'.format(PREFIX, app_name)]

        try:
            subprocess.Popen(process, stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
        except KeyboardInterrupt:
            pass

        self.stdout.write('App "{0}" successfully uninstalled.'.format(app_with_prefix))
예제 #6
0
def uninstall_command(args):
    """
    Uninstall an app command.
    """
    app_name = args.app
    installed_apps = get_installed_tethys_apps()

    if PREFIX in app_name:
        prefix_length = len(PREFIX) + 1
        app_name = app_name[prefix_length:]

    if app_name not in installed_apps:
        print(
            'WARNING: App with name "{0}" cannot be uninstalled, because it is not installed.'
            .format(app_name))
        exit(0)

    app_with_prefix = '{0}-{1}'.format(PREFIX, app_name)

    # Confirm
    valid_inputs = ('y', 'n', 'yes', 'no')
    no_inputs = ('n', 'no')

    overwrite_input = raw_input(
        'Are you sure you want to uninstall "{0}"? (y/n): '.format(
            app_with_prefix)).lower()

    while overwrite_input not in valid_inputs:
        overwrite_input = raw_input(
            'Invalid option. Are you sure you want to '
            'uninstall "{0}"? (y/n): '.format(app_with_prefix)).lower()

    if overwrite_input in no_inputs:
        print('Uninstall cancelled by user.')
        exit(0)

    try:
        # Remove directory
        shutil.rmtree(installed_apps[app_name])
    except OSError:
        # Remove symbolic link
        os.remove(installed_apps[app_name])

    # Uninstall using pip
    process = ['pip', 'uninstall', '-y', '{0}-{1}'.format(PREFIX, app_name)]

    try:
        subprocess.Popen(process,
                         stderr=subprocess.STDOUT,
                         stdout=subprocess.PIPE).communicate()[0]
    except KeyboardInterrupt:
        pass

    print('App "{0}" successfully uninstalled.'.format(app_with_prefix))
예제 #7
0
    def handle(self, *args, **options):
        """
        Symbolically link the static directories of each app into the static/public directory specified by the STATIC_ROOT
        parameter of the settings.py. Do this prior to running Django's collectstatic method.
        """
        if not hasattr(settings, 'TETHYS_WORKSPACES_ROOT') or (
                hasattr(settings, 'TETHYS_WORKSPACES_ROOT')
                and not settings.TETHYS_WORKSPACES_ROOT):
            print(
                'WARNING: Cannot find the TETHYS_WORKSPACES_ROOT setting in the settings.py file. '
                'Please provide the path to the static directory using the TETHYS_WORKSPACES_ROOT setting and try again.'
            )
            exit(1)

        # Read settings
        workspaces_root = settings.TETHYS_WORKSPACES_ROOT

        # Get a list of installed apps
        installed_apps = get_installed_tethys_apps()

        # Provide feedback to user
        print(
            'INFO: Moving workspace directories of apps to "{0}" and linking back.'
            .format(workspaces_root))

        for app, path in installed_apps.items():
            # Check for both variants of the static directory (public and static)
            workspaces_path = os.path.join(path, 'workspaces')
            workspaces_root_path = os.path.join(workspaces_root, app)

            # Only perform if workspaces_path is a directory
            if os.path.isdir(
                    workspaces_path) and not os.path.islink(workspaces_path):
                # Clear out old symbolic links/directories in workspace root if necessary
                try:
                    # Remove link
                    os.remove(workspaces_root_path)
                except OSError:
                    try:
                        # Remove directory
                        shutil.rmtree(workspaces_root_path)
                    except OSError:
                        # No file
                        pass

                # Move the directory to workspace root path
                shutil.move(workspaces_path, workspaces_root_path)

                # Create appropriate symbolic link
                if os.path.isdir(workspaces_root_path):
                    os.symlink(workspaces_root_path, workspaces_path)
                    print(
                        'INFO: Successfully linked "workspaces" directory to TETHYS_WORKSPACES_ROOT for app "{0}".'
                        .format(app))
예제 #8
0
    def handle(self, *args, **options):
        """
        Symbolically link the static directories of each app into the static/public directory specified by the
        STATIC_ROOT parameter of the settings.py. Do this prior to running Django's collectstatic method.
        """  # noqa: E501
        if not settings.STATIC_ROOT:
            print(
                'WARNING: Cannot find the STATIC_ROOT setting. Please provide the path to the static directory using '
                'the STATIC_ROOT setting in the portal_config.yml file and try again.'
            )
            exit(1)

        # Read settings
        static_root = settings.STATIC_ROOT

        # Get a list of installed apps
        installed_apps_and_extensions = get_installed_tethys_apps()
        installed_apps_and_extensions.update(get_installed_tethys_extensions())

        # Provide feedback to user
        print(
            'INFO: Linking static and public directories of apps and extensions to "{0}".'
            .format(static_root))

        for item, path in installed_apps_and_extensions.items():
            # Check for both variants of the static directory (public and static)
            public_path = os.path.join(path, 'public')
            static_path = os.path.join(path, 'static')
            static_root_path = os.path.join(static_root, item)

            # Clear out old symbolic links/directories if necessary
            try:
                # Remove link
                os.remove(static_root_path)
            except OSError:
                try:
                    # Remove directory
                    shutil.rmtree(static_root_path)
                except OSError:
                    # No file
                    pass

            # Create appropriate symbolic link
            if os.path.isdir(public_path):
                os.symlink(public_path, static_root_path)
                print(
                    'INFO: Successfully linked public directory to STATIC_ROOT for app "{0}".'
                    .format(item))

            elif os.path.isdir(static_path):
                os.symlink(static_path, static_root_path)
                print(
                    'INFO: Successfully linked static directory to STATIC_ROOT for app "{0}".'
                    .format(item))
예제 #9
0
def list_command(args):
    """
    List installed apps.
    """
    installed_apps = get_installed_tethys_apps()
    installed_extensions = get_installed_tethys_extensions()

    if installed_apps:
        print('Apps:')
        for item in installed_apps:
            print('  {}'.format(item))

    if installed_extensions:
        print('Extensions:')
        for item in installed_extensions:
            print('  {}'.format(item))
예제 #10
0
def uninstall_command(args):
    """
    Uninstall an app command.
    """
    app_name = args.app
    installed_apps = get_installed_tethys_apps()

    if PREFIX in app_name:
        prefix_length = len(PREFIX) + 1
        app_name = app_name[prefix_length:]

    if app_name not in installed_apps:
        print('WARNING: App with name "{0}" cannot be uninstalled, because it is not installed.'.format(app_name))
        exit(0)

    app_with_prefix = '{0}-{1}'.format(PREFIX, app_name)

    # Confirm
    valid_inputs = ('y', 'n', 'yes', 'no')
    no_inputs = ('n', 'no')

    overwrite_input = raw_input('Are you sure you want to uninstall "{0}"? (y/n): '.format(app_with_prefix)).lower()

    while overwrite_input not in valid_inputs:
        overwrite_input = raw_input('Invalid option. Are you sure you want to '
                                    'uninstall "{0}"? (y/n): '.format(app_with_prefix)).lower()

    if overwrite_input in no_inputs:
        print('Uninstall cancelled by user.')
        exit(0)

    try:
        # Remove directory
        shutil.rmtree(installed_apps[app_name])
    except OSError:
        # Remove symbolic link
        os.remove(installed_apps[app_name])

    # Uninstall using pip
    process = ['pip', 'uninstall', '-y', '{0}-{1}'.format(PREFIX, app_name)]

    try:
        subprocess.Popen(process, stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
    except KeyboardInterrupt:
        pass

    print('App "{0}" successfully uninstalled.'.format(app_with_prefix))
예제 #11
0
    def handle(self, *args, **options):
        """
        Symbolically link the static directories of each app into the static/public directory specified by the STATIC_ROOT
        parameter of the settings.py. Do this prior to running Django's collectstatic method.
        """  # noqa: E501
        if not settings.STATIC_ROOT:
            print('WARNING: Cannot find the STATIC_ROOT setting in the settings.py file. '
                  'Please provide the path to the static directory using the STATIC_ROOT setting and try again.')
            exit(1)

        # Read settings
        static_root = settings.STATIC_ROOT

        # Get a list of installed apps
        installed_apps_and_extensions = get_installed_tethys_apps()
        installed_apps_and_extensions.update(get_installed_tethys_extensions())

        # Provide feedback to user
        print('INFO: Linking static and public directories of apps and extensions to "{0}".'.format(static_root))

        for item, path in installed_apps_and_extensions.items():
            # Check for both variants of the static directory (public and static)
            public_path = os.path.join(path, 'public')
            static_path = os.path.join(path, 'static')
            static_root_path = os.path.join(static_root, item)

            # Clear out old symbolic links/directories if necessary
            try:
                # Remove link
                os.remove(static_root_path)
            except OSError:
                try:
                    # Remove directory
                    shutil.rmtree(static_root_path)
                except OSError:
                    # No file
                    pass

            # Create appropriate symbolic link
            if os.path.isdir(public_path):
                os.symlink(public_path, static_root_path)
                print('INFO: Successfully linked public directory to STATIC_ROOT for app "{0}".'.format(item))

            elif os.path.isdir(static_path):
                os.symlink(static_path, static_root_path)
                print('INFO: Successfully linked static directory to STATIC_ROOT for app "{0}".'.format(item))
예제 #12
0
    def handle(self, *args, **options):
        """
        Symbolically link the static directories of each app into the static/public directory specified by the STATIC_ROOT
        parameter of the settings.py. Do this prior to running Django's collectstatic method.
        """
        if not hasattr(settings, 'TETHYS_WORKSPACES_ROOT') or (hasattr(settings, 'TETHYS_WORKSPACES_ROOT') and not settings.TETHYS_WORKSPACES_ROOT):
            print('WARNING: Cannot find the TETHYS_WORKSPACES_ROOT setting in the settings.py file. '
                  'Please provide the path to the static directory using the TETHYS_WORKSPACES_ROOT setting and try again.')
            exit(1)

        # Read settings
        workspaces_root = settings.TETHYS_WORKSPACES_ROOT

        # Get a list of installed apps
        installed_apps = get_installed_tethys_apps()

        # Provide feedback to user
        print('INFO: Moving workspace directories of apps to "{0}" and linking back.'.format(workspaces_root))

        for app, path in installed_apps.iteritems():
            # Check for both variants of the static directory (public and static)
            workspaces_path = os.path.join(path, 'workspaces')
            workspaces_root_path = os.path.join(workspaces_root, app)

            # Only perform if workspaces_path is a directory
            if os.path.isdir(workspaces_path) and not os.path.islink(workspaces_path):
                # Clear out old symbolic links/directories in workspace root if necessary
                try:
                    # Remove link
                    os.remove(workspaces_root_path)
                except OSError:
                    try:
                        # Remove directory
                        shutil.rmtree(workspaces_root_path)
                    except OSError:
                        # No file
                        pass

                # Move the directory to workspace root path
                shutil.move(workspaces_path, workspaces_root_path)

                # Create appropriate symbolic link
                if os.path.isdir(workspaces_root_path):
                    os.symlink(workspaces_root_path, workspaces_path)
                    print('INFO: Successfully linked "workspaces" directory to TETHYS_WORKSPACES_ROOT for app "{0}".'.format(app))
예제 #13
0
    def handle(self, *args, **options):
        """
        Remove the app from disk and in the database
        """
        from tethys_apps.models import TethysApp, TethysExtension
        app_or_extension = "App" if not options['is_extension'] else 'Extension'
        PREFIX = 'tethysapp' if not options['is_extension'] else 'tethysext'
        item_name = options['app_or_extension'][0]

        # Check for app files installed
        installed_items = get_installed_tethys_extensions() if options['is_extension'] else get_installed_tethys_apps()

        if PREFIX in item_name:
            prefix_length = len(PREFIX) + 1
            item_name = item_name[prefix_length:]

        module_found = True
        if item_name not in installed_items:
            module_found = False

        # Check for app/extension in database
        TethysModel = TethysApp if not options['is_extension'] else TethysExtension
        db_app = None
        db_found = True

        try:
            db_app = TethysModel.objects.get(package=item_name)
        except TethysModel.DoesNotExist:
            db_found = False

        if not module_found and not db_found:
            warnings.warn('WARNING: {0} with name "{1}" cannot be uninstalled, because it is not installed or'
                          ' not an {0}.'.format(app_or_extension, item_name))
            exit(0)

        # Confirm
        item_with_prefix = '{0}-{1}'.format(PREFIX, item_name)

        valid_inputs = ('y', 'n', 'yes', 'no')
        no_inputs = ('n', 'no')

        overwrite_input = input('Are you sure you want to uninstall "{0}"? (y/n): '.format(item_with_prefix)).lower()

        while overwrite_input not in valid_inputs:
            overwrite_input = input('Invalid option. Are you sure you want to '
                                    'uninstall "{0}"? (y/n): '.format(item_with_prefix)).lower()

        if overwrite_input in no_inputs:
            self.stdout.write('Uninstall cancelled by user.')
            exit(0)

        # Remove app from database
        if db_found and db_app:
            db_app.delete()

        if module_found and not options['is_extension']:
            try:
                # Remove directory
                shutil.rmtree(installed_items[item_name])
            except OSError:
                # Remove symbolic link
                os.remove(installed_items[item_name])

        # Uninstall using pip
        process = ['pip', 'uninstall', '-y', '{0}-{1}'.format(PREFIX, item_name)]

        try:
            subprocess.Popen(process, stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0]
        except KeyboardInterrupt:
            pass

        # Remove the namespace package file if applicable.
        for site_package in site.getsitepackages():
            try:
                os.remove(os.path.join(site_package, "{}-{}-nspkg.pth".format(PREFIX, item_name.replace('_', '-'))))
            except Exception:
                continue

        self.stdout.write('{} "{}" successfully uninstalled.'.format(app_or_extension, item_with_prefix))
예제 #14
0
    def handle(self, *args, **options):
        """
        Remove the app from disk and in the database
        """
        from tethys_apps.models import TethysApp, TethysExtension
        app_or_extension = "App" if not options['is_extension'] else 'Extension'
        PREFIX = 'tethysapp' if not options['is_extension'] else 'tethysext'
        item_name = options['app_or_extension'][0]

        # Check for app files installed
        installed_items = get_installed_tethys_extensions(
        ) if options['is_extension'] else get_installed_tethys_apps()

        if PREFIX in item_name:
            prefix_length = len(PREFIX) + 1
            item_name = item_name[prefix_length:]

        module_found = True
        if item_name not in installed_items:
            module_found = False

        # Check for app/extension in database
        TethysModel = TethysApp if not options[
            'is_extension'] else TethysExtension
        db_app = None
        db_found = True

        try:
            db_app = TethysModel.objects.get(package=item_name)
        except TethysModel.DoesNotExist:
            db_found = False

        if not module_found and not db_found:
            warnings.warn(
                'WARNING: {0} with name "{1}" cannot be uninstalled, because it is not installed or'
                ' not an {0}.'.format(app_or_extension, item_name))
            exit(0)

        # Confirm
        item_with_prefix = '{0}-{1}'.format(PREFIX, item_name)

        valid_inputs = ('y', 'n', 'yes', 'no')
        no_inputs = ('n', 'no')

        overwrite_input = input(
            'Are you sure you want to uninstall "{0}"? (y/n): '.format(
                item_with_prefix)).lower()

        while overwrite_input not in valid_inputs:
            overwrite_input = input(
                'Invalid option. Are you sure you want to '
                'uninstall "{0}"? (y/n): '.format(item_with_prefix)).lower()

        if overwrite_input in no_inputs:
            self.stdout.write('Uninstall cancelled by user.')
            exit(0)

        # Remove app from database
        if db_found and db_app:
            db_app.delete()

        if module_found and not options['is_extension']:
            try:
                # Remove directory
                shutil.rmtree(installed_items[item_name])
            except OSError:
                # Remove symbolic link
                os.remove(installed_items[item_name])

        # Uninstall using pip
        process = [
            'pip', 'uninstall', '-y', '{0}-{1}'.format(PREFIX, item_name)
        ]

        try:
            subprocess.Popen(process,
                             stderr=subprocess.STDOUT,
                             stdout=subprocess.PIPE).communicate()[0]
        except KeyboardInterrupt:
            pass

        # Remove the namespace package file if applicable.
        for site_package in site.getsitepackages():
            try:
                os.remove(
                    os.path.join(
                        site_package,
                        "{}-{}-nspkg.pth".format(PREFIX,
                                                 item_name.replace('_', '-'))))
            except Exception:
                continue

        self.stdout.write('{} "{}" successfully uninstalled.'.format(
            app_or_extension, item_with_prefix))
예제 #15
0
 def test_get_installed_tethys_apps(self):
     # Get list of apps installed in the tethysapp directory
     result = helpers.get_installed_tethys_apps()
     self.assertTrue('test_app' in result)
예제 #16
0
    def handle(self, *args, **kwargs):
        """
        Symbolically link the static directories of each app into the static/public directory specified by the
        STATIC_ROOT parameter of the settings.py. Do this prior to running Django's collectstatic method.
        """  # noqa: E501
        if not settings.STATIC_ROOT:
            print(
                'WARNING: Cannot find the STATIC_ROOT setting. Please provide the path to the static directory using '
                'the STATIC_ROOT setting in the portal_config.yml file and try again.'
            )
            exit(1)

        # Read settings
        static_root = settings.STATIC_ROOT

        # Get a list of installed apps and extensions
        installed_apps_and_extensions = get_installed_tethys_apps()
        installed_apps_and_extensions.update(get_installed_tethys_extensions())

        # Provide feedback to user
        print(
            'INFO: Collecting static and public directories of apps and extensions to "{0}".'
            .format(static_root))

        # Get the link option
        link_opt = kwargs.get('link')

        for item, path in installed_apps_and_extensions.items():
            # Check for both variants of the static directory (named either public or static)
            public_path = os.path.join(path, 'public')
            static_path = os.path.join(path, 'static')

            if os.path.isdir(public_path):
                item_static_source_dir = public_path
            elif os.path.isdir(static_path):
                item_static_source_dir = static_path
            else:
                print(
                    f'WARNING: Cannot find a directory named "static" or "public" for app "{item}". Skipping...'
                )
                continue

            # Path for app in the STATIC_ROOT directory
            item_static_root_dir = os.path.join(static_root, item)

            # Clear out old symbolic links/directories if necessary
            try:
                # Remove link
                os.remove(item_static_root_dir)
            except OSError:
                try:
                    # Remove directory
                    shutil.rmtree(item_static_root_dir)
                except OSError:
                    pass
                    # No file to remove

            # Create appropriate symbolic link
            if link_opt:
                os.symlink(item_static_source_dir, item_static_root_dir)
                print(
                    'INFO: Successfully linked public directory to STATIC_ROOT for app "{0}".'
                    .format(item))

            else:
                shutil.copytree(item_static_source_dir, item_static_root_dir)
                print(
                    'INFO: Successfully copied public directory to STATIC_ROOT for app "{0}".'
                    .format(item))