コード例 #1
0
def proper_name_validator(value, default):
    """
    Validate proper_name user input.
    """
    # Check for default
    if value == default:
        return True, value

    # Validate and sanitize user input
    proper_name_error_regex = re.compile(r'^[a-zA-Z0-9\s]+$')
    proper_name_warn_regex = re.compile(r'^[a-zA-Z0-9-\s_\"\']+$')

    if not proper_name_error_regex.match(value):
        # If offending characters are dashes, underscores or quotes, replace and notify user
        if proper_name_warn_regex.match(value):
            before = value
            value = value.replace('_', ' ')
            value = value.replace('-', ' ')
            value = value.replace('"', '')
            value = value.replace("'", "")
            with pretty_output(FG_YELLOW) as p:
                p.write('Warning: Illegal characters were detected in proper name "{0}". They have been replaced or '
                        'removed with valid characters: "{1}"'.format(before, value))
        # Otherwise, throw error
        else:
            with pretty_output(FG_RED) as p:
                p.write('Error: Proper name can only contain letters and numbers and spaces.')
            return False, value
    return True, value
コード例 #2
0
def proper_name_validator(value, default):
    """
    Validate proper_name user input.
    """
    # Check for default
    if value == default:
        return True, value

    # Validate and sanitize user input
    proper_name_error_regex = re.compile(r'^[a-zA-Z0-9\s]+$')
    proper_name_warn_regex = re.compile(r'^[a-zA-Z0-9-\s_\"\']+$')

    if not proper_name_error_regex.match(value):
        # If offending characters are dashes, underscores or quotes, replace and notify user
        if proper_name_warn_regex.match(value):
            before = value
            value = value.replace('_', ' ')
            value = value.replace('-', ' ')
            value = value.replace('"', '')
            value = value.replace("'", "")
            with pretty_output(FG_YELLOW) as p:
                p.write(
                    'Warning: Illegal characters were detected in proper name "{0}". They have been replaced or '
                    'removed with valid characters: "{1}"'.format(
                        before, value))
        # Otherwise, throw error
        else:
            with pretty_output(FG_RED) as p:
                p.write(
                    'Error: Proper name can only contain letters and numbers and spaces.'
                )
            return False, value
    return True, value
コード例 #3
0
def create_ps_database_setting(app_package,
                               name,
                               description='',
                               required=False,
                               initializer='',
                               initialized=False,
                               spatial=False,
                               dynamic=False):
    from tethys_apps.cli.cli_colors import pretty_output, FG_RED, FG_GREEN
    from tethys_apps.models import PersistentStoreDatabaseSetting
    from tethys_apps.models import TethysApp

    try:
        app = TethysApp.objects.get(package=app_package)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A Tethys App with the name "{}" does not exist. Aborted.'.
                    format(app_package))
        return False

    try:
        setting = PersistentStoreDatabaseSetting.objects.get(name=name)
        if setting:
            with pretty_output(FG_RED) as p:
                p.write(
                    'A PersistentStoreDatabaseSetting with name "{}" already exists. Aborted.'
                    .format(name))
            return False
    except ObjectDoesNotExist:
        pass

    try:
        ps_database_setting = PersistentStoreDatabaseSetting(
            tethys_app=app,
            name=name,
            description=description,
            required=required,
            initializer=initializer,
            initialized=initialized,
            spatial=spatial,
            dynamic=dynamic)
        ps_database_setting.save()
        with pretty_output(FG_GREEN) as p:
            p.write(
                'PersistentStoreDatabaseSetting named "{}" for app "{}" created successfully!'
                .format(name, app_package))
        return True
    except Exception as e:
        print(e)
        with pretty_output(FG_RED) as p:
            p.write('The above error was encountered. Aborted.'.format(
                app_package))
        return False
コード例 #4
0
ファイル: middleware.py プロジェクト: SarvaPulla/tethys
    def process_exception(self, request, exception):
        if hasattr(social_exceptions, exception.__class__.__name__):
            if isinstance(exception, social_exceptions.AuthCanceled):
                if request.user.is_anonymous:
                    return redirect('accounts:login')
                else:
                    return redirect('user:settings', username=request.user.username)
            elif isinstance(exception, social_exceptions.AuthAlreadyAssociated):
                blurb = 'The {0} account you tried to connect to has already been associated with another account.'
                with pretty_output(FG_WHITE) as p:
                    p.write(exception.backend.name)
                if 'google' in exception.backend.name:
                    blurb = blurb.format('Google')
                elif 'linkedin' in exception.backend.name:
                    blurb = blurb.format('LinkedIn')
                elif 'hydroshare' in exception.backend.name:
                    blurb = blurb.format('HydroShare')
                elif 'facebook' in exception.backend.name:
                    blurb = blurb.format('Facebook')
                else:
                    blurb = blurb.format('social')

                messages.success(request, blurb)

                if request.user.is_anonymous:
                    return redirect('accounts:login')
                else:
                    return redirect('user:settings', username=request.user.username)
            elif isinstance(exception, social_exceptions.NotAllowedToDisconnect):
                blurb = 'Unable to disconnect from this social account.'
                messages.success(request, blurb)
                if request.user.is_anonymous:
                    return redirect('accounts:login')
                else:
                    return redirect('user:settings', username=request.user.username)
コード例 #5
0
ファイル: base.py プロジェクト: SarvaPulla/tethys
    def __init__(self, name, type, endpoint, apikey=None, username=None, password=None):
        """
        Constructor
        """
        self.name = name

        # Validate the types
        if type in VALID_SPATIAL_ENGINES:
            self.type = type
            self.engine = VALID_SPATIAL_ENGINES[type]
        else:
            spatial_engine_key_list = list(VALID_SPATIAL_ENGINES)
            if len(VALID_SPATIAL_ENGINES) > 2:
                comma_separated_types = ', '.join('"{0}"'.format(t) for t in spatial_engine_key_list[:-1])
                last_type = '"{0}"'.format(spatial_engine_key_list[-1])
                valid_types_string = '{0}, and {1}'.format(comma_separated_types, last_type)
            elif len(VALID_SPATIAL_ENGINES) == 2:
                valid_types_string = '"{0}" and "{1}"'.format(spatial_engine_key_list[0], spatial_engine_key_list[1])
            else:
                valid_types_string = '"{0}"'.format(spatial_engine_key_list[0])

            raise ValueError('The value "{0}" is not a valid for argument "type" of SpatialDatasetService.'
                             ' Valid values for "type" argument include {1}.'.format(type, valid_types_string))

        self.endpoint = endpoint
        self.apikey = apikey
        self.username = username
        self.password = password

        with pretty_output(FG_WHITE) as p:
            p.write('DEPRECATION WARNING: Storing connection credentials for Spatial Dataset Services '
                    'in the app.py is a security leak. App configuration for Spatial Dataset Services '
                    'will be deprecated in version 1.2.')
