示例#1
0
def test_load():
    ep = entrypoints.EntryPoint('get_ep', 'entrypoints', 'get_single', None)
    obj = ep.load()
    assert obj is entrypoints.get_single

    # The object part is optional (e.g. pytest plugins use just a module ref)
    ep = entrypoints.EntryPoint('ep_mod', 'entrypoints', None)
    obj = ep.load()
    assert obj is entrypoints
示例#2
0
 def from_conf(self):
     return [
         entrypoints.EntryPoint(name=k,
                                module_name=v.rsplit(":", 1)[0]
                                if ":" in v else v.rsplit(".", 1)[0],
                                object_name=v.rsplit(":", 1)[1]
                                if ":" in v else v.rsplit(".", 1)[1])
         for k, v in self.conf.get("drivers", {}).items() if v
     ]
示例#3
0
class TestFailedToLoadPlugin(_ExceptionTest):
    """Tests for the FailedToLoadPlugin exception."""

    err = exceptions.FailedToLoadPlugin(
        plugin=plugins_manager.Plugin(
            'plugin_name',
            entrypoints.EntryPoint('plugin_name', 'os.path', None),
        ),
        exception=ValueError('boom!'),
    )
示例#4
0
    def register(self, target_name, plugin_module):
        """
        Register a deployment client given its target name and module

        :param target_name: The name of the deployment target. This name will be used by
                            `get_deploy_client()` to retrieve a deployment client from
                            the plugin store
        :param plugin_module: The module that implements the deployment plugin interface
        """
        self.registry[target_name] = entrypoints.EntryPoint(
            target_name, plugin_module, None)
示例#5
0
    def test_cannot_getattr_bad(self):
        self.setup_entry(entrypoints.EntryPoint('bad', 'really_bad', ''))
        assert 'bad' in dir(bio)
        assert 'bad' in bio.FORMATS
        with pytest.raises(AttributeError, match='not loadable'):
            bio.bad

        assert 'bad' not in dir(bio)
        assert 'bad' not in bio.FORMATS
        with pytest.raises(AttributeError, match='has no attribute'):
            bio.bad
示例#6
0
 def test_find_new(self):
     self.setup_entry(entrypoints.EntryPoint('new', 'baseband.vdif', ''))
     assert 'new' in dir(bio)
     assert 'new' in bio.FORMATS
     assert bio.new is vdif
     # Check that it comes back if we remove it from the module.
     bio.__dict__.pop('new', None)
     assert 'new' not in bio.__dict__
     assert 'new' in bio.FORMATS
     assert 'new' in dir(bio)
     assert bio.new is vdif
示例#7
0
 def test_fake_bad_vdif(self):
     assert bio.vdif is vdif
     del bio.vdif
     bio._entries['vdif'] = entrypoints.EntryPoint('vdif', 'bad.vdif', '')
     with pytest.raises(AttributeError, match='not loadable'):
         bio.vdif
     assert 'vdif' not in dir(bio)
     assert 'vdif' in bio._bad_entries
     # Does not auto-reload since already known as bad.
     with pytest.raises(AttributeError, match='has no attribute'):
         bio.vdif
     # But will reload if we reload and thus start over.
     reload(bio)
     assert bio.vdif is vdif
     assert 'vdif' in bio.FORMATS
示例#8
0
def __getattr__(attr):
    """Get a missing attribute from a possible entry point.

    Looks for the attribute among the (possibly updated) entry points,
    and, if found, tries loading the entry.  If that fails, the entry
    is added to _bad_entries to ensure it does not recur.
    """
    if attr.startswith('_') or attr in _bad_entries:
        raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")

    FORMATS = globals().setdefault('FORMATS', [])
    if attr not in _entries:
        if not _entries:
            # On initial update, we add our own formats as explicit entries,
            # in part to set some order, but also so things work even in a
            # pure source checkout, where entry points are missing.
            _entries.update({
                fmt: entrypoints.EntryPoint(fmt, 'baseband.'+fmt, '')
                for fmt in ('dada', 'guppi', 'mark4', 'mark5b', 'vdif', 'gsb')
            })

        _entries.update(entrypoints.get_group_named('baseband.io'))
        FORMATS.extend([name for name, entry in _entries.items()
                        if not (entry.object_name or name in FORMATS)])
        if attr == 'FORMATS':
            return FORMATS

    entry = _entries.get(attr, None)
    if entry is None:
        raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")

    try:
        value = entry.load()
    except Exception:
        _entries.pop(attr)
        _bad_entries.add(attr)
        if attr in FORMATS:
            FORMATS.remove(attr)
        raise AttributeError(f"{entry} was not loadable. Now removed")

    # Update so we do not have to go through __getattr__ again.
    globals()[attr] = value
    return value
