LSST Applications  21.0.0-1-g8760c09+64c1bc5aa5,21.0.0-1-ga51b5d4+9915f4c1f0,21.0.0-111-gf06e6c5c+fee76ed8f6,21.0.0-14-g3bd782b+25c619aa25,21.0.0-17-gd94932e+0bf297642c,21.0.0-2-g103fe59+ccc08e5a44,21.0.0-2-g45278ab+64c1bc5aa5,21.0.0-2-g5242d73+7a03d65b13,21.0.0-2-g7f82c8f+cb30300d2e,21.0.0-2-gde069b7+4f46bdaea8,21.0.0-2-gfc62afb+7a03d65b13,21.0.0-20-g1e553c2+8d8bef21d9,21.0.0-20-g3b2d1f0+b95b9e7887,21.0.0-21-g51ee50f4+27a29155c2,21.0.0-21-gc8894c7+552aca6dca,21.0.0-27-gcbf119a+71dcc0c312,21.0.0-3-g1b65d06+c212a16cbd,21.0.0-3-g357aad2+6b2f77ef8c,21.0.0-3-g4a4ce7f+7a03d65b13,21.0.0-3-g4be5c26+7a03d65b13,21.0.0-3-ge02ed75+552aca6dca,21.0.0-3-gf9d8b05+cb30300d2e,21.0.0-30-g727f315e+692e5d6c44,21.0.0-4-g7dab645+80ff539b09,21.0.0-45-g119a6608a+532d44eec1,21.0.0-5-g5f8d297+a12ef938c8,21.0.0-5-g8c1d971+7e5b4c34a6,21.0.0-5-gcc89fd6+b18c5f6b76,21.0.0-5-gd00fb1e+cabc0fa2dc,21.0.0-6-g1930a60+b18c5f6b76,21.0.0-6-gc54ca17+f4e773f57d,21.0.0-6-gc675373+7a03d65b13,21.0.0-7-g0503b2e+18535a8d22,21.0.0-7-g7aa11f2+552aca6dca,21.0.0-7-gdf92d54+64c1bc5aa5,21.0.0-9-g7058be7+2d726afa20,master-ga86695c5c8+552aca6dca,master-gcc5351303a+ccc08e5a44,w.2021.25
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:486
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:162
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:173
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.