Exemple #1
0
    def import_app(entry, instance):
        # Import the module, we need to strip down the path into namespace, file and class.
        module_path, app_glue, cls_name = entry.rpartition('.')

        # The app name (full module path to module, not the app!)
        app_name = module_path.rpartition('.')[0]

        if not module_path:
            raise ImproperlyConfigured(
                'Module for your app {} can\'t be found!'.format(entry))

        # The new style definitions works a bit different. We just import the module, search for the first class that is
        # a subclass of AppConfig.
        if cls_name.islower():
            module_path += '.' + cls_name
            app_name = module_path
            cls_name = None

        # Try to load the app module, containing the class.
        try:
            module = importlib.import_module(module_path)

            # If we have a new-style module, check for the first AppConfig extending class in our module.
            # See #109.
            if cls_name is None:
                for name, obj in inspect.getmembers(module):
                    if inspect.isclass(obj) and issubclass(
                            obj, AppConfig) and obj.__name__ != 'AppConfig':
                        cls_name = obj.__name__
                        break

            module = getattr(module, cls_name)
        except TypeError as e:
            raise ImproperlyConfigured(
                'Can\'t load the app {}. Can\'t find the app config! '
                'Check your apps.py and if your app is installed correctly'.
                format(entry)) from e
        except ImportError:
            raise ImproperlyConfigured(
                'Can\'t load the app {}. Can\'t find the app config!'.format(
                    entry))
        except AttributeError as e:
            raise ImproperlyConfigured(
                'Can\'t load the app {}. Can\'t load the app class!'.format(
                    entry)) from e

        # Last check if subclass of appconfig.
        if not issubclass(module, AppConfig):
            raise InvalidAppModule(
                'Your required app {} couldn\'t be loaded!'.format(entry))

        # Ensure app_name points to a valid module.
        try:
            app_module = importlib.import_module(app_name)
        except ImportError:
            raise ImproperlyConfigured(
                'Can\'t import {}. Check that \'{}.{}.name\' is correct.'.
                format(app_name, module_path, cls_name))

        return module(app_name, app_module, instance)
Exemple #2
0
    def create_from_settings(cls, instance, conf):
        try:
            engine_path, _, cls_name = conf['ENGINE'].rpartition('.')
            db_name = conf['NAME']
            db_options = conf['OPTIONS'] if 'OPTIONS' in conf and conf[
                'OPTIONS'] else dict()

            # FIX for #331. Replace utf8 by utf8mb4 in the mysql driver encoding.
            if conf['ENGINE'] == 'peewee_async.MySQLDatabase' and 'charset' in db_options and db_options[
                    'charset'] == 'utf8':
                logging.info(
                    'Forcing to use \'utf8mb4\' instead of \'utf8\' for the MySQL charset option! (Fix #331).'
                )
                db_options['charset'] = 'utf8mb4'

            # We will try to load it so we have the validation inside this class.
            engine = getattr(importlib.import_module(engine_path), cls_name)
        except ImportError:
            raise ImproperlyConfigured('Database engine doesn\'t exist!')
        except Exception as e:
            raise ImproperlyConfigured(
                'Database configuration isn\'t complete or engine could\'t be found!'
            )

        return cls(engine, instance, db_name, **db_options)
Exemple #3
0
    def _path_from_module(self, module):
        """Attempt to determine app's filesystem path from its module."""
        paths = list(getattr(module, '__path__', []))

        if len(paths) != 1:
            filename = getattr(module, '__file__', None)
            if filename is not None:
                paths = [os.path.dirname(filename)]
            else:
                # Can be bugged for unknown reasons.
                paths = list(set(paths))

        if len(paths) > 1:
            raise ImproperlyConfigured(
                'The app module {} has multiple filesystem locations {}; '
                'you must configure this app with an AppConfig subclass '
                'with a \'path\' class attribute.'.format(module, paths))

        elif not paths:
            raise ImproperlyConfigured(
                'The app module {} has no filesystem location, '
                'you must configure this app with an AppConfig subclass '
                'with a \'path\' class attribute.'.format(module))

        return paths[0]
