mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
New panda3d.* import structure
This commit is contained in:
parent
cb3edda46d
commit
8f83314ae3
202
direct/src/ffi/panda3d.py
Normal file
202
direct/src/ffi/panda3d.py
Normal file
@ -0,0 +1,202 @@
|
||||
#!/bin/true
|
||||
import os, sys, imp
|
||||
|
||||
panda3d_modules = {
|
||||
"core" :("libpandaexpress", "libpanda"),
|
||||
"physics" : "libpandaphysics",
|
||||
"fx" : "libpandafx",
|
||||
"direct" : "libp3direct",
|
||||
"skel" : "libpandaskel",
|
||||
"egg" : "libpandaegg",
|
||||
"ode" : "libpandaode",
|
||||
}
|
||||
|
||||
class panda3d_import_manager:
|
||||
# Important: store a reference to the sys and os modules, as
|
||||
# all references in the global namespace will be reset.
|
||||
os = os
|
||||
sys = sys
|
||||
imp = imp
|
||||
|
||||
# Figure out the dll suffix (commonly, _d for windows debug builds),
|
||||
# and the dll extension.
|
||||
dll_suffix = ''
|
||||
dll_exts = ('.pyd', '.so')
|
||||
if sys.platform == "win32":
|
||||
dll_exts = ('.pyd', '.dll')
|
||||
|
||||
# We allow the caller to preload dll_suffix into the sys module.
|
||||
dll_suffix = getattr(sys, 'dll_suffix', None)
|
||||
|
||||
if dll_suffix is None:
|
||||
# Otherwise, we try to determine it from the executable name:
|
||||
# python_d.exe implies _d across the board.
|
||||
dll_suffix = ''
|
||||
if sys.executable.endswith('_d.exe'):
|
||||
dll_suffix = '_d'
|
||||
|
||||
# On OSX, extension modules can be loaded from either .so or .dylib.
|
||||
if sys.platform == "darwin":
|
||||
dll_exts = ('.pyd', '.so', '.dylib')
|
||||
|
||||
prepared = False
|
||||
|
||||
@classmethod
|
||||
def __prepare(cls):
|
||||
# This method only needs to be called once.
|
||||
if cls.prepared:
|
||||
return
|
||||
cls.prepared = True
|
||||
|
||||
# First, we must ensure that the library path is
|
||||
# modified to locate all of the dynamic libraries.
|
||||
target = None
|
||||
filename = "libpandaexpress" + cls.dll_suffix
|
||||
if cls.sys.platform == "win32":
|
||||
filename += "_d"
|
||||
for dir in cls.sys.path + [cls.sys.prefix]:
|
||||
lib = cls.os.path.join(dir, filename)
|
||||
for dll_ext in cls.dll_exts:
|
||||
if (cls.os.path.exists(lib + dll_ext)):
|
||||
target = dir
|
||||
break
|
||||
if target == None:
|
||||
message = "Cannot find %s" % (filename)
|
||||
raise ImportError, message
|
||||
target = cls.os.path.abspath(target)
|
||||
|
||||
# And add that directory to the system library path.
|
||||
if cls.sys.platform == "win32":
|
||||
cls.__prepend_to_path("PATH", target)
|
||||
else:
|
||||
cls.__prepend_to_path("LD_LIBRARY_PATH", target)
|
||||
|
||||
if cls.sys.platform == "darwin":
|
||||
cls.__prepend_to_path("DYLD_LIBRARY_PATH", target)
|
||||
|
||||
@classmethod
|
||||
def __prepend_to_path(cls, varname, target):
|
||||
""" Prepends the given directory to the
|
||||
specified search path environment variable. """
|
||||
|
||||
# Get the current value
|
||||
if varname in cls.os.environ:
|
||||
path = cls.os.environ[varname].strip(cls.os.pathsep)
|
||||
else:
|
||||
path = ""
|
||||
|
||||
# Prepend our value, if it's not already the first thing
|
||||
if len(path) == 0:
|
||||
cls.os.environ[varname] = target
|
||||
elif not path.startswith(target):
|
||||
cls.os.environ[varname] = target + cls.os.pathsep + path
|
||||
|
||||
@classmethod
|
||||
def libimport(cls, name):
|
||||
""" Imports and returns the specified library name. The
|
||||
provided library name has to be without dll extension. """
|
||||
|
||||
if not cls.prepared: cls.__prepare()
|
||||
|
||||
# Try to import it normally first.
|
||||
try:
|
||||
return __import__(name)
|
||||
except ImportError, err:
|
||||
if str(err) != "No module named " + name:
|
||||
raise
|
||||
|
||||
# Hm, importing normally didn't work. Let's try imp.load_dynamic.
|
||||
# But first, locate the desired library.
|
||||
target = None
|
||||
filename = name + cls.dll_suffix
|
||||
for dir in cls.sys.path + [cls.sys.prefix]:
|
||||
lib = cls.os.path.join(dir, filename)
|
||||
for dll_ext in cls.dll_exts:
|
||||
if (cls.os.path.exists(lib + dll_ext)):
|
||||
target = lib + dll_ext
|
||||
break
|
||||
if target == None:
|
||||
message = "DLL loader cannot find %s." % name
|
||||
raise ImportError, message
|
||||
target = cls.os.path.abspath(target)
|
||||
|
||||
# Now import the file explicitly.
|
||||
return cls.imp.load_dynamic(name, target)
|
||||
|
||||
class panda3d_submodule(type(sys)):
|
||||
""" Represents a submodule of 'panda3d' that represents a dynamic
|
||||
library. This dynamic library is loaded when something is accessed
|
||||
from the module. """
|
||||
|
||||
__manager__ = panda3d_import_manager
|
||||
|
||||
def __init__(self, name, library):
|
||||
type(sys).__init__(self, "panda3d." + name)
|
||||
self.__library__ = library
|
||||
self.__libraries__ = [self.__library__]
|
||||
|
||||
def __getattr__(self, name):
|
||||
mod = self.__manager__.libimport(self.__library__)
|
||||
if name == "__all__":
|
||||
return dir(mod)
|
||||
elif name in dir(mod):
|
||||
return mod.__dict__[name]
|
||||
|
||||
# Not found? Raise the error that Python would normally raise.
|
||||
raise AttributeError, "'module' object has no attribute '%s'" % name
|
||||
|
||||
class panda3d_multisubmodule(type(sys)):
|
||||
""" Represents a submodule of 'panda3d' that represents multiple
|
||||
dynamic libraries. These are loaded when something is accessed
|
||||
from the module. """
|
||||
|
||||
__manager__ = panda3d_import_manager
|
||||
|
||||
def __init__(self, name, libraries):
|
||||
type(sys).__init__(self, "panda3d." + name)
|
||||
self.__libraries__ = libraries
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name == "__all__":
|
||||
everything = []
|
||||
for lib in self.__libraries__:
|
||||
everything += dir(self.__manager__.libimport(self.__libraries__))
|
||||
|
||||
for lib in self.__libraries__:
|
||||
mod = self.__manager__.libimport(lib)
|
||||
if name in dir(mod):
|
||||
return mod.__dict__[name]
|
||||
|
||||
# Not found? Raise the error that Python would normally raise.
|
||||
raise AttributeError, "'module' object has no attribute '%s'" % name
|
||||
|
||||
class panda3d_module(type(sys)):
|
||||
""" Represents the main 'panda3d' module. """
|
||||
|
||||
modules = panda3d_modules
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name == "__all__":
|
||||
return self.modules.keys()
|
||||
elif name in self.modules:
|
||||
return sys.modules["panda3d.%s" % name]
|
||||
|
||||
# Not found? Raise the error that Python would normally raise.
|
||||
raise AttributeError, "'module' object has no attribute '%s'" % name
|
||||
|
||||
# Create the fake module objects and insert them into sys.modules.
|
||||
this = panda3d_module("panda3d")
|
||||
|
||||
# Loop through the module dictionary, create a fake
|
||||
# module for each of them, and insert them into
|
||||
# sys.modules and into the 'panda3d' fake module.
|
||||
for mod, lib in panda3d_modules.items():
|
||||
if isinstance(lib, tuple):
|
||||
module = panda3d_multisubmodule(mod, lib)
|
||||
else:
|
||||
module = panda3d_submodule(mod, lib)
|
||||
sys.modules["panda3d." + mod] = module
|
||||
this.__dict__[mod] = module
|
||||
|
||||
# Important: this must be the last thing in this file
|
||||
sys.modules["panda3d"] = this
|
Loading…
x
Reference in New Issue
Block a user