コード例 #6
0
    def test_pretty_output_fg_red(self, mock_print):
        act_msg = 'This is a test in RED'
        expected_string = '\x1b[31mThis is a test in RED\x1b[0m'
        with pretty_output(FG_RED) as p:
            p.write(act_msg)

        mock_print.assert_called_with(expected_string)
コード例 #7
0
    def test_pretty_output_fg_blue(self, mock_print):
        act_msg = 'This is a test in BLUE'
        expected_string = '\x1b[34mThis is a test in BLUE\x1b[0m'
        with pretty_output(FG_BLUE) as p:
            p.write(act_msg)

        mock_print.assert_called_with(expected_string)
コード例 #8
0
    def test_pretty_output_bold_fg_green(self, mock_print):
        act_msg = 'This is a bold text in green'
        expected_string = '\x1b[1m\x1b[32mThis is a bold text in green\x1b[0m'
        with pretty_output(BOLD, FG_GREEN) as p:
            p.write(act_msg)

        mock_print.assert_called_with(expected_string)
コード例 #9
0
    def test_pretty_output_bold_bg_green(self, mock_print):
        act_msg = 'This is a text with green background'
        expected_string = '\x1b[1m\x1b[42mThis is a text with green background\x1b[0m'
        with pretty_output(BOLD, BG_GREEN) as p:
            p.write(act_msg)

        mock_print.assert_called_with(expected_string)
コード例 #10
0
    def test_pretty_output_fg_green(self, mock_print):
        act_msg = 'This is a green text with ' + BOLD + 'bold' + END + ' text included'
        expected_string = '\x1b[32mThis is a green text with \x1b[1mbold\x1b[0m\x1b[32m text included\x1b[0m'
        with pretty_output(FG_GREEN) as p:
            p.write(act_msg)

        mock_print.assert_called_with(expected_string)
コード例 #11
0
ファイル: app_installation.py プロジェクト: SarvaPulla/tethys
def _run_install(self):
    """
    The definition of the "run" method for the CustomInstallCommand metaclass.
    """
    # Get paths
    tethysapp_dir = get_tethysapp_directory()
    destination_dir = os.path.join(tethysapp_dir, self.app_package)

    # Notify user
    with pretty_output(FG_BLACK) as p:
        p.write('Copying App Package: {0} to {1}'.format(self.app_package_dir, destination_dir))

    # Copy files
    try:
        shutil.copytree(self.app_package_dir, destination_dir)

    except Exception:
        try:
            shutil.rmtree(destination_dir)
        except Exception:
            os.remove(destination_dir)

        shutil.copytree(self.app_package_dir, destination_dir)

    # Install dependencies
    for dependency in self.dependencies:
        subprocess.call(['pip', 'install', dependency])

    # Run the original install command
    install.run(self)
コード例 #12
0
ファイル: app_installation.py プロジェクト: sdc50/tethys
def _run_install(self):
    """
    The definition of the "run" method for the CustomInstallCommand metaclass.
    """
    # Get paths
    tethysapp_dir = get_tethysapp_directory()
    destination_dir = os.path.join(tethysapp_dir, self.app_package)

    # Notify user
    with pretty_output(FG_BLACK) as p:
        p.write('Copying App Package: {0} to {1}'.format(
            self.app_package_dir, destination_dir))

    # Copy files
    try:
        shutil.copytree(self.app_package_dir, destination_dir)

    except Exception:
        try:
            shutil.rmtree(destination_dir)
        except Exception:
            os.remove(destination_dir)

        shutil.copytree(self.app_package_dir, destination_dir)

    # Install dependencies
    for dependency in self.dependencies:
        subprocess.call(['pip', 'install', dependency])

    # Run the original install command
    install.run(self)
コード例 #13
0
def remove_ps_database_setting(app_package, name, force=False):
    from tethys_apps.models import TethysApp
    from tethys_apps.cli.cli_colors import pretty_output, FG_RED, FG_GREEN
    from tethys_apps.models import PersistentStoreDatabaseSetting

    try:
        app = TethysApp.objects.get(package=app_package)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A Tethys App with the name "{}" does not exist. Aborted.'.
                    format(app_package))
        return False

    try:
        setting = PersistentStoreDatabaseSetting.objects.get(tethys_app=app,
                                                             name=name)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write(
                'An PersistentStoreDatabaseSetting with the name "{}" for app "{}" does not exist. Aborted.'
                .format(name, app_package))
        return False

    if not force:
        proceed = input(
            'Are you sure you want to delete the '
            'PersistentStoreDatabaseSetting named "{}"? [y/n]: '.format(name))
        while proceed not in ['y', 'n', 'Y', 'N']:
            proceed = input('Please enter either "y" or "n": ')

        if proceed in ['y', 'Y']:
            setting.delete()
            with pretty_output(FG_GREEN) as p:
                p.write(
                    'Successfully removed PersistentStoreDatabaseSetting with name "{0}"!'
                    .format(name))
            return True
        else:
            with pretty_output(FG_RED) as p:
                p.write('Aborted. PersistentStoreDatabaseSetting not removed.')
    else:
        setting.delete()
        with pretty_output(FG_GREEN) as p:
            p.write(
                'Successfully removed PersistentStoreDatabaseSetting with name "{0}"!'
                .format(name))
        return True
コード例 #14
0
ファイル: app_installation.py プロジェクト: sdc50/tethys
def _run_develop(self):
    """
    The definition of the "run" method for the CustomDevelopCommand metaclass.
    """
    # Get paths
    tethysapp_dir = get_tethysapp_directory()
    destination_dir = os.path.join(tethysapp_dir, self.app_package)

    # Notify user
    with pretty_output(FG_BLACK) as p:
        p.write('Creating Symbolic Link to App Package: {0} to {1}'.format(
            self.app_package_dir, destination_dir))

    # Create symbolic link
    try:
        os_symlink = getattr(os, "symlink", None)
        if callable(os_symlink):
            os.symlink(self.app_package_dir, destination_dir)
        else:

            def symlink_ms(source, dest):
                csl = ctypes.windll.kernel32.CreateSymbolicLinkW
                csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p,
                                ctypes.c_uint32)
                csl.restype = ctypes.c_ubyte
                flags = 1 if os.path.isdir(source) else 0
                if csl(dest, source.replace('/', '\\'), flags) == 0:
                    raise ctypes.WinError()

            os.symlink = symlink_ms
            symlink_ms(self.app_package_dir, destination_dir)
    except Exception as e:
        with pretty_output(FG_BLACK) as p:
            p.write(e)
        try:
            shutil.rmtree(destination_dir)
        except Exception:
            os.remove(destination_dir)

        os.symlink(self.app_package_dir, destination_dir)

    # Install dependencies
    for dependency in self.dependencies:
        subprocess.call(['pip', 'install', dependency])

    # Run the original develop command
    develop.run(self)
