lsst.afw
g3a5ebb7d8a+28b83bf6a5
Toggle main menu visibility
Loading...
Searching...
No Matches
python
lsst
afw
typehandling
_GenericMap.py
Go to the documentation of this file.
1
# This file is part of afw.
2
#
3
# Developed for the LSST Data Management System.
4
# This product includes software developed by the LSST Project
5
# (https://www.lsst.org).
6
# See the COPYRIGHT file at the top-level directory of this distribution
7
# for details of code ownership.
8
#
9
# This program is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU General Public License as published by
11
# the Free Software Foundation, either version 3 of the License, or
12
# (at your option) any later version.
13
#
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
18
#
19
# You should have received a copy of the GNU General Public License
20
# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22
__all__ = [
"GenericMap"
,
"MutableGenericMap"
]
23
24
from
collections.abc
import
Mapping, MutableMapping
25
26
from
lsst.utils
import
TemplateMeta
27
from
._typehandling
import
GenericMapS, MutableGenericMapS
28
29
30
class
GenericMap
(metaclass=TemplateMeta):
31
"""An abstract `~collections.abc.Mapping` for use when sharing a
32
map between C++ and Python.
33
34
For compatibility with C++, ``GenericMap`` has the following
35
restrictions:
36
37
- all keys must be of the same type
38
- values must be built-in types or subclasses of
39
`lsst.afw.typehandling.Storable`. Almost any user-defined class in
40
C++ or Python can have `~lsst.afw.typehandling.Storable` as a mixin.
41
42
As a safety precaution, `~lsst.afw.typehandling.Storable` objects that are
43
added from C++ may be copied when you retrieve them from Python, making it
44
impossible to modify them in-place. This issue does not affect objects that
45
are added from Python, or objects that are always passed by
46
:cpp:class:`shared_ptr` in C++.
47
"""
48
49
def
__repr__
(self):
50
className = type(self).__name__
51
return
className +
"({"
+
", "
.join(
"%r: %r"
% (key, value)
for
key, value
in
self.
items
()) +
"})"
52
53
# Support equality with any Mapping, including dict
54
# Not clear why Mapping.__eq__ doesn't work
55
def
__eq__
(self, other):
56
if
len(self) != len(other):
57
return
False
58
59
for
key, value
in
self.
items
():
60
try
:
61
if
(value != other[key]):
62
return
False
63
except
KeyError:
64
return
False
65
return
True
66
67
# Easier than making GenericMap actually inherit from Mapping
68
keys = Mapping.keys
69
values = Mapping.values
70
items = Mapping.items
71
72
73
GenericMap.register(str, GenericMapS)
74
Mapping.register(GenericMapS)
75
76
77
class
MutableGenericMap
(
GenericMap
):
78
"""An abstract `~collections.abc.MutableMapping` for use when sharing a
79
map between C++ and Python.
80
81
For compatibility with C++, ``MutableGenericMap`` has the following
82
restrictions:
83
84
- all keys must be of the same type
85
- values must be built-in types or subclasses of
86
`lsst.afw.typehandling.Storable`. Almost any user-defined class in
87
C++ or Python can have `~lsst.afw.typehandling.Storable` as a mixin.
88
89
As a safety precaution, `~lsst.afw.typehandling.Storable` objects that are
90
added from C++ may be copied when you retrieve them from Python, making it
91
impossible to modify them in-place. This issue does not affect objects that
92
are added from Python, or objects that are always passed by
93
:cpp:class:`shared_ptr` in C++.
94
95
Notes
96
-----
97
Key-type specializations of ``MutableGenericMap`` are available as, e.g.,
98
``MutableGenericMap[str]``.
99
"""
100
101
# Easier than making MutableGenericMap actually inherit from MutableMapping
102
setdefault = MutableMapping.setdefault
103
update = MutableMapping.update
104
105
# MutableMapping.pop relies on implementation details of MutableMapping
106
def
pop
(self, key, default=None):
107
try
:
108
value = self[key]
109
del self[key]
110
return
value
111
except
KeyError:
112
if
default
is
not
None
:
113
return
default
114
else
:
115
raise
116
117
118
MutableGenericMap.register(str, MutableGenericMapS)
119
MutableMapping.register(MutableGenericMapS)
120
121
122
class
AutoKeyMeta
(TemplateMeta):
123
"""A metaclass for abstract mappings whose key type is implied by their
124
constructor arguments.
125
126
This metaclass requires that the mapping have a `dict`-like constructor,
127
i.e., it takes a mapping or an iterable of key-value pairs as its first
128
positional parameter.
129
130
This class differs from `~lsst.utils.TemplateMeta` only in that the dtype
131
(or equivalent) constructor keyword is optional. If it is omitted, the
132
class will attempt to infer it from the first argument.
133
"""
134
135
def
__call__
(cls, *args, **kwargs):
# noqa N805, non-self first param
136
if
len(cls.
TEMPLATE_PARAMS
) != 1:
137
raise
ValueError(
"AutoKeyMeta requires exactly one template parameter"
)
138
dtypeKey = cls.
TEMPLATE_PARAMS
[0]
139
dtype = kwargs.get(dtypeKey,
None
)
140
141
# Try to infer dtype if not provided
142
if
dtype
is
None
and
len(args) >= 1:
143
dtype = cls.
_guessKeyType
(args[0])
144
if
dtype
is
not
None
:
145
kwargs[dtypeKey] = dtype
146
147
return
super().
__call__
(*args, **kwargs)
148
149
def
_guessKeyType
(cls, inputData):
# noqa N805, non-self first param
150
"""Try to infer the key type of a map from its input.
151
152
Parameters
153
----------
154
inputData : `~collections.abc.Mapping` or iterable of pairs
155
Any object that can be passed to a `dict`-like constructor. Keys
156
are assumed homogeneous (if not, a
157
`~lsst.afw.typehandling.GenericMap` constructor will raise
158
`TypeError` no matter what key type, if any, is provided).
159
160
Returns
161
-------
162
keyType : `type`
163
The type of the keys in ``inputData``, or `None` if the type could
164
not be inferred.
165
"""
166
if
inputData:
167
firstKey =
None
168
if
isinstance(inputData, Mapping):
169
# mapping to copy
170
firstKey = iter(inputData.keys()).__next__()
171
elif
not
isinstance(inputData, str):
172
# iterable of key-value pairs
173
try
:
174
firstKey = iter(inputData).__next__()[0]
175
except
TypeError:
176
# Not an iterable of pairs
177
pass
178
if
firstKey:
179
return
type(firstKey)
180
# Any other input is either empty or an invalid input to dict-like constructors
181
return
None
lsst::afw::typehandling._GenericMap.AutoKeyMeta
Definition
_GenericMap.py:122
lsst::afw::typehandling._GenericMap.AutoKeyMeta.__call__
__call__(cls, *args, **kwargs)
Definition
_GenericMap.py:135
lsst::afw::typehandling._GenericMap.AutoKeyMeta.TEMPLATE_PARAMS
TEMPLATE_PARAMS
Definition
_GenericMap.py:136
lsst::afw::typehandling._GenericMap.AutoKeyMeta._guessKeyType
_guessKeyType(cls, inputData)
Definition
_GenericMap.py:149
lsst::afw::typehandling._GenericMap.GenericMap
Definition
_GenericMap.py:30
lsst::afw::typehandling._GenericMap.GenericMap.__repr__
__repr__(self)
Definition
_GenericMap.py:49
lsst::afw::typehandling._GenericMap.GenericMap.items
items
Definition
_GenericMap.py:70
lsst::afw::typehandling._GenericMap.GenericMap.__eq__
__eq__(self, other)
Definition
_GenericMap.py:55
lsst::afw::typehandling._GenericMap.MutableGenericMap
Definition
_GenericMap.py:77
lsst::afw::typehandling._GenericMap.MutableGenericMap.pop
pop(self, key, default=None)
Definition
_GenericMap.py:106
collections.abc
lsst.utils
Generated on
for lsst.afw by
1.17.0