test_Loader.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. from panda3d.core import Filename, NodePath, LoaderFileTypeRegistry
  2. from direct.showbase.Loader import Loader
  3. import pytest
  4. import sys
  5. @pytest.fixture
  6. def loader():
  7. return Loader(base=None)
  8. @pytest.fixture
  9. def temp_model():
  10. from panda3d.core import ModelPool, ModelRoot
  11. root = ModelRoot('model')
  12. root.fullpath = '/test-model.bam'
  13. ModelPool.add_model(root.fullpath, root)
  14. yield root.fullpath
  15. ModelPool.release_model(root.fullpath)
  16. def test_load_model_filename(loader, temp_model):
  17. model = loader.load_model(Filename(temp_model))
  18. assert model
  19. assert isinstance(model, NodePath)
  20. assert model.name == 'model'
  21. def test_load_model_str(loader, temp_model):
  22. model = loader.load_model(str(temp_model))
  23. assert model
  24. assert isinstance(model, NodePath)
  25. assert model.name == 'model'
  26. def test_load_model_list(loader, temp_model):
  27. models = loader.load_model([temp_model, temp_model])
  28. assert models
  29. assert isinstance(models, list)
  30. assert len(models) == 2
  31. assert isinstance(models[0], NodePath)
  32. assert isinstance(models[1], NodePath)
  33. def test_load_model_tuple(loader, temp_model):
  34. models = loader.load_model((temp_model, temp_model))
  35. assert models
  36. assert isinstance(models, list)
  37. assert len(models) == 2
  38. assert isinstance(models[0], NodePath)
  39. assert isinstance(models[1], NodePath)
  40. def test_load_model_set(loader, temp_model):
  41. models = loader.load_model({temp_model})
  42. assert models
  43. assert isinstance(models, list)
  44. assert len(models) == 1
  45. assert isinstance(models[0], NodePath)
  46. def test_load_model_missing(loader):
  47. with pytest.raises(IOError):
  48. loader.load_model('/nonexistent.bam')
  49. def test_load_model_okmissing(loader):
  50. model = loader.load_model('/nonexistent.bam', okMissing=True)
  51. assert model is None
  52. def test_loader_entry_points(tmpdir):
  53. # A dummy loader for .fnrgl files.
  54. tmpdir.join("fnargle.py").write("""
  55. from panda3d.core import ModelRoot
  56. import sys
  57. sys._fnargle_loaded = True
  58. class FnargleLoader:
  59. name = "Fnargle"
  60. extensions = ['fnrgl']
  61. supports_compressed = False
  62. @staticmethod
  63. def load_file(path, options, record=None):
  64. return ModelRoot("fnargle")
  65. """)
  66. tmpdir.join("fnargle.dist-info").mkdir()
  67. tmpdir.join("fnargle.dist-info", "METADATA").write("""
  68. Metadata-Version: 2.0
  69. Name: fnargle
  70. Version: 1.0.0
  71. """)
  72. tmpdir.join("fnargle.dist-info", "entry_points.txt").write("""
  73. [panda3d.loaders]
  74. fnrgl = fnargle:FnargleLoader
  75. """)
  76. model_path = tmpdir.join("test.fnrgl")
  77. model_path.write("")
  78. if sys.version_info >= (3, 11):
  79. import sysconfig
  80. stdlib = sysconfig.get_path("stdlib")
  81. platstdlib = sysconfig.get_path("platstdlib")
  82. else:
  83. from distutils import sysconfig
  84. stdlib = sysconfig.get_python_lib(False, True)
  85. platstdlib = sysconfig.get_python_lib(True, True)
  86. if sys.version_info < (3, 8):
  87. # Older Python versions don't have importlib.metadata, so we rely on
  88. # pkg_resources - but this caches the results once. Fortunately, it
  89. # provides this function for reinitializing the cached entry points.
  90. # See pypa/setuptools#373
  91. pkg_resources = pytest.importorskip("pkg_resources")
  92. if not hasattr(pkg_resources, "_initialize_master_working_set"):
  93. pytest.skip("pkg_resources too old")
  94. registry = LoaderFileTypeRegistry.get_global_ptr()
  95. prev_loaded = Loader._loadedPythonFileTypes
  96. prev_path = sys.path
  97. file_type = None
  98. try:
  99. # We do this so we don't re-register thirdparty loaders
  100. sys.path = [str(tmpdir), platstdlib, stdlib]
  101. if sys.version_info < (3, 8):
  102. pkg_resources._initialize_master_working_set()
  103. Loader._loadedPythonFileTypes = False
  104. # base parameter is only used for audio
  105. loader = Loader(None)
  106. assert Loader._loadedPythonFileTypes
  107. if sys.version_info < (3, 8):
  108. # pkg_resources relies on things in site-packages (_markerlib)
  109. sys.path += [sysconfig.get_python_lib(True, False), sysconfig.get_python_lib(False, False)]
  110. # Should be registered, not yet loaded
  111. file_type = registry.get_type_from_extension('fnrgl')
  112. assert file_type is not None
  113. assert not hasattr(sys, '_fnargle_loaded')
  114. assert file_type.supports_load()
  115. assert not file_type.supports_save()
  116. assert not file_type.supports_compressed()
  117. assert file_type.get_extension() == 'fnrgl'
  118. # The above should have caused it to load
  119. assert sys._fnargle_loaded
  120. assert 'fnargle' in sys.modules
  121. # Now try loading a fnargle file
  122. model_fn = Filename.from_os_specific(str(model_path))
  123. model_fn.make_true_case()
  124. model = loader.load_model(model_fn, noCache=True)
  125. assert model is not None
  126. assert model.name == "fnargle"
  127. finally:
  128. # Set everything back to what it was
  129. Loader._loadedPythonFileTypes = prev_loaded
  130. sys.path = prev_path
  131. if hasattr(sys, '_fnargle_loaded'):
  132. del sys._fnargle_loaded
  133. if 'fnargle' in sys.modules:
  134. del sys.modules['fnargle']
  135. if file_type is not None:
  136. registry.unregister_type(file_type)
  137. if sys.version_info < (3, 8):
  138. pkg_resources._initialize_master_working_set()