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')
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')
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'''
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)
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
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)
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
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)
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'''
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)
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')
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')
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