Skip to content

Commit

Permalink
Merge branch 'tickets/DM-31507'
Browse files Browse the repository at this point in the history
  • Loading branch information
natelust committed Aug 26, 2021
2 parents a51b5d4 + 616f35f commit 87000a6
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 17 deletions.
11 changes: 10 additions & 1 deletion python/lsst/pex/config/configChoiceField.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
from .comparison import getComparisonName, compareScalars, compareConfigs
from .callStack import getCallStack, getStackFrame

import weakref


class SelectionSet(collections.abc.MutableSet):
"""A mutable set class that tracks the selection of multi-select
Expand Down Expand Up @@ -65,7 +67,7 @@ def __init__(self, dict_, value, at=None, label="assignment", setHistory=True):
at = getCallStack()
self._dict = dict_
self._field = self._dict._field
self._config = self._dict._config
self._config_ = weakref.ref(self._dict._config)
self.__history = self._config._history.setdefault(self._field.name, [])
if value is not None:
try:
Expand All @@ -83,6 +85,13 @@ def __init__(self, dict_, value, at=None, label="assignment", setHistory=True):
if setHistory:
self.__history.append(("Set selection to %s" % self, at, label))

@property
def _config(self) -> Config:
# Config Fields should never outlive their config class instance
# assert that as such here
assert(self._config_() is not None)
return self._config_()

def add(self, value, at=None):
"""Add a value to the selected set.
"""
Expand Down
11 changes: 10 additions & 1 deletion python/lsst/pex/config/configurableField.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
from .comparison import compareConfigs, getComparisonName
from .callStack import getCallStack, getStackFrame

import weakref


class ConfigurableInstance:
"""A retargetable configuration in a `ConfigurableField` that proxies
Expand Down Expand Up @@ -68,7 +70,7 @@ def __initValue(self, at, label):
object.__setattr__(self, "_value", value)

def __init__(self, config, field, at=None, label="default"):
object.__setattr__(self, "_config", config)
object.__setattr__(self, "_config_", weakref.ref(config))
object.__setattr__(self, "_field", field)
object.__setattr__(self, "__doc__", config)
object.__setattr__(self, "_target", field.target)
Expand All @@ -83,6 +85,13 @@ def __init__(self, config, field, at=None, label="default"):
history = config._history.setdefault(field.name, [])
history.append(("Targeted and initialized from defaults", at, label))

@property
def _config(self) -> Config:
# Config Fields should never outlive their config class instance
# assert that as such here
assert(self._config_() is not None)
return self._config_()

target = property(lambda x: x._target)
"""The targeted configurable (read-only).
"""
Expand Down
17 changes: 9 additions & 8 deletions python/lsst/pex/config/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@
dafBase = None


def _helper(ps, prefix, dict_):
for k, v in dict_.items():
name = prefix + "." + k if prefix is not None else k
if isinstance(v, dict):
_helper(ps, name, v)
elif v is not None:
ps.set(name, v)


def makePropertySet(config):
"""Convert a configuration into a `lsst.daf.base.PropertySet`.
Expand All @@ -55,14 +64,6 @@ def makePropertySet(config):
if dafBase is None:
raise RuntimeError("lsst.daf.base is not available")

def _helper(ps, prefix, dict_):
for k, v in dict_.items():
name = prefix + "." + k if prefix is not None else k
if isinstance(v, dict):
_helper(ps, name, v)
elif v is not None:
ps.set(name, v)

if config is not None:
ps = dafBase.PropertySet()
_helper(ps, None, config.toDict())
Expand Down
15 changes: 12 additions & 3 deletions python/lsst/pex/config/dictField.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@

import collections.abc

from .config import Field, FieldValidationError, _typeStr, _autocast, _joinNamePath
from .config import Field, FieldValidationError, _typeStr, _autocast, _joinNamePath, Config
from .comparison import getComparisonName, compareScalars
from .callStack import getCallStack, getStackFrame

import weakref


class Dict(collections.abc.MutableMapping):
"""An internal mapping container.
Expand All @@ -42,7 +44,7 @@ class Dict(collections.abc.MutableMapping):

def __init__(self, config, field, value, at, label, setHistory=True):
self._field = field
self._config = config
self._config_ = weakref.ref(config)
self._dict = {}
self._history = self._config._history.setdefault(self._field.name, [])
self.__doc__ = field.doc
Expand All @@ -58,6 +60,13 @@ def __init__(self, config, field, value, at, label, setHistory=True):
if setHistory:
self._history.append((dict(self._dict), at, label))

@property
def _config(self) -> Config:
# Config Fields should never outlive their config class instance
# assert that as such here
assert(self._config_() is not None)
return self._config_()

history = property(lambda x: x._history)
"""History (read-only).
"""
Expand Down Expand Up @@ -132,7 +141,7 @@ def __setattr__(self, attr, value, at=None, label="assignment"):
if hasattr(getattr(self.__class__, attr, None), '__set__'):
# This allows properties to work.
object.__setattr__(self, attr, value)
elif attr in self.__dict__ or attr in ["_field", "_config", "_history", "_dict", "__doc__"]:
elif attr in self.__dict__ or attr in ["_field", "_config_", "_history", "_dict", "__doc__"]:
# This allows specific private attributes to work.
object.__setattr__(self, attr, value)
else:
Expand Down
17 changes: 13 additions & 4 deletions python/lsst/pex/config/listField.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@

import collections.abc

from .config import Field, FieldValidationError, _typeStr, _autocast, _joinNamePath
from .config import Field, FieldValidationError, _typeStr, _autocast, _joinNamePath, Config
from .comparison import compareScalars, getComparisonName
from .callStack import getCallStack, getStackFrame

import weakref


class List(collections.abc.MutableSequence):
"""List collection used internally by `ListField`.
Expand Down Expand Up @@ -63,7 +65,7 @@ class List(collections.abc.MutableSequence):

def __init__(self, config, field, value, at, label, setHistory=True):
self._field = field
self._config = config
self._config_ = weakref.ref(config)
self._history = self._config._history.setdefault(self._field.name, [])
self._list = []
self.__doc__ = field.doc
Expand All @@ -73,10 +75,17 @@ def __init__(self, config, field, value, at, label, setHistory=True):
self.insert(i, x, setHistory=False)
except TypeError:
msg = "Value %s is of incorrect type %s. Sequence type expected" % (value, _typeStr(value))
raise FieldValidationError(self._field, self._config, msg)
raise FieldValidationError(self._field, config, msg)
if setHistory:
self.history.append((list(self._list), at, label))

@property
def _config(self) -> Config:
# Config Fields should never outlive their config class instance
# assert that as such here
assert(self._config_() is not None)
return self._config_()

def validateItem(self, i, x):
"""Validate an item to determine if it can be included in the list.
Expand Down Expand Up @@ -204,7 +213,7 @@ def __setattr__(self, attr, value, at=None, label="assignment"):
if hasattr(getattr(self.__class__, attr, None), '__set__'):
# This allows properties to work.
object.__setattr__(self, attr, value)
elif attr in self.__dict__ or attr in ["_field", "_config", "_history", "_list", "__doc__"]:
elif attr in self.__dict__ or attr in ["_field", "_config_", "_history", "_list", "__doc__"]:
# This allows specific private attributes to work.
object.__setattr__(self, attr, value)
else:
Expand Down

0 comments on commit 87000a6

Please sign in to comment.