コード例 #15
0
def link_command(args):
    """
    Interact with Tethys Services (Spatial/Persistent Stores) to create them and/or link them to existing apps
    """
    try:
        service = args.service
        setting = args.setting

        service_parts = service.split(':')
        setting_parts = setting.split(':')
        service_type = None
        service_uid = None
        setting_app_package = None
        setting_type = None
        setting_uid = None

        try:
            service_type = service_parts[0]
            service_uid = service_parts[1]

            setting_app_package = setting_parts[0]
            setting_type = setting_parts[1]
            setting_uid = setting_parts[2]
        except IndexError:
            with pretty_output(FG_RED) as p:
                p.write(
                    'Incorrect argument format. \nUsage: "tethys link <spatial|persistent>:<service_id|service_name> '
                    '<app_package>:<setting_type (ps_database|ps_connection|ds_spatial)><setting_id|setting_name>"'
                    '\nCommand aborted.')
            exit(1)

        success = link_service_to_app_setting(service_type, service_uid,
                                              setting_app_package,
                                              setting_type, setting_uid)

        if not success:
            exit(1)

        exit(0)

    except Exception as e:
        with pretty_output(FG_RED) as p:
            p.write(e)
            p.write('An unexpected error occurred. Please try again.')
        exit(1)
コード例 #16
0
    def test_pretty_output_empty_msg(self, mock_print):
        in_msg = BOLD + 'Use this' + END + ' even with ' + BOLD + FG_RED + 'no parameters' + \
                 END + ' in the with statement'
        expected_string = '\x1b[1mUse this\x1b[0m even with \x1b[1m\x1b[31mno parameters\x1b' \
                          '[0m in the with statement\x1b[0m'
        with pretty_output() as p:
            p.write(in_msg)

        mock_print.assert_called_with(expected_string)
コード例 #17
0
ファイル: app_installation.py プロジェクト: SarvaPulla/tethys
def _run_develop(self):
    """
    The definition of the "run" method for the CustomDevelopCommand metaclass.
    """
    # Get paths
    tethysapp_dir = get_tethysapp_directory()
    destination_dir = os.path.join(tethysapp_dir, self.app_package)

    # Notify user
    with pretty_output(FG_BLACK) as p:
        p.write('Creating Symbolic Link to App Package: {0} to {1}'.format(self.app_package_dir, destination_dir))

    # Create symbolic link
    try:
        os_symlink = getattr(os, "symlink", None)
        if callable(os_symlink):
            os.symlink(self.app_package_dir, destination_dir)
        else:
            def symlink_ms(source, dest):
                csl = ctypes.windll.kernel32.CreateSymbolicLinkW
                csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
                csl.restype = ctypes.c_ubyte
                flags = 1 if os.path.isdir(source) else 0
                if csl(dest, source.replace('/', '\\'), flags) == 0:
                    raise ctypes.WinError()

            os.symlink = symlink_ms
            symlink_ms(self.app_package_dir, destination_dir)
    except Exception as e:
        with pretty_output(FG_BLACK) as p:
            p.write(e)
        try:
            shutil.rmtree(destination_dir)
        except Exception:
            os.remove(destination_dir)

        os.symlink(self.app_package_dir, destination_dir)

    # Install dependencies
    for dependency in self.dependencies:
        subprocess.call(['pip', 'install', dependency])

    # Run the original develop command
    develop.run(self)
コード例 #18
0
ファイル: utilities.py プロジェクト: SarvaPulla/tethys
def create_ps_database_setting(app_package, name, description='', required=False, initializer='', initialized=False,
                               spatial=False, dynamic=False):
    from tethys_apps.cli.cli_colors import pretty_output, FG_RED, FG_GREEN
    from tethys_apps.models import PersistentStoreDatabaseSetting
    from tethys_apps.models import TethysApp

    try:
        app = TethysApp.objects.get(package=app_package)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A Tethys App with the name "{}" does not exist. Aborted.'.format(app_package))
        return False

    try:
        setting = PersistentStoreDatabaseSetting.objects.get(name=name)
        if setting:
            with pretty_output(FG_RED) as p:
                p.write('A PersistentStoreDatabaseSetting with name "{}" already exists. Aborted.'.format(name))
            return False
    except ObjectDoesNotExist:
        pass

    try:
        ps_database_setting = PersistentStoreDatabaseSetting(
            tethys_app=app,
            name=name,
            description=description,
            required=required,
            initializer=initializer,
            initialized=initialized,
            spatial=spatial,
            dynamic=dynamic
        )
        ps_database_setting.save()
        with pretty_output(FG_GREEN) as p:
            p.write('PersistentStoreDatabaseSetting named "{}" for app "{}" created successfully!'.format(name,
                                                                                                          app_package))
        return True
    except Exception as e:
        print(e)
        with pretty_output(FG_RED) as p:
            p.write('The above error was encountered. Aborted.'.format(app_package))
        return False
コード例 #19
0
ファイル: link_commands.py プロジェクト: SarvaPulla/tethys
def link_command(args):
    """
    Interact with Tethys Services (Spatial/Persistent Stores) to create them and/or link them to existing apps
    """
    try:
        service = args.service
        setting = args.setting

        service_parts = service.split(':')
        setting_parts = setting.split(':')
        service_type = None
        service_uid = None
        setting_app_package = None
        setting_type = None
        setting_uid = None

        try:
            service_type = service_parts[0]
            service_uid = service_parts[1]

            setting_app_package = setting_parts[0]
            setting_type = setting_parts[1]
            setting_uid = setting_parts[2]
        except IndexError:
            with pretty_output(FG_RED) as p:
                p.write(
                    'Incorrect argument format. \nUsage: "tethys link <spatial|persistent>:<service_id|service_name> '
                    '<app_package>:<setting_type (ps_database|ps_connection|ds_spatial)><setting_id|setting_name>"'
                    '\nCommand aborted.')
            exit(1)

        success = link_service_to_app_setting(service_type, service_uid, setting_app_package, setting_type, setting_uid)

        if not success:
            exit(1)

        exit(0)

    except Exception as e:
        with pretty_output(FG_RED) as p:
            p.write(e)
            p.write('An unexpected error occurred. Please try again.')
        exit(1)
コード例 #20
0
ファイル: base.py プロジェクト: SarvaPulla/tethys
    def __init__(self, name, endpoint, username=None, password=None):
        """
        Constructor
        """
        self.name = name
        self.endpoint = endpoint
        self.username = username
        self.password = password

        with pretty_output(FG_WHITE) as p:
            p.write('DEPRECATION WARNING: Storing connection credentials for WPS Services in the app.py is a security '
                    'leak. App configuration for WPS Services will be deprecated in version 1.2.')
