28__all__ = (
"Registry",
"makeRegistry",
"RegistryField",
"registerConfig",
"registerConfigurable")
33from .config
import Config, FieldValidationError, _typeStr
34from .configChoiceField
import ConfigChoiceField, ConfigInstanceDict
38 """A wrapper for configurables.
40 Used for configurables that don
't contain a ``ConfigClass`` attribute,
41 or contain one that
is being overridden.
49 return self.
_target(*args, **kwargs)
53 """A base class for global registries, which map names to configurables.
55 A registry acts like a read-only dictionary with an additional `register`
56 method to add targets. Targets
in the registry are configurables (see
62 The base
class for config classes in the registry.
66 A configurable
is a callable
with call signature ``(config, *args)``
67 Configurables typically create an algorithm
or are themselves the
68 algorithm. Often configurables are `lsst.pipe.base.Task` subclasses, but
71 A ``Registry`` has these requirements:
73 - All configurables added to a particular registry have the same call
75 - All configurables
in a registry typically share something important
76 in common. For example, all configurables
in ``psfMatchingRegistry``
77 return a PSF matching
class that has
a ``psfMatch`` method
with a
78 particular call signature.
82 This examples creates a configurable
class ``Foo``
and adds it to a
83 registry. First, creating the configurable:
86 >>>
class FooConfig(
Config):
87 ... val =
Field(dtype=int, default=3, doc=
"parameter for Foo")
90 ... ConfigClass = FooConfig
92 ... self.config = config
93 ...
def addVal(self, num):
94 ...
return self.config.val + num
97 Next, create a ``Registry`` instance called ``registry``
and register the
98 ``Foo`` configurable under the ``
"foo"`` key:
101 >>> registry.register(
"foo", Foo)
102 >>> print(
list(registry.keys()))
105 Now ``Foo``
is conveniently accessible
from the registry itself.
107 Finally, use the registry to get the configurable
class and create an
110 >>> FooConfigurable = registry[
"foo"]
111 >>> foo = FooConfigurable(FooConfigurable.ConfigClass())
117 if not issubclass(configBaseType, Config):
119 "configBaseType=%s must be a subclass of Config"
127 def register(self, name, target, ConfigClass=None):
128 """Add a new configurable target to the registry.
133 Name that the ``target`` is registered under. The target can
134 be accessed later
with `dict`-like patterns using ``name``
as
137 A configurable type, usually a subclass of `lsst.pipe.base.Task`.
140 configurable. If `
None` then the configurable
's ``ConfigClass``
146 Raised
if an item
with ``name``
is already
in the registry.
148 Raised
if ``ConfigClass``
is `
None`
and ``target`` does
not have
149 a ``ConfigClass`` attribute.
153 If ``ConfigClass``
is provided then the ``target`` configurable
is
154 wrapped
in a new object that forwards function calls to it. Otherwise
155 the original ``target``
is stored.
157 if name
in self.
_dict:
158 raise RuntimeError(
"An item with name %r already exists" % name)
159 if ConfigClass
is None:
165 "ConfigClass=%s is not a subclass of %r"
168 self.
_dict[name] = wrapper
171 return self.
_dict[key]
174 return len(self.
_dict)
177 return iter(self.
_dict)
180 return key
in self.
_dict
182 def makeField(self, doc, default=None, optional=False, multi=False, on_none=None):
183 """Create a `RegistryField` configuration field from this registry.
188 A description of the field.
189 default : object, optional
190 The default target for the field.
191 optional : `bool`, optional
192 When `
False`, `lsst.pex.config.Config.validate` fails
if the
193 field
's value is `None`.
194 multi : `bool`, optional
195 A flag to allow multiple selections in the `RegistryField`
if
197 on_none: `Callable`, optional
198 A callable that should be invoked when ``apply``
is called but the
199 selected name
or names
is `
None`. Will be passed the field
200 attribute proxy (`RegistryInstanceDict`)
and then all positional
201 and keyword arguments passed to ``apply``.
208 return RegistryField(doc, self, default, optional, multi, on_none=on_none)
212 """Private class that makes a `Registry` behave like the thing a
217 registry : `Registry`
238 """Dictionary of instantiated configs, used to populate a `RegistryField`.
243 Configuration instance.
244 field : `RegistryField`
249 ConfigInstanceDict.__init__(self, config, field)
259 target = property(_getTarget)
268 targets = property(_getTargets)
271 """Call the active target(s) with the active config as a keyword arg.
275 selection : `str` or `~collections.abc.Iterable` [ `str` ]
276 Name
or names of targets, depending on whether ``multi=
True``.
278 Additional arguments will be passed on to the configurable
284 If this
is a single-selection field, the
return value
from calling
285 the target. If this
is a multi-selection field, a list thereof.
289 return self.
_field_field._on_none(self, *args, **kwargs)
290 msg =
"No selection has been made. Options: %s" %
" ".join(self.
typestypes.registry.keys())
295 """Call named target(s) with the corresponding config as a keyword
300 selection : `str` or `~collections.abc.Iterable` [ `str` ]
301 Name
or names of targets, depending on whether ``multi=
True``.
303 Additional arguments will be passed on to the configurable
309 If this
is a single-selection field, the
return value
from calling
310 the target. If this
is a multi-selection field, a list thereof.
314 This method ignores the current selection
in the ``name``
or ``names``
315 attribute, which
is usually
not what you want. This method
is most
316 useful
in ``on_none`` callbacks provided at field construction, which
317 allow a context-dependent default to be used when no selection
is
323 retvals.append(self.
typestypes.registry[c](*args, config=self[c], **kwargs))
326 return self.
typestypes.registry[selection](*args, config=self[selection], **kwargs)
329 if attr ==
"registry":
330 object.__setattr__(self, attr, value)
332 ConfigInstanceDict.__setattr__(self, attr, value)
336 """A configuration field whose options are defined in a `Registry`.
341 A description of the field.
342 registry : `Registry`
343 The registry that contains this field.
344 default : `str`, optional
345 The default target key.
346 optional : `bool`, optional
347 When `False`, `lsst.pex.config.Config.validate` fails
if the field
's
349 multi : `bool`, optional
350 If `
True`, the field allows multiple selections. The default
is
352 on_none: `Callable`, optional
353 A callable that should be invoked when ``apply``
is called but the
354 selected name
or names
is `
None`. Will be passed the field attribute
355 proxy (`RegistryInstanceDict`)
and then all positional
and keyword
356 arguments passed to ``apply``.
371 instanceDictClass = RegistryInstanceDict
372 """Class used to hold configurable instances in the field.
375 def __init__(self, doc, registry, default=None, optional=False, multi=False, on_none=None):
379 ConfigChoiceField.__init__(self, doc, types, default, optional, multi)
382 """Customize deep-copying, want a reference to the original registry.
384 WARNING: this must be overridden by subclasses if they change the
385 constructor signature!
390 default=copy.deepcopy(self.default),
395 other.source = self.source
399def makeRegistry(doc, configBaseType=Config):
400 """Create a `Registry`.
405 Docstring for the created `Registry` (this
is set
as the ``__doc__``
406 attribute of the `Registry` instance.
408 Base type of config classes
in the `Registry`.
412 registry : `Registry`
413 Registry
with ``__doc__``
and ``_configBaseType`` attributes
416 cls = type("Registry", (Registry,), {
"__doc__": doc})
417 return cls(configBaseType=configBaseType)
421 """Add a class as a configurable in a `Registry` instance.
426 Name of the target (the decorated class)
in the ``registry``.
427 registry : `Registry`
428 The `Registry` instance that the decorated
class is added
to.
430 Config
class associated with the configurable. If `
None`, the
class's
431 ``ConfigClass`` attribute is used instead.
439 Internally, this decorator runs `Registry.register`.
443 registry.register(name, target=cls, ConfigClass=ConfigClass)
450 """Add a class as a ``ConfigClass`` in a `Registry` and
451 associate it with the given configurable.
456 Name of the ``target``
in the ``registry``.
457 registry : `Registry`
458 The registry containing the ``target``.
460 A configurable type, such
as a subclass of `lsst.pipe.base.Task`.
468 Internally, this decorator runs `Registry.register`.
472 registry.register(name, target=target, ConfigClass=cls)
__init__(self, target, ConfigClass)
__call__(self, *args, **kwargs)
__init__(self, doc, registry, default=None, optional=False, multi=False, on_none=None)
makeField(self, doc, default=None, optional=False, multi=False, on_none=None)
__init__(self, configBaseType=Config)
__setattr__(self, attr, value)
apply_with(self, selection, *args, **kwargs)
__init__(self, config, field)
apply(self, *args, **kwargs)
daf::base::PropertyList * list
registerConfigurable(name, registry, ConfigClass=None)
registerConfig(name, registry, target)