Esempio n. 1
0
    def create_test_persistent_stores_for_app(app_class):
        """
        Creates temporary persistent store databases for this app to be used in testing.

        Args:
            app_class: The app class from the app's app.py module
        Return:
            None
        """
        from tethys_apps.models import TethysApp

        if not is_testing_environment():
            raise EnvironmentError(
                'This function will only execute properly if executed in the testing environment.'
            )

        if not issubclass(app_class, TethysAppBase):
            raise TypeError(
                'The app_class argument was not of the correct type. '
                'It must be a class that inherits from <TethysAppBase>.')

        db_app = TethysApp.objects.get(package=app_class.package)

        ps_database_settings = db_app.persistent_store_database_settings
        for db_setting in ps_database_settings:
            create_store_success = app_class.create_persistent_store(
                db_name=db_setting.name,
                connection_name=None,
                spatial=db_setting.spatial,
                initializer=db_setting.initializer,
                refresh=True,
                force_first_time=True)

            if not create_store_success:
                raise SystemError('The test store was not able to be created')
Esempio n. 2
0
    def create_test_persistent_stores_for_app(app_class):
        """
        Creates temporary persistent store databases for this app to be used in testing.

        Args:
            app_class: The app class from the app's app.py module
        Return:
            None
        """
        from tethys_apps.models import TethysApp

        if not is_testing_environment():
            raise EnvironmentError('This function will only execute properly if executed in the testing environment.')

        if not issubclass(app_class, TethysAppBase):
            raise TypeError('The app_class argument was not of the correct type. '
                            'It must be a class that inherits from <TethysAppBase>.')

        db_app = TethysApp.objects.get(package=app_class.package)

        ps_database_settings = db_app.persistent_store_database_settings
        for db_setting in ps_database_settings:
            create_store_success = app_class.create_persistent_store(db_name=db_setting.name,
                                                                     connection_name=None,
                                                                     spatial=db_setting.spatial,
                                                                     initializer=db_setting.initializer,
                                                                     refresh=True,
                                                                     force_first_time=True)

            if not create_store_success:
                raise SystemError('The test store was not able to be created')
Esempio n. 3
0
    def harvest_extensions(self):
        """
        Searches for and loads Tethys extensions.
        """
        try:
            if not is_testing_environment():
                print(self.BLUE + 'Loading Tethys Extensions...' + self.ENDC)

            import tethysext
            tethys_extensions = dict()
            for _, modname, ispkg in pkgutil.iter_modules(tethysext.__path__):
                if ispkg:
                    tethys_extensions[modname] = 'tethysext.{}'.format(modname)
            self._harvest_extension_instances(tethys_extensions)
        except Exception:
            '''DO NOTHING'''
Esempio n. 4
0
    def harvest_apps(self):
        """
        Searches the apps package for apps
        """
        # Notify user harvesting is taking place
        if not is_testing_environment():
            print(self.BLUE + 'Loading Tethys Apps...' + self.ENDC)

        # List the apps packages in directory
        apps_dir = os.path.join(os.path.dirname(__file__), 'tethysapp')
        app_packages_list = [
            app_package for app_package in os.listdir(apps_dir)
            if app_package != '__pycache__'
        ]

        # Harvest App Instances
        self._harvest_app_instances(app_packages_list)
Esempio n. 5
0
    def drop_persistent_store(cls, name):
        """
        Drop a persistent store database for the app. This method is idempotent.

        Args:
          name(string): Name of the persistent store to be dropped.

        Returns:
          bool: True if successful.


        **Example:**

        ::

            from my_first_app.app import MyFirstApp as app

            result = app.drop_persistent_store('example_db')

            if result:
                # App database 'example_db' was successfully destroyed and no longer exists
                pass

        """

        # Get the setting
        from tethys_apps.models import TethysApp
        db_app = TethysApp.objects.get(package=cls.package)
        ps_database_settings = db_app.persistent_store_database_settings

        if is_testing_environment():
            if 'tethys-testing_' not in name:
                test_store_name = 'tethys-testing_{0}'.format(name)
                name = test_store_name

        try:
            ps_database_setting = ps_database_settings.get(name=name)
        except ObjectDoesNotExist:
            return True

        # Drop the persistent store
        ps_database_setting.drop_persistent_store_database()

        # Remove the database setting
        ps_database_setting.delete()
        return True