コード例 #21
0
ファイル: utilities.py プロジェクト: SarvaPulla/tethys
def remove_ps_database_setting(app_package, name, force=False):
    from tethys_apps.models import TethysApp
    from tethys_apps.cli.cli_colors import pretty_output, FG_RED, FG_GREEN
    from tethys_apps.models import PersistentStoreDatabaseSetting

    try:
        app = TethysApp.objects.get(package=app_package)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A Tethys App with the name "{}" does not exist. Aborted.'.format(app_package))
        return False

    try:
        setting = PersistentStoreDatabaseSetting.objects.get(tethys_app=app, name=name)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('An PersistentStoreDatabaseSetting with the name "{}" for app "{}" does not exist. Aborted.'
                    .format(name, app_package))
        return False

    if not force:
        proceed = input('Are you sure you want to delete the '
                        'PersistentStoreDatabaseSetting named "{}"? [y/n]: '.format(name))
        while proceed not in ['y', 'n', 'Y', 'N']:
            proceed = input('Please enter either "y" or "n": ')

        if proceed in ['y', 'Y']:
            setting.delete()
            with pretty_output(FG_GREEN) as p:
                p.write('Successfully removed PersistentStoreDatabaseSetting with name "{0}"!'.format(name))
            return True
        else:
            with pretty_output(FG_RED) as p:
                p.write('Aborted. PersistentStoreDatabaseSetting not removed.')
    else:
        setting.delete()
        with pretty_output(FG_GREEN) as p:
            p.write('Successfully removed PersistentStoreDatabaseSetting with name "{0}"!'.format(name))
        return True
コード例 #22
0
    def __init__(self, name, endpoint, username=None, password=None):
        """
        Constructor
        """
        self.name = name
        self.endpoint = endpoint
        self.username = username
        self.password = password

        with pretty_output(FG_WHITE) as p:
            p.write(
                'DEPRECATION WARNING: Storing connection credentials for WPS Services in the app.py is a security '
                'leak. App configuration for WPS Services will be deprecated in version 1.2.'
            )
コード例 #23
0
    def __init__(self,
                 name,
                 type,
                 endpoint,
                 apikey=None,
                 username=None,
                 password=None):
        """
        Constructor
        """
        self.name = name

        # Validate the types
        if type in VALID_SPATIAL_ENGINES:
            self.type = type
            self.engine = VALID_SPATIAL_ENGINES[type]
        else:
            spatial_engine_key_list = list(VALID_SPATIAL_ENGINES)
            if len(VALID_SPATIAL_ENGINES) > 2:
                comma_separated_types = ', '.join(
                    '"{0}"'.format(t) for t in spatial_engine_key_list[:-1])
                last_type = '"{0}"'.format(spatial_engine_key_list[-1])
                valid_types_string = '{0}, and {1}'.format(
                    comma_separated_types, last_type)
            elif len(VALID_SPATIAL_ENGINES) == 2:
                valid_types_string = '"{0}" and "{1}"'.format(
                    spatial_engine_key_list[0], spatial_engine_key_list[1])
            else:
                valid_types_string = '"{0}"'.format(spatial_engine_key_list[0])

            raise ValueError(
                'The value "{0}" is not a valid for argument "type" of SpatialDatasetService.'
                ' Valid values for "type" argument include {1}.'.format(
                    type, valid_types_string))

        self.endpoint = endpoint
        self.apikey = apikey
        self.username = username
        self.password = password

        with pretty_output(FG_WHITE) as p:
            p.write(
                'DEPRECATION WARNING: Storing connection credentials for Spatial Dataset Services '
                'in the app.py is a security leak. App configuration for Spatial Dataset Services '
                'will be deprecated in version 1.2.')
コード例 #24
0
ファイル: manage_commands.py プロジェクト: SarvaPulla/tethys
def get_manage_path(args):
    """
    Validate user defined manage path, use default, or throw error
    """
    # Determine path to manage.py file
    manage_path = os.path.join(get_tethys_src_dir(), 'manage.py')

    # Check for path option
    if hasattr(args, 'manage'):
        manage_path = args.manage or manage_path

    # Throw error if path is not valid
    if not os.path.isfile(manage_path):
        with pretty_output(FG_RED) as p:
            p.write('ERROR: Can\'t open file "{0}", no such file.'.format(manage_path))
        exit(1)

    return manage_path
コード例 #25
0
ファイル: manage_commands.py プロジェクト: sdc50/tethys
def get_manage_path(args):
    """
    Validate user defined manage path, use default, or throw error
    """
    # Determine path to manage.py file
    manage_path = os.path.join(get_tethys_src_dir(), 'manage.py')

    # Check for path option
    if hasattr(args, 'manage'):
        manage_path = args.manage or manage_path

    # Throw error if path is not valid
    if not os.path.isfile(manage_path):
        with pretty_output(FG_RED) as p:
            p.write('ERROR: Can\'t open file "{0}", no such file.'.format(
                manage_path))
        exit(1)

    return manage_path
コード例 #26
0
def theme_color_validator(value, default):
    """
    Validate theme_color user input.
    """
    # Generate random color if default option provided
    if value == default:
        return True, get_random_color()

    # Validate hexadecimal if provided
    try:
        if len(value) > 0 and '#' in value:
            value = value[1:]

        int(value, 16)
        value = '#' + value
        return True, value
    except ValueError:
        with pretty_output(FG_RED) as p:
            p.write("Error: Value given is not a valid hexadecimal color.")
        return False, value
コード例 #27
0
def theme_color_validator(value, default):
    """
    Validate theme_color user input.
    """
    # Generate random color if default option provided
    if value == default:
        return True, get_random_color()

    # Validate hexadecimal if provided
    try:
        if len(value) > 0 and '#' in value:
            value = value[1:]

        int(value, 16)
        value = '#' + value
        return True, value
    except ValueError:
        with pretty_output(FG_RED) as p:
            p.write("Error: Value given is not a valid hexadecimal color.")
        return False, value