示例#9
0
def autodiscover(path=None, plugin_prefix='intake_', do_package_scan=False):
    r"""Discover intake drivers.

    In order of decreasing precedence:

    - Respect the 'drivers' section of the intake configuration file.
    - Find 'intake.drivers' entrypoints provided by any Python packages in the
      environment.
    - Search all packages in the environment for names that begin with
      ``intake\_``. Import them and scan them for subclasses of
      ``intake.source.base.DataSourceBase``. This was previously the *only* mechanism
      for auto-discoverying intake drivers, and it is maintained for backward
      compatibility.

    Parameters
    ----------
    path : str or None
        Default is ``sys.path``.
    plugin_prefix : str
        DEPRECATED. Default is 'intake\_'.
    do_package_scan : boolean
        Whether to look for intake source classes in packages named
        "intake_*". This has been superceded by entrypoints declarations.

    Returns
    -------
    drivers : dict
        Name mapped to driver class.
    """
    # Discover drivers via package scan.
    if do_package_scan:
        package_scan_results = _package_scan(path, plugin_prefix)
        if package_scan_results:
            warnings.warn(
                "The option `do_package_scan` may be removed in a future release.",
                PendingDeprecationWarning)
    else:
        package_scan_results = {}

    # Discover drivers via entrypoints.
    group = entrypoints.get_group_named('intake.drivers', path=path)
    group_all = entrypoints.get_group_all('intake.drivers', path=path)
    if len(group_all) != len(group):
        # There are some name collisions. Let's go digging for them.
        for name, matches in itertools.groupby(group_all, lambda ep: ep.name):
            matches = list(matches)
            if len(matches) != 1:
                winner = group[name]
                logger.debug(
                    "There are %d 'intake.driver' entrypoints for the name "
                    "%r. They are %r. The match %r has won the race.",
                    len(matches),
                    name,
                    matches,
                    winner)

    for name, entrypoint in group.items():
        logger.debug("Discovered entrypoint '%s = %s.%s'",
                     name,
                     entrypoint.module_name,
                     entrypoint.object_name)
        if name in package_scan_results:
            cls = package_scan_results[name]
            del package_scan_results[name]
            logger.debug("Entrypoint shadowed package_scan result '%s = %s.%s'",
                         name, cls.__module__, cls.__name__)

    # Discover drivers via config.
    drivers_conf = conf.get('drivers', {})
    logger.debug("Using configuration file at %s", cfile())
    for name, dotted_object_name in drivers_conf.items():
        if not dotted_object_name:
            logger.debug('Name %s is banned in config file', name)
            if name in group:
                entrypoint = group[name]
                del group[name]
                logger.debug("Disabled entrypoint '%s = %s.%s'",
                             entrypoint.name,
                             entrypoint.module_name,
                             entrypoint.object_name)
            if name in package_scan_results:
                cls = package_scan_results[name]
                del package_scan_results[name]
                logger.debug("Disabled package_scan result '%s = %s.%s'",
                             name, cls.__module__, cls.__name__)
            continue
        module_name, object_name = dotted_object_name.rsplit('.', 1)
        entrypoint = entrypoints.EntryPoint(name, module_name, object_name)
        logger.debug("Discovered config-specified '%s = %s.%s'",
                     entrypoint.name,
                     entrypoint.module_name,
                     entrypoint.object_name)
        if name in group:
            shadowed = group[name]
            logger.debug("Config shadowed entrypoint '%s = %s.%s'",
                         shadowed.name,
                         shadowed.module_name,
                         shadowed.object_name)
        if name in package_scan_results:
            cls = package_scan_results[name]
            del package_scan_results[name]
            logger.debug("Config shadowed package scan result '%s = %s.%s'",
                         name, cls.__module__, cls.__name__)
        group[name] = entrypoint

    # Discovery is complete.

    if package_scan_results:
        warnings.warn(
            f"The drivers {list(package_scan_results)} do not specify entry_"
            f"points and were only discovered via a package scan. This may "
            f"break in a future release of intake. The packages should be "
            f"updated.",
            FutureWarning)

    # Load entrypoints. Any that were shadowed or banned have already been
    # removed above.
    drivers = {}
    for entrypoint in group.values():
        try:
            drivers[entrypoint.name] = _load_entrypoint(entrypoint)
        except ConfigurationError:
            logger.exception(
                "Error while loading entrypoint %s",
                entrypoint.name)
            continue
        logger.debug("Loaded entrypoint '%s = %s.%s'",
                     entrypoint.name,
                     entrypoint.module_name,
                     entrypoint.object_name)

    # Now include any package scan results. Any that were shadowed or
    # banned have already been removed above.
    for name, cls in package_scan_results.items():
        drivers[name] = cls
        logger.debug("Loaded package scan result '%s = %s.%s'",
                     name,
                     cls.__module__,
                     cls.__name__)

    return drivers