Esempio n. 6
0
    def destroy_test_persistent_stores_for_app(app_class):
        """
        Destroys the temporary persistent store databases for this app that were used in testing.

        Args:
            app_class: The app class from the app's app.py module
        Return:
            None
        """
        if not is_testing_environment():
            raise EnvironmentError('This function will only execute properly if executed in the testing environment.')

        if not issubclass(app_class, TethysAppBase):
            raise TypeError('The app_class argument was not of the correct type. '
                            'It must be a class that inherits from <TethysAppBase>.')

        for db_name in app_class.list_persistent_store_databases(static_only=True):
            test_db_name = get_test_db_name(db_name)
            app_class.drop_persistent_store(test_db_name)
Esempio n. 7
0
    def persistent_store_exists(cls, name):
        """
        Returns True if a persistent store with the given name exists for the app.

        Args:
          name(string): Name of the persistent store database to check.

        Returns:
          bool: True if persistent store exists.


        **Example:**

        ::

            from my_first_app.app import MyFirstApp as app

            result = app.persistent_store_exists('example_db')

            if result:
                engine = app.get_persistent_store_engine('example_db')

        """
        from tethys_apps.models import TethysApp
        db_app = TethysApp.objects.get(package=cls.package)
        ps_database_settings = db_app.persistent_store_database_settings

        if is_testing_environment():
            if 'tethys-testing_' not in name:
                test_store_name = 'tethys-testing_{0}'.format(name)
                name = test_store_name

        try:
            # If it exists return True
            ps_database_setting = ps_database_settings.get(name=name)
        except ObjectDoesNotExist:
            # Else return False
            return False

        # Check if it exists
        ps_database_setting.persistent_store_database_exists()
        return True
Esempio n. 8
0
    def get_persistent_store_database(cls, name, as_url=False, as_sessionmaker=False):
        """
        Gets an SQLAlchemy Engine or URL object for the named persistent store database given.

        Args:
          name(string): Name of the PersistentStoreConnectionSetting as defined in app.py.
          as_url(bool): Return SQLAlchemy URL object instead of engine object if True. Defaults to False.
          as_sessionmaker(bool): Returns SessionMaker class bound to the engine if True.  Defaults to False.

        Returns:
          sqlalchemy.Engine or sqlalchemy.URL: An SQLAlchemy Engine or URL object for the persistent store requested.

        **Example:**

        ::

            from my_first_app.app import MyFirstApp as app

            db_engine = app.get_persistent_store_database('example_db')
            db_url = app.get_persistent_store_database('example_db', as_url=True)
            SessionMaker = app.get_persistent_store_database('example_db', as_sessionmaker=True)
            session = SessionMaker()

        """
        from tethys_apps.models import TethysApp
        db_app = TethysApp.objects.get(package=cls.package)
        ps_database_settings = db_app.persistent_store_database_settings

        if is_testing_environment():
            if 'tethys-testing_' not in name:
                test_store_name = 'tethys-testing_{0}'.format(name)
                name = test_store_name

        try:
            ps_database_setting = ps_database_settings.get(name=name)
            return ps_database_setting.get_value(with_db=True, as_url=as_url, as_sessionmaker=as_sessionmaker,
                                                 as_engine=True)
        except ObjectDoesNotExist:
            raise TethysAppSettingDoesNotExist('PersistentStoreDatabaseSetting', name, cls.name)
        except TethysAppSettingNotAssigned:
            cls._log_tethys_app_setting_not_assigned_errror('PersistentStoreConnectionSetting', name)
Esempio n. 9
0
    def harvest_apps(self):
        """
        Searches the apps package for apps
        """
        # Notify user harvesting is taking place

        try:
            if not is_testing_environment():
                print(self.BLUE + 'Loading Tethys Apps...' + self.ENDC)

            import tethysapp
            tethys_apps = dict()
            for _, modname, ispkg in pkgutil.iter_modules(tethysapp.__path__):
                if ispkg:
                    tethys_apps[modname] = 'tethysapp.{}'.format(modname)

            # Harvest App Instances
            self._harvest_app_instances(tethys_apps)

        except Exception:
            '''DO NOTHING'''