コード例 #28
0
ファイル: middleware.py プロジェクト: sdc50/tethys
    def process_exception(self, request, exception):
        if hasattr(social_exceptions, exception.__class__.__name__):
            if isinstance(exception, social_exceptions.AuthCanceled):
                if request.user.is_anonymous:
                    return redirect('accounts:login')
                else:
                    return redirect('user:settings',
                                    username=request.user.username)
            elif isinstance(exception,
                            social_exceptions.AuthAlreadyAssociated):
                blurb = 'The {0} account you tried to connect to has already been associated with another account.'
                with pretty_output(FG_WHITE) as p:
                    p.write(exception.backend.name)
                if 'google' in exception.backend.name:
                    blurb = blurb.format('Google')
                elif 'linkedin' in exception.backend.name:
                    blurb = blurb.format('LinkedIn')
                elif 'hydroshare' in exception.backend.name:
                    blurb = blurb.format('HydroShare')
                elif 'facebook' in exception.backend.name:
                    blurb = blurb.format('Facebook')
                else:
                    blurb = blurb.format('social')

                messages.success(request, blurb)

                if request.user.is_anonymous:
                    return redirect('accounts:login')
                else:
                    return redirect('user:settings',
                                    username=request.user.username)
            elif isinstance(exception,
                            social_exceptions.NotAllowedToDisconnect):
                blurb = 'Unable to disconnect from this social account.'
                messages.success(request, blurb)
                if request.user.is_anonymous:
                    return redirect('accounts:login')
                else:
                    return redirect('user:settings',
                                    username=request.user.username)
コード例 #29
0
def scaffold_command(args):
    """
    Create a new Tethys app projects in the current directory.
    """
    # Log
    log = logging.getLogger('tethys')
    # log.setLevel(logging.DEBUG)
    log.debug('Command args: {}'.format(args))

    # Get template dirs
    log.debug('APP_PATH: {}'.format(APP_PATH))
    log.debug('EXTENSION_PATH: {}'.format(EXTENSION_PATH))

    # Get template root directory
    is_extension = False

    if args.extension:
        is_extension = True
        template_name = args.template
        template_root = os.path.join(EXTENSION_PATH, args.template)
    else:
        template_name = args.template
        template_root = os.path.join(APP_PATH, args.template)

    log.debug('Template root directory: {}'.format(template_root))

    # Validate template
    if not os.path.isdir(template_root):
        with pretty_output(FG_WHITE) as p:
            p.write('Error: "{}" is not a valid template.'.format(template_name))
        exit(1)

    # Validate project name
    project_name = args.name

    # Only lowercase
    contains_uppers = False
    for letter in project_name:
        if letter.isupper():
            contains_uppers = True
            break

    if contains_uppers:
        before = project_name
        project_name = project_name.lower()
        with pretty_output(FG_YELLOW) as p:
            p.write('Warning: Uppercase characters in project name "{0}" '
                    'changed to lowercase: "{1}".'.format(before, project_name))

    # Check for valid characters name
    project_error_regex = re.compile(r'^[a-zA-Z0-9_]+$')
    project_warning_regex = re.compile(r'^[a-zA-Z0-9_-]+$')

    # Only letters, numbers and underscores allowed in app names
    if not project_error_regex.match(project_name):
        # If the only offending character is a dash, replace dashes with underscores and notify user
        if project_warning_regex.match(project_name):
            before = project_name
            project_name = project_name.replace('-', '_')
            with pretty_output(FG_YELLOW) as p:
                p.write('Warning: Dashes in project name "{0}" have been replaced '
                        'with underscores "{1}"'.format(before, project_name))
        # Otherwise, throw error
        else:
            with pretty_output(FG_YELLOW) as p:
                p.write('Error: Invalid characters in project name "{0}". '
                        'Only letters, numbers, and underscores.'.format(project_name))
            exit(1)

    # Project name derivatives
    project_dir = '{0}-{1}'.format(EXTENSION_PREFIX if is_extension else APP_PREFIX, project_name)
    split_project_name = project_name.split('_')
    title_case_project_name = [x.title() for x in split_project_name]
    default_proper_name = ' '.join(title_case_project_name)
    class_name = ''.join(title_case_project_name)
    default_theme_color = get_random_color()

    with pretty_output(FG_WHITE) as p:
        p.write('Creating new Tethys project named "{0}".'.format(project_dir))

    # Get metadata from user
    if not is_extension:
        metadata_input = (
            {
                'name': 'proper_name',
                'prompt': 'Proper name for the app (e.g.: "My First App")',
                'default': default_proper_name,
                'validator': proper_name_validator
            },
            {
                'name': 'description',
                'prompt': 'Brief description of the app',
                'default': '',
                'validator': None
            },
            {
                'name': 'color',
                'prompt': 'App theme color (e.g.: "#27AE60")',
                'default': default_theme_color,
                'validator': theme_color_validator
            },
            {
                'name': 'tags',
                'prompt': 'Tags: Use commas to delineate tags and '
                          'quotes around each tag (e.g.: "Hydrology","Reference Timeseries")',
                'default': '',
                'validator': None
            },
            {
                'name': 'author',
                'prompt': 'Author name',
                'default': '',
                'validator': None
            },
            {
                'name': 'author_email',
                'prompt': 'Author email',
                'default': '',
                'validator': None
            },
            {
                'name': 'license_name',
                'prompt': 'License name',
                'default': '',
                'validator': None
            },
        )
    else:
        metadata_input = (
            {
                'name': 'proper_name',
                'prompt': 'Proper name for the extension (e.g.: "My First Extension")',
                'default': default_proper_name,
                'validator': proper_name_validator
            },
            {
                'name': 'description',
                'prompt': 'Brief description of the extension',
                'default': '',
                'validator': None
            },
            {
                'name': 'author',
                'prompt': 'Author name',
                'default': '',
                'validator': None
            },
            {
                'name': 'author_email',
                'prompt': 'Author email',
                'default': '',
                'validator': None
            },
            {
                'name': 'license_name',
                'prompt': 'License name',
                'default': '',
                'validator': None
            },
        )

    # Build up template context
    context = {
        'project': project_name,
        'project_dir': project_dir,
        'project_url': project_name.replace('_', '-'),
        'class_name': class_name,
        'proper_name': default_proper_name,
        'description': '',
        'color': default_theme_color,
        'tags': '',
        'author': '',
        'author_email': '',
        'license_name': ''
    }

    if not args.use_defaults:
        # Collect metadata input from user
        for item in metadata_input:
            valid = False
            response = item['default']

            while not valid:
                try:
                    response = input('{0} ["{1}"]: '.format(item['prompt'], item['default'])) or item['default']
                except (KeyboardInterrupt, SystemExit):
                    with pretty_output(FG_YELLOW) as p:
                        p.write('\nScaffolding cancelled.')
                    exit(1)

                if callable(item['validator']):
                    valid, response = item['validator'](response, item['default'])
                else:
                    valid = True

                if not valid:
                    with pretty_output(FG_RED) as p:
                        p.write('Invalid response: {}'.format(response))

            context[item['name']] = response

    log.debug('Template context: {}'.format(context))

    # Create root directory
    project_root = os.path.join(os.getcwd(), project_dir)
    log.debug('Project root path: {}'.format(project_root))

    if os.path.isdir(project_root):
        if not args.overwrite:
            valid = False
            negative_choices = ['n', 'no', '']
            valid_choices = ['y', 'n', 'yes', 'no']
            default = 'y'
            response = ''

            while not valid:
                try:
                    response = input('Directory "{}" already exists. '
                                     'Would you like to overwrite it? [Y/n]: '.format(project_root)) or default
                except (KeyboardInterrupt, SystemExit):
                    with pretty_output(FG_YELLOW) as p:
                        p.write('\nScaffolding cancelled.')
                    exit(1)

                if response.lower() in valid_choices:
                    valid = True

            if response.lower() in negative_choices:
                with pretty_output(FG_YELLOW) as p:
                    p.write('Scaffolding cancelled.')
                exit(0)

        try:
            shutil.rmtree(project_root)
        except OSError:
            with pretty_output(FG_YELLOW) as p:
                p.write('Error: Unable to overwrite "{}". '
                        'Please remove the directory and try again.'.format(project_root))
            exit(1)

    # Walk the template directory, creating the templates and directories in the new project as we go
    template_context = Context(context)

    for curr_template_root, dirs, template_files in os.walk(template_root):
        # print(curr_template_root, dirs, files)
        curr_project_root = curr_template_root.replace(template_root, project_root)
        curr_project_root = render_path(curr_project_root, context)

        # Create Root Directory
        os.makedirs(curr_project_root)
        with pretty_output(FG_WHITE) as p:
            p.write('Created: "{}"'.format(curr_project_root))

        # Create Files
        for template_file in template_files:
            template_file_path = os.path.join(curr_template_root, template_file)
            project_file = template_file.replace(TEMPLATE_SUFFIX, '')
            project_file_path = os.path.join(curr_project_root, project_file)
            template = None

            # Load the template
            log.debug('Loading template: "{}"'.format(template_file_path))

            try:
                with open(template_file_path, 'r') as tfp:
                    template = Template(tfp.read())
            except UnicodeDecodeError:
                with open(template_file_path, 'br') as tfp:
                    with open(project_file_path, 'bw') as pfp:
                        pfp.write(tfp.read())
                continue

            # Render template if loaded
            log.debug('Rendering template: "{}"'.format(template_file_path))
            if template:
                with open(project_file_path, 'w') as pfp:
                    pfp.write(template.render(template_context))
                with pretty_output(FG_WHITE) as p:
                    p.write('Created: "{}"'.format(project_file_path))

    with pretty_output(FG_WHITE) as p:
        p.write('Successfully scaffolded new project "{}"'.format(project_name))
