def loadPackage(self, tex: TeX, file_name: str, options: Optional[Dict] = None) -> bool: """ Load a Python or LaTeX package A Python version of the package is searched for first, if one cannot be found then a LaTeX version of the package is searched for if config['general']['load-tex-packages'] is True, or the package has been white-listed in config['general']['tex-packages']. Python versions are first searched for in the directories of config['general']['packages-dirs'], then in plugins listed in config['general']['plugins'], and then among builtin packages. Required Arguments: tex -- the instance of the TeX engine to use for parsing the LaTeX file, if needed. file_name -- the name of the file to load Keyword Arguments: options -- the options given on the macro to pass to the package Returns: boolean indicating whether or not the package loaded successfully """ config = tex.ownerDocument.config working_dir = tex.ownerDocument.userdata.get('working-dir', '') options = options or {} module = os.path.splitext(file_name)[0] # See if it has already been loaded if module in self.packages: return True packagesini = os.path.join(os.path.dirname(plasTeX.Packages.__file__), os.path.basename(module) + '.ini') imported = None orig_sys_path = sys.path for pkg_dir in config['general']['packages-dirs']: if Path(pkg_dir).is_absolute(): path = Path(pkg_dir) else: path = (Path(working_dir) / pkg_dir).absolute() pypath = (path / module).with_suffix('.py') sys.path.insert(0, str(path)) spec = find_spec(module) if spec is None: sys.path = orig_sys_path continue if (module in sys.modules and pypath.exists()): if spec.origin != str(pypath): log.warning( 'Python has already loaded a module named {} ' ' independently from plasTeX, so we cannot load ' 'it from {}. You can fix this by creating a ' 'plugin.'.format(module, pkg_dir)) break if spec.origin: # python found the module but not in the expected place, # so we give up on this package dir. continue try: imported = import_module(module) except (ImportError, ModuleNotFoundError) as msg: # Error while importing sys.path = orig_sys_path raise if imported is None: for plugin in reversed(config['general']['plugins']): sys.path = orig_sys_path plugin_module = import_module(plugin) sys.path.insert( 0, str(Path(plugin_module.__file__).parent.parent)) try: imported = import_module(plugin + '.Packages.' + module) break except (ImportError, ModuleNotFoundError) as msg: # No Python module if 'No module' in str(msg) and module in str(msg): pass # Failed to load Python package # Error while importing else: sys.path = orig_sys_path raise if imported is None: # Now try builtin plasTeX packages sys.path.insert(0, str(Path(__file__).parent.parent)) try: imported = import_module('plasTeX.Packages.' + module) except (ImportError, ModuleNotFoundError) as msg: # No Python module if 'No module' in str(msg) and module in str(msg): pass # Failed to load Python package # Error while importing else: sys.path = orig_sys_path raise sys.path = orig_sys_path if imported: status.info(' (loading package %s ' % imported.__file__) if hasattr(imported, 'ProcessOptions'): imported.ProcessOptions(options, tex.ownerDocument) # type: ignore self.importMacros(vars(imported)) moduleini = os.path.splitext(imported.__file__)[0] + '.ini' self.loadINIPackage([packagesini, moduleini]) self.packages[module] = options status.info(' ) ') return True log.warning('No Python version of %s was found' % file_name) # Try to load a LaTeX implementation if (config['general']['load-tex-packages'] or module in config['general']['tex-packages']): log.warning('Will now try to load a LaTeX implementation of %s' % file_name) result = tex.loadPackage(file_name, options) try: moduleini = os.path.join( os.path.dirname(tex.kpsewhich(file_name)), os.path.basename(module) + '.ini') self.loadINIPackage([packagesini, moduleini]) except OSError: pass return result return False
def loadPackage(self, tex: TeX, file_name: str, options: Optional[Dict] = None) -> bool: """ Load a Python or LaTeX package A Python version of the package is searched for first, if one cannot be found then a LaTeX version of the package is searched for if config['general']['load-tex-packages'] is True, or the package has been white-listed in config['general']['tex-packages']. Python versions are first searched for in the directories of config['general']['packages-dirs'], then in plugins listed in config['general']['plugins'], and this among builtin packages. Required Arguments: tex -- the instance of the TeX engine to use for parsing the LaTeX file, if needed. file_name -- the name of the file to load Keyword Arguments: options -- the options given on the macro to pass to the package Returns: boolean indicating whether or not the package loaded successfully """ config = tex.ownerDocument.config working_dir = tex.ownerDocument.userdata.get('working-dir', '') options = options or {} module = os.path.splitext(file_name)[0] # See if it has already been loaded if module in self.packages: return True packagesini = os.path.join(os.path.dirname(plasTeX.Packages.__file__), os.path.basename(module) + '.ini') imported = None for pkg_dir in config['general']['packages-dirs']: if Path(pkg_dir).is_absolute(): path = str(Path(pkg_dir)) else: path = str(Path(working_dir) / path) sys.path.insert(0, path) try: imported = import_module(module) sys.path.remove(path) break except ImportError as msg: # No Python module if 'No module' in str(msg) and module in str(msg): pass # Failed to load Python package # Error while importing else: sys.path.remove(path) raise sys.path.remove(path) if imported is None: for plugin in reversed(config['general']['plugins']): plugin_module = import_module(plugin) path = str(Path(plugin_module.__file__).parent / 'Packages') sys.path.insert(0, path) try: imported = import_module(module) sys.path.remove(path) break except ImportError as msg: # No Python module if 'No module' in str(msg) and module in str(msg): pass # Failed to load Python package # Error while importing else: sys.path.remove(path) raise sys.path.remove(path) if imported is None: # Now try builtin plasTeX packages path = str(Path(__file__).parent / 'Packages') sys.path.insert(0, path) try: imported = import_module(module) except ImportError as msg: # No Python module if 'No module' in str(msg) and module in str(msg): pass # Failed to load Python package # Error while importing else: sys.path.remove(path) raise sys.path.remove(path) if imported: status.info(' (loading package %s ' % imported.__file__) if hasattr(imported, 'ProcessOptions'): imported.ProcessOptions(options, tex.ownerDocument) # type: ignore self.importMacros(vars(imported)) moduleini = os.path.splitext(imported.__file__)[0] + '.ini' self.loadINIPackage([packagesini, moduleini]) self.packages[module] = options status.info(' ) ') return True log.warning('No Python version of %s was found' % file_name) # Try to load a LaTeX implementation if (config['general']['load-tex-packages'] or module in config['general']['tex-packages']): log.warning('Will now try to load a LaTeX implementation of %s' % file_name) result = tex.loadPackage(file_name, options) try: moduleini = os.path.join( os.path.dirname(tex.kpsewhich(file_name)), os.path.basename(module) + '.ini') self.loadINIPackage([packagesini, moduleini]) except OSError: pass return result return False