示例#10
0
def autodiscover_all(path=None, plugin_prefix='intake_', do_package_scan=True):
    """Discover intake drivers including those registered for the same name.

    Parameters
    ----------
    path : str or None
        Default is ``sys.path``.
    plugin_prefix : str
        DEPRECATED. Default is 'intake_'.
    do_package_scan : boolean
        Default is True. In the future, the default will be changed to False,
        and the option may eventually be removed entirely.

    Returns
    -------
    drivers : list
        Each entry is a tuple: ``(name, driver_class)``.
    """
    # Discover drivers via package scan.
    if do_package_scan:
        warnings.warn(
            "The option `do_package_scan` may be removed in a future release.",
            PendingDeprecationWarning)
        package_scan_results = _package_scan(path, plugin_prefix)
    else:
        package_scan_results = {}

    # Discover drivers via entrypoints.
    group_all = entrypoints.get_group_all('intake.drivers', path=path)
    for entrypoint in group_all:
        logger.debug("Discovered entrypoint '%s = %s.%s'",
                     entrypoint.name,
                     entrypoint.module_name,
                     entrypoint.object_name)

    # Discover drivers via config.
    drivers_conf = conf.get('drivers', {})
    logger.debug("Using configuration file at %s", cfile())
    for name, dotted_object_name in drivers_conf.items():
        if not dotted_object_name:
            continue
        module_name, object_name = dotted_object_name.rsplit('.', 1)
        entrypoint = entrypoints.EntryPoint(name, module_name, object_name)
        logger.debug("Discovered config-specified '%s = %s.%s'",
                     entrypoint.name,
                     entrypoint.module_name,
                     entrypoint.object_name)
        group_all.append(entrypoint)

    # Load entrypoints. Any that were shadowed or banned have already been
    # removed above.
    drivers = []
    for entrypoint in group_all:
        try:
            drivers.append((entrypoint.name, _load_entrypoint(entrypoint)))
        except ConfigurationError:
            logger.exception(
                "Error while loading entrypoint %s",
                entrypoint.name)
            continue
        logger.debug("Loaded entrypoint '%s = %s.%s'",
                     entrypoint.name,
                     entrypoint.module_name,
                     entrypoint.object_name)

    # Now include any package scan results. Any that were shadowed or
    # banned have already been removed above.
    for name, cls in package_scan_results.items():
        drivers.append((name, cls))
        logger.debug("Loaded package scan result '%s = %s.%s'",
                     name,
                     cls.__module__,
                     cls.__name__)

    return drivers
示例#11
0
 def test_not_hasattr_bad(self):
     self.setup_entry(entrypoints.EntryPoint('bad', 'really_bad', ''))
     assert 'bad' in dir(bio)
     assert not hasattr(bio, 'bad')
     assert 'bad' not in dir(bio)