Source code for pyunity.window

## Copyright (c) 2020-2022 The PyUnity Team
## This file is licensed under the MIT License.
## See https://docs.pyunity.x10.bz/en/latest/license.html

"""
A module used to load the window providers.

The window is provided by one of three
providers: GLFW, PySDL2 and GLUT.
When you first import PyUnity, it checks
to see if any of the three providers
work. The testing order is as above, so
GLUT is tested last.

To create your own provider, create a
class that has the following methods:

- ``__init__``: initiate your window and
    check to see if it works.
- ``start``: start the main loop in your
    window. The first parameter is
    ``updateFunc``, which is called
    when you want to do the OpenGL calls.

Check the source code of any of the window
providers for an example. If you have a
window provider, then please create a new
pull request.

"""

__all__ = ["GetWindowProvider", "SetWindowProvider",
           "CustomWindowProvider", "ABCWindow"]

from .providers import getProviders
from .abc import ABCWindow
from ..errors import PyUnityException
from .. import Logger
from .. import config
from .. import settings
import os
import fnmatch
import importlib.util

[docs]def GetWindowProvider(): """Gets an appropriate window provider to use""" if os.environ["PYUNITY_INTERACTIVE"] != "1": Logger.LogLine(Logger.DEBUG, "Using no window provider") return None if "windowProvider" in settings.db and os.environ["PYUNITY_CHECK_WINDOW"] == "0": env = os.getenv("PYUNITY_WINDOW_PROVIDER") if env is not None: env = env.split(",") use = settings.db["windowProvider"] in env[0] else: use = True if use: if "windowCache" in settings.db: del settings.db["windowCache"] Logger.LogLine(Logger.DEBUG, "Detected settings.json entry") providerName = settings.db["windowProvider"] if providerName in getProviders(): module = importlib.import_module(f".providers.{providerName}", __name__) name = module.name Logger.LogLine( Logger.DEBUG, "Using window provider", name) try: module = importlib.import_module(f".providers.{providerName}.window", __name__) return module.Window except Exception as e: Logger.LogLine( Logger.WARN, "Window provider loading failed") Logger.LogLine( Logger.WARN, type(e).__name__ + ":", str(e)) Logger.LogLine( Logger.WARN, "Selecting new window provider") else: Logger.LogLine(Logger.WARN, f"settings.json entry {providerName!r} is " f"not a valid window provider, removing") settings.db.pop("windowProvider") env = os.getenv("PYUNITY_WINDOW_PROVIDER") providers = getProviders() if env is not None: newProviders = [] env = env.split(",") for specified in env: if specified.isspace() or not specified: continue specified = specified.rstrip().lstrip() added = False for item in providers: if item not in newProviders: if fnmatch.fnmatch(item.lower(), specified.lower()): added = True newProviders.append(item) if not added: Logger.LogLine(Logger.WARN, "PYUNITY_WINDOW_PROVIDER environment variable contains", repr(specified), "but no window provider matches") continue if len(newProviders) == 0: Logger.Log("Available window providers:", " ".join(providers)) raise PyUnityException("No matching window providers found") providers = newProviders elif len(providers) == 0: raise PyUnityException("No window providers installed") windowProvider = "" module = importlib.import_module(f".providers.{providers[0]}", __name__) Logger.LogLine(Logger.DEBUG, "Trying", module.name, "as a window provider") for i, name in enumerate(providers): try: module.check() windowProvider = name except Exception as e: if isinstance(e, ImportError): Logger.LogLine(Logger.WARN, name + ": This window manager requires a " "package that you haven't installed.") Logger.LogLine(Logger.WARN, name + ": Check the source code and use `pip install` " "to resolve any missing dependencies.") if i == len(providers) - 1: Logger.LogLine(Logger.DEBUG, module.name, "doesn't work") break else: newModule = importlib.import_module(f".providers.{providers[i+1]}", __name__) Logger.LogLine(Logger.DEBUG, module.name, "doesn't work, trying", newModule.name) module = newModule if windowProvider: break if not windowProvider: if env is not None: raise PyUnityException(f"No matching window provider found") else: raise PyUnityException(f"No window provider found") settings.db["windowProvider"] = windowProvider settings.db["windowCache"] = True module = importlib.import_module(f".providers.{windowProvider}", __name__) Logger.LogLine(Logger.DEBUG, "Using window provider", module.name) try: module = importlib.import_module(f".providers.{windowProvider}.window", __name__) except Exception: Logger.LogLine(Logger.WARN, "windowCache entry has been set, indicating " "window checking happened on this import") Logger.LogLine( Logger.WARN, "settings.json entry may be faulty, removing") settings.db.pop("windowProvider") raise return module.Window
[docs]def SetWindowProvider(name): providers = getProviders() if name not in providers: raise PyUnityException(f"No window provider named {name!r} found") module = importlib.import_module(f".providers.{name}", __name__) exc = None try: module.check() except Exception as e: if isinstance(e, ImportError): Logger.LogLine(Logger.WARN, name + ": This window manager requires on a package " "you don't have installed.") Logger.LogLine(Logger.WARN, name + ": Check the source code and use `pip install` " "to resolve any missing dependencies.") exc = e if exc is not None: raise PyUnityException(f"Cannot use window provider {module.name!r}") Logger.LogLine(Logger.DEBUG, "Using window provider", module.name) module = importlib.import_module(f".providers.{name}.window", __name__) config.windowProvider = module.Window return module.Window
[docs]def CustomWindowProvider(cls): if not isinstance(cls, type): raise PyUnityException("Provided window provider is not a class") if not issubclass(cls, ABCWindow): raise PyUnityException( "Provided window provider does not subclass Window.ABCWindow") Logger.LogLine(Logger.DEBUG, "Using window provider", cls.__name__) config.windowProvider = cls return cls