Exemple #4
0
    def _setup(self):
        """
		Setup will create the wrapped settings and load the settings module.
		"""
        settings_method = os.environ.get('PYPLANET_SETTINGS_METHOD', 'python')
        if not settings_method:
            raise ImproperlyConfigured(
                'Settings method is not defined! Please define PYPLANET_SETTINGS_METHOD in your '
                'environment or start script. The possible values: \'python\', \'json\', \'yaml\''
            )

        self._settings_method = settings_method
        try:
            self._settings_method_class = self.BACKEND[settings_method]
        except:
            raise ImproperlyConfigured(
                'The provided settings method \'{}\' does not exist in the current PyPlanet version!'
                'The current possible methods: \'python\', \'json\', \'yaml\'.'
            )

        # Initiate the backend class.
        self._settings = self._settings_method_class()

        # Load the contents.
        self._settings.load()
Exemple #5
0
    async def load_blacklist(self, filename=None):
        """
		Load blacklist file.

		:param filename: File to load or will get from settings.
		:raise: pyplanet.core.exceptions.ImproperlyConfigured
		:raise: pyplanet.core.storage.exceptions.StorageException
		:return: Boolean if loaded.
		"""
        setting = settings.BLACKLIST_FILE
        if isinstance(setting,
                      dict) and self._instance.process_name in setting:
            setting = setting[self._instance.process_name]
        if not isinstance(setting, str):
            setting = None

        if not filename and not setting:
            raise ImproperlyConfigured(
                'The setting \'BLACKLIST_FILE\' is not configured for this server! We can\'t load the Blacklist!'
            )
        if not filename:
            filename = setting.format(
                server_login=self._instance.game.server_player_login)

        try:
            self._instance.gbx('LoadBlackList', filename)
        except Exception as e:
            logging.exception(e)
            raise StorageException(
                'Can\'t load blacklist according the dedicated server, tried loading from \'{}\'!'
                .format(filename)) from e
Exemple #6
0
    async def save_matchsettings(self, filename=None):
        """
		Save the current playlist and configuration to the matchsettings file.

		:param filename: Give the filename of the matchsettings, Leave empty to use the current loaded and configured one.
		:type filename: str
		:raise: pyplanet.contrib.map.exceptions.MapException
		:raise: pyplanet.core.storage.exceptions.StorageException
		"""
        setting = settings.MAP_MATCHSETTINGS
        if isinstance(setting,
                      dict) and self._instance.process_name in setting:
            setting = setting[self._instance.process_name]
        if not isinstance(setting, str):
            setting = None

        if not filename and not setting:
            raise ImproperlyConfigured(
                'The setting \'MAP_MATCHSETTINGS\' is not configured for this server! We can\'t save the Match Settings!'
            )
        if not filename:
            filename = 'MatchSettings/{}'.format(
                setting.format(
                    server_login=self._instance.game.server_player_login))

        try:
            await self._instance.gbx('SaveMatchSettings', filename)
            await self._override_timelimit(filename)
        except Exception as e:
            logging.exception(e)
            raise MapException(
                'Can\'t save matchsettings to \'{}\'!'.format(filename)) from e
Exemple #7
0
    def populate(self, apps, in_order=False):
        """
		Loads application into the apps registry. Once you populate, the order isn't yet been decided.
		After all imports are done you should shuffle the apps list so it's in the right order of execution!

		:param apps: Apps list.
		:param in_order: Is the list already in order?
		:type apps: list
		"""
        if self.ready:
            return

        populated_apps = {}
        dep_dict = {}

        # Load modules.
        for entry in apps:
            app = AppConfig.import_app(entry, self.instance)

            # Check if the app is unique.
            if app.label in self.apps:
                raise ImproperlyConfigured(
                    'Application labels aren\'t unique! Duplicates: {}'.format(
                        app.label))

            # Inject apps instance into app itself.
            app.apps = self

            # Set state on app.
            app.state = AppState.UNLOADED

            # Get dependencies to other apps.
            deps = getattr(app, 'app_dependencies', list())
            if type(deps) is not list:
                deps = []

            # Add to the list so it can get ordered by dependencies. (not if in_order is true).
            if in_order:
                self.apps[app.label] = app
            else:
                populated_apps[app.label] = app

                # Add nodes of dependencies.
                dep_dict[app.label] = deps

        if in_order:
            return

        # Determinate order.
        order = toposort(dep_dict)

        # Add in order
        for label in order:
            try:
                self.apps[label] = populated_apps[label]
            except KeyError:
                if not label.startswith('core.'):
                    raise Exception(
                        'One of the apps depends on a non existing app: {}'.
                        format(label))