Esempio n. 10
0
    def destroy_test_persistent_stores_for_app(app_class):
        """
        Destroys the temporary persistent store databases for this app that were used in testing.

        Args:
            app_class: The app class from the app's app.py module
        Return:
            None
        """
        if not is_testing_environment():
            raise EnvironmentError(
                'This function will only execute properly if executed in the testing environment.'
            )

        if not issubclass(app_class, TethysAppBase):
            raise TypeError(
                'The app_class argument was not of the correct type. '
                'It must be a class that inherits from <TethysAppBase>.')

        for db_name in app_class.list_persistent_store_databases(
                static_only=True):
            test_db_name = get_test_db_name(db_name)
            app_class.drop_persistent_store(test_db_name)
Esempio n. 11
0
    def _harvest_app_instances(self, app_packages_list):
        """
        Search each app package for the app.py module. Find the AppBase class in the app.py
        module and instantiate it. Save the list of instantiated AppBase classes.
        """
        valid_app_instance_list = []
        valid_app_modules = {}
        loaded_apps = []
        for app_name, app_package in app_packages_list.items():

            # Skip these things
            if app_package in [
                    '__init__.py', '__init__.pyc', '.gitignore', '.DS_Store'
            ]:
                continue

            try:
                # Import the app.py module from the custom app package programmatically
                # (e.g.: apps.apps.<custom_package>.app)

                app_module = __import__(app_package + ".app", fromlist=[''])

                for name, obj in inspect.getmembers(app_module):
                    # Retrieve the members of the app_module and iterate through
                    # them to find the the class that inherits from AppBase.
                    try:
                        # issubclass() will fail if obj is not a class
                        if (issubclass(
                                obj,
                                TethysAppBase)) and (obj is not TethysAppBase):
                            # Assign a handle to the class
                            AppClass = getattr(app_module, name)

                            # Instantiate app and validate
                            app_instance = AppClass()
                            validated_app_instance = self._validate_app(
                                app_instance)

                            # sync app with Tethys db
                            app_instance.sync_with_tethys_db()

                            # load/validate app url patterns
                            try:
                                app_instance.url_patterns
                            except Exception:
                                tethys_log.exception(
                                    'App {0} not loaded because of an issue with loading urls:'
                                    .format(app_package))
                                app_instance.remove_from_db()
                                continue

                            # load/validate app handler patterns
                            try:
                                app_instance.handler_patterns
                            except Exception:
                                tethys_log.exception(
                                    'App {0} not loaded because of an issue with loading handlers:'
                                    .format(app_package))
                                app_instance.remove_from_db()
                                continue

                            # register app permissions
                            try:
                                app_instance.register_app_permissions()
                            except ProgrammingError:
                                tethys_log.warning(
                                    "Unable to register app permissions. django_contetn_type "
                                    "table does not exist")
                            except ObjectDoesNotExist as e:
                                tethys_log.warning(e)

                            # compile valid apps
                            if validated_app_instance:
                                valid_app_modules[app_name] = app_package
                                valid_app_instance_list.append(
                                    validated_app_instance)

                                # Notify user that the app has been loaded
                                loaded_apps.append(app_name)

                            # We found the app class so we're done
                            break

                    except TypeError:
                        continue
            except Exception:
                tethys_log.exception(
                    'App {0} not loaded because of the following error:'.
                    format(app_package))
                continue

        # Save valid apps
        self.apps = valid_app_instance_list
        self.app_modules = valid_app_modules

        # Update user
        if not is_testing_environment():
            print(self.BLUE + 'Tethys Apps Loaded: ' + self.ENDC +
                  '{0}'.format(', '.join(loaded_apps)) + '\n')