コード例 #30
0
def scaffold_command(args):
    """
    Create a new Tethys app projects in the current directory.
    """
    # Log
    log = logging.getLogger('tethys')
    # log.setLevel(logging.DEBUG)
    log.debug('Command args: {}'.format(args))

    # Get template dirs
    log.debug('APP_PATH: {}'.format(APP_PATH))
    log.debug('EXTENSION_PATH: {}'.format(EXTENSION_PATH))

    # Get template root directory
    is_extension = False

    if args.extension:
        is_extension = True
        template_name = args.template
        template_root = os.path.join(EXTENSION_PATH, args.template)
    else:
        template_name = args.template
        template_root = os.path.join(APP_PATH, args.template)

    log.debug('Template root directory: {}'.format(template_root))

    # Validate template
    if not os.path.isdir(template_root):
        with pretty_output(FG_WHITE) as p:
            p.write(
                'Error: "{}" is not a valid template.'.format(template_name))
        exit(1)

    # Validate project name
    project_name = args.name

    # Only lowercase
    contains_uppers = False
    for letter in project_name:
        if letter.isupper():
            contains_uppers = True
            break

    if contains_uppers:
        before = project_name
        project_name = project_name.lower()
        with pretty_output(FG_YELLOW) as p:
            p.write('Warning: Uppercase characters in project name "{0}" '
                    'changed to lowercase: "{1}".'.format(
                        before, project_name))

    # Check for valid characters name
    project_error_regex = re.compile(r'^[a-zA-Z0-9_]+$')
    project_warning_regex = re.compile(r'^[a-zA-Z0-9_-]+$')

    # Only letters, numbers and underscores allowed in app names
    if not project_error_regex.match(project_name):
        # If the only offending character is a dash, replace dashes with underscores and notify user
        if project_warning_regex.match(project_name):
            before = project_name
            project_name = project_name.replace('-', '_')
            with pretty_output(FG_YELLOW) as p:
                p.write(
                    'Warning: Dashes in project name "{0}" have been replaced '
                    'with underscores "{1}"'.format(before, project_name))
        # Otherwise, throw error
        else:
            with pretty_output(FG_YELLOW) as p:
                p.write('Error: Invalid characters in project name "{0}". '
                        'Only letters, numbers, and underscores.'.format(
                            project_name))
            exit(1)

    # Project name derivatives
    project_dir = '{0}-{1}'.format(
        EXTENSION_PREFIX if is_extension else APP_PREFIX, project_name)
    split_project_name = project_name.split('_')
    title_case_project_name = [x.title() for x in split_project_name]
    default_proper_name = ' '.join(title_case_project_name)
    class_name = ''.join(title_case_project_name)
    default_theme_color = get_random_color()

    with pretty_output(FG_WHITE) as p:
        p.write('Creating new Tethys project named "{0}".'.format(project_dir))

    # Get metadata from user
    if not is_extension:
        metadata_input = (
            {
                'name': 'proper_name',
                'prompt': 'Proper name for the app (e.g.: "My First App")',
                'default': default_proper_name,
                'validator': proper_name_validator
            },
            {
                'name': 'description',
                'prompt': 'Brief description of the app',
                'default': '',
                'validator': None
            },
            {
                'name': 'color',
                'prompt': 'App theme color (e.g.: "#27AE60")',
                'default': default_theme_color,
                'validator': theme_color_validator
            },
            {
                'name': 'tags',
                'prompt': 'Tags: Use commas to delineate tags and '
                'quotes around each tag (e.g.: "Hydrology","Reference Timeseries")',
                'default': '',
                'validator': None
            },
            {
                'name': 'author',
                'prompt': 'Author name',
                'default': '',
                'validator': None
            },
            {
                'name': 'author_email',
                'prompt': 'Author email',
                'default': '',
                'validator': None
            },
            {
                'name': 'license_name',
                'prompt': 'License name',
                'default': '',
                'validator': None
            },
        )
    else:
        metadata_input = (
            {
                'name': 'proper_name',
                'prompt':
                'Proper name for the extension (e.g.: "My First Extension")',
                'default': default_proper_name,
                'validator': proper_name_validator
            },
            {
                'name': 'description',
                'prompt': 'Brief description of the extension',
                'default': '',
                'validator': None
            },
            {
                'name': 'author',
                'prompt': 'Author name',
                'default': '',
                'validator': None
            },
            {
                'name': 'author_email',
                'prompt': 'Author email',
                'default': '',
                'validator': None
            },
            {
                'name': 'license_name',
                'prompt': 'License name',
                'default': '',
                'validator': None
            },
        )

    # Build up template context
    context = {
        'project': project_name,
        'project_dir': project_dir,
        'project_url': project_name.replace('_', '-'),
        'class_name': class_name,
        'proper_name': default_proper_name,
        'description': '',
        'color': default_theme_color,
        'tags': '',
        'author': '',
        'author_email': '',
        'license_name': ''
    }

    if not args.use_defaults:
        # Collect metadata input from user
        for item in metadata_input:
            valid = False
            response = item['default']

            while not valid:
                try:
                    response = input('{0} ["{1}"]: '.format(
                        item['prompt'], item['default'])) or item['default']
                except (KeyboardInterrupt, SystemExit):
                    with pretty_output(FG_YELLOW) as p:
                        p.write('\nScaffolding cancelled.')
                    exit(1)

                if callable(item['validator']):
                    valid, response = item['validator'](response,
                                                        item['default'])
                else:
                    valid = True

                if not valid:
                    with pretty_output(FG_RED) as p:
                        p.write('Invalid response: {}'.format(response))

            context[item['name']] = response

    log.debug('Template context: {}'.format(context))

    # Create root directory
    project_root = os.path.join(os.getcwd(), project_dir)
    log.debug('Project root path: {}'.format(project_root))

    if os.path.isdir(project_root):
        if not args.overwrite:
            valid = False
            negative_choices = ['n', 'no', '']
            valid_choices = ['y', 'n', 'yes', 'no']
            default = 'y'
            response = ''

            while not valid:
                try:
                    response = input('Directory "{}" already exists. '
                                     'Would you like to overwrite it? [Y/n]: '.
                                     format(project_root)) or default
                except (KeyboardInterrupt, SystemExit):
                    with pretty_output(FG_YELLOW) as p:
                        p.write('\nScaffolding cancelled.')
                    exit(1)

                if response.lower() in valid_choices:
                    valid = True

            if response.lower() in negative_choices:
                with pretty_output(FG_YELLOW) as p:
                    p.write('Scaffolding cancelled.')
                exit(0)

        try:
            shutil.rmtree(project_root)
        except OSError:
            with pretty_output(FG_YELLOW) as p:
                p.write('Error: Unable to overwrite "{}". '
                        'Please remove the directory and try again.'.format(
                            project_root))
            exit(1)

    # Walk the template directory, creating the templates and directories in the new project as we go
    template_context = Context(context)

    for curr_template_root, dirs, template_files in os.walk(template_root):
        # print(curr_template_root, dirs, files)
        curr_project_root = curr_template_root.replace(template_root,
                                                       project_root)
        curr_project_root = render_path(curr_project_root, context)

        # Create Root Directory
        os.makedirs(curr_project_root)
        with pretty_output(FG_WHITE) as p:
            p.write('Created: "{}"'.format(curr_project_root))

        # Create Files
        for template_file in template_files:
            template_file_path = os.path.join(curr_template_root,
                                              template_file)
            project_file = template_file.replace(TEMPLATE_SUFFIX, '')
            project_file_path = os.path.join(curr_project_root, project_file)
            template = None

            # Load the template
            log.debug('Loading template: "{}"'.format(template_file_path))

            try:
                with open(template_file_path, 'r') as tfp:
                    template = Template(tfp.read())
            except UnicodeDecodeError:
                with open(template_file_path, 'br') as tfp:
                    with open(project_file_path, 'bw') as pfp:
                        pfp.write(tfp.read())
                continue

            # Render template if loaded
            log.debug('Rendering template: "{}"'.format(template_file_path))
            if template:
                with open(project_file_path, 'w') as pfp:
                    pfp.write(template.render(template_context))
                with pretty_output(FG_WHITE) as p:
                    p.write('Created: "{}"'.format(project_file_path))

    with pretty_output(FG_WHITE) as p:
        p.write(
            'Successfully scaffolded new project "{}"'.format(project_name))
