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))
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)
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)
def list_apps_command(args): """ List installed apps. """ installed_apps = get_installed_tethys_apps() for app in installed_apps: print(app)
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))
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))
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))
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))
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))
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))
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))
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))
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))
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))
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)
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))