LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
python.h
Go to the documentation of this file.
1 /*
2  * This file is part of afw.
3  *
4  * Developed for the LSST Data Management System.
5  * This product includes software developed by the LSST Project
6  * (https://www.lsst.org).
7  * See the COPYRIGHT file at the top-level directory of this distribution
8  * for details of code ownership.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <https://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef LSST_AFW_TYPEHANDLING_PYTHON_H
25 #define LSST_AFW_TYPEHANDLING_PYTHON_H
26 
27 #include "pybind11/pybind11.h"
28 
29 #include <string>
30 
36 
37 namespace lsst {
38 namespace afw {
39 namespace typehandling {
40 
53 template <class Base = Storable>
54 class StorableHelper : public Base {
55 public:
56  using Base::Base;
57 
70  template<typename... Args>
71  explicit StorableHelper<Base>(Args... args) : Base(args...) {}
72 
74  /* __deepcopy__ takes an optional dict, but PYBIND11_OVERLOAD_* won't
75  * compile unless you give it arguments that work for the C++ method
76  */
77  PYBIND11_OVERLOAD_NAME(std::shared_ptr<Storable>, Base, "__deepcopy__", cloneStorable, );
78  }
79 
80  std::string toString() const override {
81  PYBIND11_OVERLOAD_NAME(std::string, Base, "__repr__", toString, );
82  }
83 
84  std::size_t hash_value() const override {
85  PYBIND11_OVERLOAD_NAME(std::size_t, Base, "__hash__", hash_value, );
86  }
87 
88  bool equals(Storable const& other) const noexcept override {
89  PYBIND11_OVERLOAD_NAME(bool, Base, "__eq__", equals, other);
90  }
91 
92  bool isPersistable() const noexcept override {
93  PYBIND11_OVERLOAD(
94  bool, Base, isPersistable
95  );
96  }
97 
98  std::string getPersistenceName() const override {
99  PYBIND11_OVERLOAD_NAME(
100  std::string, Base, "_getPersistenceName", getPersistenceName
101  );
102  }
103 
104  std::string getPythonModule() const override {
105  PYBIND11_OVERLOAD_NAME(
106  std::string, Base, "_getPythonModule", getPythonModule
107  );
108  }
109 
110  void write(table::io::OutputArchiveHandle& handle) const override;
111 };
112 
113 std::string declareGenericMapRestrictions(std::string const& className, std::string const& keyName);
114 
130 namespace {
131 
132 class StorableHelperPersistenceHelper {
133 public:
134  table::Schema schema;
135  table::Key<table::Array<std::uint8_t>> bytes;
136 
137  static StorableHelperPersistenceHelper const &get() {
138  static StorableHelperPersistenceHelper instance;
139  return instance;
140  }
141 
142  // No copying
143  StorableHelperPersistenceHelper(StorableHelperPersistenceHelper const &) = delete;
144  StorableHelperPersistenceHelper &operator=(StorableHelperPersistenceHelper const &) = delete;
145 
146  // No moving
147  StorableHelperPersistenceHelper(StorableHelperPersistenceHelper &&) = delete;
148  StorableHelperPersistenceHelper &operator=(StorableHelperPersistenceHelper &&) = delete;
149 
150 private:
151  StorableHelperPersistenceHelper() :
152  schema(),
153  bytes(schema.addField<table::Array<std::uint8_t>>(
154  "bytes", "an opaque bytestring representation of a Storable", ""
155  ))
156  {}
157 };
158 
159 
160 class StorableHelperFactory : public table::io::PersistableFactory {
161 public:
162  StorableHelperFactory(std::string const &module, std::string const &name) :
163  table::io::PersistableFactory(name),
164  _module(module),
165  _name(name)
166  {}
167 
169  InputArchive const &archive,
170  CatalogVector const &catalogs
171  ) const override {
172  pybind11::gil_scoped_acquire gil;
173  auto const &keys = StorableHelperPersistenceHelper::get();
174  LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
175  LSST_ARCHIVE_ASSERT(catalogs.front().size() == 1u);
176  LSST_ARCHIVE_ASSERT(catalogs.front().getSchema() == keys.schema);
177  auto const &record = catalogs.front().front();
178  std::string stringRep = formatters::bytesToString(record.get(keys.bytes));
179  auto cls = pybind11::module::import(_module.c_str()).attr(_name.c_str());
180  auto pyobj = cls.attr("_read")(pybind11::bytes(stringRep));
181  return pyobj.cast<std::shared_ptr<Storable>>();
182  }
183 
184 private:
185  std::string _module;
186  std::string _name;
187 };
188 
189 } // namespace
190 
191 
192 template <typename Base>
194  pybind11::gil_scoped_acquire gil;
195  pybind11::function overload = pybind11::get_overload(static_cast<const Base *>(this), "_write");
196  if (!overload)
197  throw std::runtime_error("Cannot find StorableHelper _write overload");
198  auto o = overload().cast<std::string>();
199  auto const &keys = StorableHelperPersistenceHelper::get();
200  table::BaseCatalog cat = handle.makeCatalog(keys.schema);
202  record->set(keys.bytes, formatters::stringToBytes(o));
203  handle.saveCatalog(cat);
204 }
205 
206 } // namespace typehandling
207 } // namespace afw
208 } // namespace lsst
209 
210 #endif
table::Key< std::string > name
Definition: Amplifier.cc:116
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
table::Schema schema
Definition: python.h:134
table::Key< table::Array< std::uint8_t > > bytes
Definition: python.h:135
T c_str(T... args)
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
Definition: Catalog.h:490
An object passed to Persistable::write to allow it to persist itself.
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
"Trampoline" for Storable to let it be used as a base class in Python.
Definition: python.h:54
std::string toString() const override
Create a string representation of this object (optional operation).
Definition: python.h:80
std::shared_ptr< Storable > cloneStorable() const override
Create a new object that is a copy of this one (optional operation).
Definition: python.h:73
std::size_t hash_value() const override
Return a hash of this object (optional operation).
Definition: python.h:84
bool isPersistable() const noexcept override
Return true if this particular object can be persisted using afw::table::io.
Definition: python.h:92
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
Definition: python.h:98
std::string getPythonModule() const override
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
Definition: python.h:104
bool equals(Storable const &other) const noexcept override
Compare this object to another Storable.
Definition: python.h:88
void write(table::io::OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: python.h:193
Interface supporting iteration over heterogenous containers.
Definition: Storable.h:58
ndarray::Array< std::uint8_t, 1, 1 > stringToBytes(std::string const &str)
Encode a std::string as a vector of uint8.
Definition: Utils.cc:161
std::string bytesToString(ndarray::Array< std::uint8_t const, 1, 1 > const &bytes)
Decode a std::string from a vector of uint8 returned by stringToBytes.
Definition: Utils.cc:172
FilterProperty & operator=(FilterProperty const &)=default
std::string declareGenericMapRestrictions(std::string const &className, std::string const &keyName)
Definition: python.cc:32
A base class for image defects.
STL namespace.
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override
Definition: warpExposure.cc:0