コード例 #31
0
ファイル: app_settings_commands.py プロジェクト: sdc50/tethys
def app_settings_list_command(args):
    from tethys_apps.models import (TethysApp, PersistentStoreConnectionSetting, PersistentStoreDatabaseSetting,
                                    SpatialDatasetServiceSetting)

    setting_type_dict = {
        PersistentStoreConnectionSetting: 'ps_connection',
        PersistentStoreDatabaseSetting: 'ps_database',
        SpatialDatasetServiceSetting: 'ds_spatial'
    }

    app_package = args.app
    try:
        app = TethysApp.objects.get(package=app_package)

        app_settings = []
        for setting in PersistentStoreConnectionSetting.objects.filter(tethys_app=app):
            app_settings.append(setting)
        for setting in PersistentStoreDatabaseSetting.objects.filter(tethys_app=app):
            app_settings.append(setting)
        for setting in SpatialDatasetServiceSetting.objects.filter(tethys_app=app):
            app_settings.append(setting)

        unlinked_settings = []
        linked_settings = []

        for setting in app_settings:
            if hasattr(setting, 'spatial_dataset_service') and setting.spatial_dataset_service \
                    or hasattr(setting, 'persistent_store_service') and setting.persistent_store_service:
                linked_settings.append(setting)
            else:
                unlinked_settings.append(setting)

        with pretty_output(BOLD) as p:
            p.write("\nUnlinked Settings:")

        if len(unlinked_settings) == 0:
            with pretty_output() as p:
                p.write('None')
        else:
            is_first_row = True
            for setting in unlinked_settings:
                if is_first_row:
                    with pretty_output(BOLD) as p:
                        p.write('{0: <10}{1: <40}{2: <15}'.format('ID', 'Name', 'Type'))
                    is_first_row = False
                with pretty_output() as p:
                    p.write('{0: <10}{1: <40}{2: <15}'.format(setting.pk, setting.name,
                                                              setting_type_dict[type(setting)]))

        with pretty_output(BOLD) as p:
            p.write("\nLinked Settings:")

        if len(linked_settings) == 0:
            with pretty_output() as p:
                p.write('None')
        else:
            is_first_row = True
            for setting in linked_settings:
                if is_first_row:
                    with pretty_output(BOLD) as p:
                        p.write('{0: <10}{1: <40}{2: <15}{3: <20}'.format('ID', 'Name', 'Type', 'Linked With'))
                    is_first_row = False
                service_name = setting.spatial_dataset_service.name if hasattr(setting, 'spatial_dataset_service') \
                    else setting.persistent_store_service.name
                print('{0: <10}{1: <40}{2: <15}{3: <20}'.format(setting.pk, setting.name,
                                                                setting_type_dict[type(setting)], service_name))
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('The app you specified ("{0}") does not exist. Command aborted.'.format(app_package))
    except Exception as e:
        with pretty_output(FG_RED) as p:
            p.write(e)
            p.write('Something went wrong. Please try again.')
