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):
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
207 """Private class that makes a `Registry` behave like the thing a
212 registry : `Registry`
233 """Dictionary of instantiated configs, used to populate a `RegistryField`.
238 Configuration instance.
239 field : `RegistryField`
244 ConfigInstanceDict.__init__(self, config, field)
247 def _getTarget(self):
250 self.
_field, self.
_config,
"Multi-selection field has no attribute 'target'"
254 target = property(_getTarget)
256 def _getTargets(self):
259 self.
_field, self.
_config,
"Single-selection field has no attribute 'targets'"
263 targets = property(_getTargets)
266 """Call the active target(s) with the active config as a keyword arg
268 If this is a multi-selection field,
return a list obtained by calling
269 each active target
with its corresponding active config.
271 Additional arguments will be passed on to the configurable
target(s)
274 msg =
"No selection has been made. Options: %s" %
" ".join(self.
types.registry.keys())
279 retvals.append(self.
types.registry[c](*args, config=self[c], **kw))
282 return self.
types.registry[self.
name](*args, config=self[self.
name], **kw)
285 if attr ==
"registry":
286 object.__setattr__(self, attr, value)
288 ConfigInstanceDict.__setattr__(self, attr, value)
292 """A configuration field whose options are defined in a `Registry`.
297 A description of the field.
298 registry : `Registry`
299 The registry that contains this field.
300 default : `str`, optional
301 The default target key.
302 optional : `bool`, optional
303 When `False`, `lsst.pex.config.Config.validate` fails
if the field
's
305 multi : `bool`, optional
306 If `
True`, the field allows multiple selections. The default
is
322 instanceDictClass = RegistryInstanceDict
323 """Class used to hold configurable instances in the field.
326 def __init__(self, doc, registry, default=None, optional=False, multi=False):
329 ConfigChoiceField.__init__(self, doc, types, default, optional, multi)
332 """Customize deep-copying, want a reference to the original registry.
334 WARNING: this must be overridden by subclasses if they change the
335 constructor signature!
340 default=copy.deepcopy(self.default),
344 other.source = self.source
348def makeRegistry(doc, configBaseType=Config):
349 """Create a `Registry`.
354 Docstring for the created `Registry` (this
is set
as the ``__doc__``
355 attribute of the `Registry` instance.
357 Base type of config classes
in the `Registry`
358 (`lsst.pex.config.Registry.configBaseType`).
362 registry : `Registry`
363 Registry
with ``__doc__``
and `~Registry.configBaseType` attributes
366 cls = type("Registry", (Registry,), {
"__doc__": doc})
367 return cls(configBaseType=configBaseType)
371 """A decorator that adds a class as a configurable in a `Registry`
377 Name of the target (the decorated class)
in the ``registry``.
378 registry : `Registry`
379 The `Registry` instance that the decorated
class is added
to.
381 Config
class associated with the configurable. If `
None`, the
class's
382 ``ConfigClass`` attribute is used instead.
390 Internally, this decorator runs `Registry.register`.
394 registry.register(name, target=cls, ConfigClass=ConfigClass)
401 """Decorator that adds a class as a ``ConfigClass`` in a `Registry` and
402 associates it with the given configurable.
407 Name of the ``target``
in the ``registry``.
408 registry : `Registry`
409 The registry containing the ``target``.
411 A configurable type, such
as a subclass of `lsst.pipe.base.Task`.
419 Internally, this decorator runs `Registry.register`.
423 registry.register(name, target=target, ConfigClass=cls)
def __init__(self, target, ConfigClass)
def __call__(self, *args, **kwargs)
def __contains__(self, k)
def __init__(self, registry)
def __init__(self, doc, registry, default=None, optional=False, multi=False)
def __deepcopy__(self, memo)
def __contains__(self, key)
def makeField(self, doc, default=None, optional=False, multi=False)
def __getitem__(self, key)
def __init__(self, configBaseType=Config)
def apply(self, *args, **kw)
def __init__(self, config, field)
def __setattr__(self, attr, value)
daf::base::PropertyList * list
def registerConfigurable(name, registry, ConfigClass=None)
def registerConfig(name, registry, target)