Esempio n. 12
0
    def _harvest_extension_instances(self, extension_packages):
        """
        Locate the extension class, instantiate it, and save for later use.

        Arg:
            extension_packages(dict<name, extension_package>): Dictionary where keys are the name of the extension and value is the extension package module object.
        """  # noqa:E501
        valid_ext_instances = []
        valid_extension_modules = {}
        loaded_extensions = []

        for extension_name, extension_package in extension_packages.items():

            try:
                # Import the "ext" module from the extension package
                ext_module = __import__(extension_package + ".ext",
                                        fromlist=[''])

                # Retrieve the members of the ext_module and iterate through
                # them to find the the class that inherits from TethysExtensionBase.
                for name, obj in inspect.getmembers(ext_module):
                    try:
                        # issubclass() will fail if obj is not a class
                        if (issubclass(obj, TethysExtensionBase)) and (
                                obj is not TethysExtensionBase):
                            # Assign a handle to the class
                            ExtensionClass = getattr(ext_module, name)

                            # Instantiate app and validate
                            ext_instance = ExtensionClass()
                            validated_ext_instance = self._validate_extension(
                                ext_instance)

                            # sync app with Tethys db
                            ext_instance.sync_with_tethys_db()

                            # compile valid apps
                            if validated_ext_instance:
                                valid_ext_instances.append(
                                    validated_ext_instance)
                                valid_extension_modules[
                                    extension_name] = extension_package

                                # Notify user that the app has been loaded
                                loaded_extensions.append(extension_name)

                            # We found the extension class so we're done
                            break

                    except TypeError:
                        continue
            except Exception:
                tethys_log.exception(
                    'Extension {0} not loaded because of the following error:'.
                    format(extension_package))
                continue

        # Save valid apps
        self.extensions = valid_ext_instances
        self.extension_modules = valid_extension_modules

        # Update user
        if not is_testing_environment():
            print(self.BLUE + 'Tethys Extensions Loaded: ' + self.ENDC +
                  '{0}'.format(', '.join(loaded_extensions)) + '\n')
Esempio n. 13
0
    def create_persistent_store(cls, db_name, connection_name, spatial=False, initializer='', refresh=False,
                                force_first_time=False):
        """
        Creates a new persistent store database for the app. This method is idempotent.

        Args:
          db_name(string): Name of the persistent store that will be created.
          connection_name(string): Name of persistent store connection.
          spatial(bool): Enable spatial extension on the database being created when True. Connection must have superuser role. Defaults to False.
          initializer(string): Dot-notation path to initializer function (e.g.: 'my_first_app.models.init_db').
          refresh(bool): Drop database if it exists and create again when True. Defaults to False.
          force_first_time(bool): Call initializer function with "first_time" parameter forced to True, even if this is not the first time intializing the persistent store database. Defaults to False.

        Returns:
          bool: True if successful.


        **Example:**

        ::

            from my_first_app.app import MyFirstApp as app

            result = app.create_persistent_store('example_db', 'primary')

            if result:
                engine = app.get_persistent_store_engine('example_db')

        """
        # Get named persistent store service connection
        from tethys_apps.models import TethysApp
        from tethys_apps.models import PersistentStoreDatabaseSetting
        db_app = TethysApp.objects.get(package=cls.package)

        # Get connection service
        ps_connection_settings = db_app.persistent_store_connection_settings

        if is_testing_environment():
            if 'tethys-testing_' not in connection_name:
                test_store_name = 'test_{0}'.format(connection_name)
                connection_name = test_store_name

        try:
            ps_connection_setting = ps_connection_settings.get(name=connection_name)
        except ObjectDoesNotExist:
            raise TethysAppSettingDoesNotExist('PersistentStoreConnectionSetting', connection_name, cls.name)

        ps_service = ps_connection_setting.persistent_store_service

        # Check if persistent store database setting already exists before creating it
        try:
            db_setting = db_app.persistent_store_database_settings.get(name=db_name)
            db_setting.persistent_store_service = ps_service
            db_setting.initializer = initializer
            db_setting.save()
        except ObjectDoesNotExist:
            # Create new PersistentStoreDatabaseSetting
            db_setting = PersistentStoreDatabaseSetting(
                name=db_name,
                description='',
                required=False,
                initializer=initializer,
                spatial=spatial,
                dynamic=True
            )

            # Assign the connection service
            db_setting.persistent_store_service = ps_service
            db_app.add_settings((db_setting,))

            # Save database entry
            db_app.save()

        # Create the new database
        db_setting.create_persistent_store_database(refresh=refresh, force_first_time=force_first_time)
        return True