コード例 #32
0
ファイル: utilities.py プロジェクト: SarvaPulla/tethys
def link_service_to_app_setting(service_type, service_uid, app_package, setting_type, setting_uid):
    """
    Links a Tethys Service to a TethysAppSetting.
    :param service_type: The type of service being linked to an app. Must be either 'spatial' or 'persistent'.
    :param service_uid: The name or id of the service being linked to an app.
    :param app_package: The package name of the app whose setting is being linked to a service.
    :param setting_type: The type of setting being linked to a service. Must be one of the following: 'ps_database',
    'ps_connection', or 'ds_spatial'.
    :param setting_uid: The name or id of the setting being linked to a service.
    :return: True if successful, False otherwise.
    """
    from tethys_apps.cli.cli_colors import pretty_output, FG_GREEN, FG_RED
    from tethys_sdk.app_settings import (SpatialDatasetServiceSetting, PersistentStoreConnectionSetting,
                                         PersistentStoreDatabaseSetting)
    from tethys_services.models import (SpatialDatasetService, PersistentStoreService)
    from tethys_apps.models import TethysApp

    service_type_to_model_dict = {
        'spatial': SpatialDatasetService,
        'persistent': PersistentStoreService
    }

    setting_type_to_link_model_dict = {
        'ps_database': {
            'setting_model': PersistentStoreDatabaseSetting,
            'service_field': 'persistent_store_service'
        },
        'ps_connection': {
            'setting_model': PersistentStoreConnectionSetting,
            'service_field': 'persistent_store_service'
        },
        'ds_spatial': {
            'setting_model': SpatialDatasetServiceSetting,
            'service_field': 'spatial_dataset_service'
        }
    }

    service_model = service_type_to_model_dict[service_type]

    try:
        try:
            service_uid = int(service_uid)
            service = service_model.objects.get(pk=service_uid)
        except ValueError:
            service = service_model.objects.get(name=service_uid)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A {0} with ID/Name "{1}" does not exist.'.format(str(service_model), service_uid))
        return False

    try:
        app = TethysApp.objects.get(package=app_package)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A Tethys App with the name "{}" does not exist. Aborted.'.format(app_package))
        return False

    try:
        linked_setting_model_dict = setting_type_to_link_model_dict[setting_type]
    except KeyError:
        with pretty_output(FG_RED) as p:
            p.write('The setting_type you specified ("{0}") does not exist.'
                    '\nChoose from: "ps_database|ps_connection|ds_spatial"'.format(setting_type))
        return False

    linked_setting_model = linked_setting_model_dict['setting_model']
    linked_service_field = linked_setting_model_dict['service_field']

    try:
        try:
            setting_uid = int(setting_uid)
            setting = linked_setting_model.objects.get(tethys_app=app, pk=setting_uid)
        except ValueError:
            setting = linked_setting_model.objects.get(tethys_app=app, name=setting_uid)

        setattr(setting, linked_service_field, service)
        setting.save()
        with pretty_output(FG_GREEN) as p:
            p.write('{} with name "{}" was successfully linked to "{}" with name "{}" of the "{}" Tethys App'
                    .format(str(service_model), service_uid, linked_setting_model, setting_uid, app_package))
        return True
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A {0} with ID/Name "{1}" does not exist.'.format(str(linked_setting_model), setting_uid))
        return False
コード例 #33
0
ファイル: utilities.py プロジェクト: john3641/tethys
def link_service_to_app_setting(service_type, service_uid, app_package, setting_type, setting_uid):
    """
    Links a Tethys Service to a TethysAppSetting.
    :param service_type: The type of service being linked to an app. Must be either 'spatial' or 'persistent'.
    :param service_uid: The name or id of the service being linked to an app.
    :param app_package: The package name of the app whose setting is being linked to a service.
    :param setting_type: The type of setting being linked to a service. Must be one of the following: 'ps_database',
    'ps_connection', or 'ds_spatial'.
    :param setting_uid: The name or id of the setting being linked to a service.
    :return: True if successful, False otherwise.
    """
    from tethys_apps.cli.cli_colors import pretty_output, FG_GREEN, FG_RED
    from tethys_sdk.app_settings import (SpatialDatasetServiceSetting, PersistentStoreConnectionSetting,
                                         PersistentStoreDatabaseSetting)
    from tethys_services.models import (SpatialDatasetService, PersistentStoreService)
    from tethys_apps.models import TethysApp

    service_type_to_model_dict = {
        'spatial': SpatialDatasetService,
        'persistent': PersistentStoreService
    }

    setting_type_to_link_model_dict = {
        'ps_database': {
            'setting_model': PersistentStoreDatabaseSetting,
            'service_field': 'persistent_store_service'
        },
        'ps_connection': {
            'setting_model': PersistentStoreConnectionSetting,
            'service_field': 'persistent_store_service'
        },
        'ds_spatial': {
            'setting_model': SpatialDatasetServiceSetting,
            'service_field': 'spatial_dataset_service'
        }
    }

    service_model = service_type_to_model_dict[service_type]

    try:
        try:
            service_uid = int(service_uid)
            service = service_model.objects.get(pk=service_uid)
        except ValueError:
            service = service_model.objects.get(name=service_uid)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A {0} with ID/Name "{1}" does not exist.'.format(str(service_model), service_uid))
        return False

    try:
        app = TethysApp.objects.get(package=app_package)
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A Tethys App with the name "{}" does not exist. Aborted.'.format(app_package))
        return False

    try:
        linked_setting_model_dict = setting_type_to_link_model_dict[setting_type]
    except KeyError:
        with pretty_output(FG_RED) as p:
            p.write('The setting_type you specified ("{0}") does not exist.'
                    '\nChoose from: "ps_database|ps_connection|ds_spatial"'.format(setting_type))
        return False

    linked_setting_model = linked_setting_model_dict['setting_model']
    linked_service_field = linked_setting_model_dict['service_field']

    try:
        try:
            setting_uid = int(setting_uid)
            setting = linked_setting_model.objects.get(tethys_app=app, pk=setting_uid)
        except ValueError:
            setting = linked_setting_model.objects.get(tethys_app=app, name=setting_uid)

        setattr(setting, linked_service_field, service)
        setting.save()
        with pretty_output(FG_GREEN) as p:
            p.write('{} with name "{}" was successfully linked to "{}" with name "{}" of the "{}" Tethys App'
                    .format(str(service_model), service_uid, linked_setting_model, setting_uid, app_package))
        return True
    except ObjectDoesNotExist:
        with pretty_output(FG_RED) as p:
            p.write('A {0} with ID/Name "{1}" does not exist.'.format(str(linked_setting_model), setting_uid))
        return False