Exemple #8
0
    async def save_blacklist(self, filename=None):
        """
		Save the current blacklisted players to file given or fetch from config.

		:param filename: Give the filename of the blacklist, Leave empty to use the current loaded and configured one.
		:type filename: str
		:raise: pyplanet.core.exceptions.ImproperlyConfigured
		:raise: pyplanet.core.storage.exceptions.StorageException
		"""
        setting = settings.BLACKLIST_FILE
        if isinstance(setting,
                      dict) and self._instance.process_name in setting:
            setting = setting[self._instance.process_name]
        if not isinstance(setting, str):
            setting = None

        if not filename and not setting:
            raise ImproperlyConfigured(
                'The setting \'BLACKLIST_FILE\' is not configured for this server! We can\'t save the Blacklist!'
            )
        if not filename:
            filename = setting.format(
                server_login=self._instance.game.server_player_login)

        try:
            await self._instance.gbx('SaveBlackList', filename)
        except Exception as e:
            logging.exception(e)
            raise StorageException(
                'Can\'t save blacklist file to \'{}\'!'.format(
                    filename)) from e
Exemple #9
0
	def __get_migrator(self):
		if isinstance(self.db.engine, (peewee.SqliteDatabase, SqliteExtDatabase)):
			return SqliteMigrator(self.db.engine)
		elif isinstance(self.db.engine, peewee.MySQLDatabase):
			return MySQLMigrator(self.db.engine)
		elif isinstance(self.db.engine, peewee.PostgresqlDatabase):
			return PostgresqlMigrator(self.db.engine)
		raise ImproperlyConfigured('Database engine doesn\'t support Migrations!')
Exemple #10
0
    def create_from_settings(cls, instance, conf):
        try:
            engine_path, _, cls_name = conf['ENGINE'].rpartition('.')
            db_name = conf['NAME']
            db_options = conf['OPTIONS'] if 'OPTIONS' in conf and conf[
                'OPTIONS'] else dict()

            # We will try to load it so we have the validation inside this class.
            engine = getattr(importlib.import_module(engine_path), cls_name)
        except ImportError:
            raise ImproperlyConfigured('Database engine doesn\'t exist!')
        except Exception as e:
            raise ImproperlyConfigured(
                'Database configuration isn\'t complete or engine could\'t be found!'
            )

        return cls(engine, instance, db_name, **db_options)
Exemple #11
0
    def _setup(self):
        """Setup will create the wrapped settings and load the settings module."""
        settings_module = os.environ.get('PYPLANET_SETTINGS_MODULE')
        if not settings_module:
            raise ImproperlyConfigured(
                'Settings module is not defined! Please define PYPLANET_SETTINGS_MODULE in your '
                'environment or start script.')

        self._settings = Settings(settings_module)
Exemple #12
0
    def load(self):
        # Make sure we load the defaults first.
        super().load()

        # Make sure we get the directory from the environment variable.
        self.directory = os.environ.get('PYPLANET_SETTINGS_DIRECTORY')

        if not self.directory:
            raise ImproperlyConfigured(
                'Settings directory is not defined! Please define PYPLANET_SETTINGS_DIRECTORY in your '
                'environment or start script (manage.py).')

        # Make directory absolute.
        self.directory = os.path.join(os.getcwd(), self.directory)

        if not os.path.exists(self.directory) or not os.path.isdir(
                self.directory):
            raise ImproperlyConfigured(
                'Settings directory does not exist or is not a directory! Please define the right PYPLANET_SETTINGS_DIRECTORY '
                'in your environment or start script (manage.py).')

        # Add the module itself to the configuration.
        self.settings['SETTINGS_DIRECTORY'] = self.directory
