| 589 | |
| 590 | |
| 591 | class ExtsManager(importlib.abc.MetaPathFinder): |
| 592 | __slots__ = ["exts", "all_specs"] |
| 593 | |
| 594 | GPLV2_LICENCES = [ |
| 595 | "GPL-2.0-only", |
| 596 | "GPL-2.0-or-later", |
| 597 | ] |
| 598 | |
| 599 | def __init__(self): |
| 600 | self.exts: List[ScapyExt] = [] |
| 601 | self.all_specs: Dict[str, ScapyExt.ScapyExtSpec] = {} |
| 602 | self._loaded: List[str] = [] |
| 603 | # Add to meta_path as we are an import provider |
| 604 | if self not in sys.meta_path: |
| 605 | sys.meta_path.append(self) |
| 606 | |
| 607 | def find_spec(self, fullname, path, target=None): |
| 608 | if fullname in self.all_specs: |
| 609 | return self.all_specs[fullname].spec |
| 610 | |
| 611 | def invalidate_caches(self): |
| 612 | pass |
| 613 | |
| 614 | def _register_spec(self, spec): |
| 615 | # Register to known specs |
| 616 | self.all_specs[spec.fullname] = spec |
| 617 | |
| 618 | # If default=True, inject it in the currently loaded modules |
| 619 | if spec.default: |
| 620 | loader = importlib.util.LazyLoader(spec.spec.loader) |
| 621 | spec.spec.loader = loader |
| 622 | module = importlib.util.module_from_spec(spec.spec) |
| 623 | sys.modules[spec.fullname] = module |
| 624 | loader.exec_module(module) |
| 625 | |
| 626 | def load(self, extension: str): |
| 627 | """ |
| 628 | Load a scapy extension. |
| 629 | |
| 630 | :param extension: the name of the extension, as installed. |
| 631 | """ |
| 632 | if extension in self._loaded: |
| 633 | return |
| 634 | |
| 635 | try: |
| 636 | import importlib.metadata |
| 637 | except ImportError: |
| 638 | log_loading.warning( |
| 639 | "'%s' not loaded. " |
| 640 | "Scapy extensions require at least Python 3.8+ !" % extension |
| 641 | ) |
| 642 | return |
| 643 | |
| 644 | # Get extension distribution |
| 645 | try: |
| 646 | distr = importlib.metadata.distribution(extension) |
| 647 | except importlib.metadata.PackageNotFoundError: |
| 648 | log_loading.warning("The extension '%s' was not found !" % extension) |