Exemple #13
0
    def load(self):
        # Make sure we load the defaults first.
        super().load()

        # Prepare the loading.
        self.module = os.environ.get('PYPLANET_SETTINGS_MODULE', 'settings')

        if not self.module:
            raise ImproperlyConfigured(
                'Settings module is not defined! Please define PYPLANET_SETTINGS_MODULE in your environment or start script.'
            )

        # Add the module itself to the configuration.
        self.settings['SETTINGS_MODULE'] = self.module

        # Load the module, put the settings into the local context.
        try:
            module = importlib.import_module(self.module)
        except ModuleNotFoundError as e:
            raise ImproperlyConfigured(
                'The settings module doesn\'t contain any submodules or files to load! Please make sure '
                'your settings module exist or contains the files base.py and apps.py. Your module: {}'
                .format(self.module)) from e

        # Load from the modules.
        processed = 0
        for setting in dir(module):
            if setting.isupper():
                self.settings[setting] = getattr(module, setting)
                processed += 1

        # Check for empty results.
        if processed < 1:
            raise ImproperlyConfigured(
                'The settings module doesn\'t contain any submodules or files to load! Please make sure '
                'your settings module exist or contains the files base.py and apps.py. Your module: {}'
                .format(self.module))
Exemple #14
0
    def load(self):
        # Prepare + load directory.
        super().load()

        # Load the files and parse Yaml.
        parsed_settings = dict()

        try:
            for file_name in self.files:
                file_path = os.path.join(self.directory, file_name)
                with open(file_path, 'r') as file_handle:
                    parsed_settings.update(yaml.safe_load(file_handle))
        except (yaml.YAMLError, yaml.MarkedYAMLError) as e:
            raise ImproperlyConfigured(
                'Your settings file(s) contain invalid YAML syntax! Please fix and restart!, {}'
                .format(str(e)))

        # Loop and set in local settings (+ uppercase keys).
        for key, value in parsed_settings.items():
            self.settings[key.upper()] = value
Exemple #15
0
    def load(self):
        # Prepare + load directory.
        super().load()

        # Load the files and parse JSON.
        parsed_settings = dict()

        for file_name in self.files:
            try:
                file_path = os.path.join(self.directory, file_name)
                with open(file_path, 'r') as file_handle:
                    parsed_settings.update(json.load(file_handle))
            except json.JSONDecodeError as e:
                raise ImproperlyConfigured(
                    'Your settings file(s) contain invalid JSON syntax! Please fix and restart! File {}, Error {}'
                    .format(file_name, str(e)))

        # Loop and set in local settings (+ uppercase keys).
        for key, value in parsed_settings.items():
            self.settings[key.upper()] = value
Exemple #16
0
    def load(self):
        # Make sure we load the defaults first.
        super().load()

        # Prepare the loading.
        self.module = os.environ.get('PYPLANET_SETTINGS_MODULE', 'settings')

        if not self.module:
            raise ImproperlyConfigured(
                'Settings module is not defined! Please define PYPLANET_SETTINGS_MODULE in your environment or start script.'
            )

        # Add the module itself to the configuration.
        self.settings['SETTINGS_MODULE'] = self.module

        # Load the module, put the settings into the local context.
        module = importlib.import_module(self.module)

        for setting in dir(module):
            if setting.isupper():
                self.settings[setting] = getattr(module, setting)
Exemple #17
0
    def __init__(self, process_name):
        """
		The actual instance of the controller.
		
		:param process_name: EnvironmentProcess class specific for this process.
		:type process_name: str
		"""
        # Initiate all the core components.
        self.process_name = process_name
        self.loop = asyncio.get_event_loop()
        self.game = Game

        self.gbx = GbxClient.create_from_settings(
            self, settings.DEDICATED[self.process_name])
        self.db = Database.create_from_settings(
            self, settings.DATABASES[self.process_name])
        self.storage = Storage.create_from_settings(
            self, settings.STORAGE[self.process_name])
        self.signal_manager = SignalManager
        self.ui_manager = GlobalUIManager(self)
        self.apps = Apps(self)

        # Contrib components.
        self.map_manager = MapManager(self)
        self.player_manager = PlayerManager(self)
        self.permission_manager = PermissionManager(self)
        self.command_manager = CommandManager(self)
        self.setting_manager = GlobalSettingManager(self)
        self.mode_manager = ModeManager(self)
        self.chat_manager = self.chat = ChatManager(self)

        # Populate apps.
        self.apps.populate(settings.MANDATORY_APPS, in_order=True)
        try:
            self.apps.populate(settings.APPS[self.process_name])
        except KeyError as e:
            raise ImproperlyConfigured(
                'One of the pool names doesn\'t reflect into the APPS setting! You must '
                'declare the apps per pool! ({})'.format(str(e)))