LSST Applications  21.0.0+3c14b91618,21.0.0+9f51b1e3f7,21.0.0-1-ga51b5d4+6691386486,21.0.0-10-g2408eff+2abf8e6692,21.0.0-10-g560fb7b+4d6b2593e7,21.0.0-10-gcf60f90+3282c3fba3,21.0.0-15-g490e301a+3bb30e68ef,21.0.0-2-g103fe59+2768baa6eb,21.0.0-2-g1367e85+7f080822af,21.0.0-2-g45278ab+9f51b1e3f7,21.0.0-2-g5242d73+7f080822af,21.0.0-2-g7f82c8f+c804b2348a,21.0.0-2-g8f08a60+e6fd6d9ff9,21.0.0-2-ga326454+c804b2348a,21.0.0-2-gde069b7+66c51b65da,21.0.0-2-gecfae73+7b7e4bc850,21.0.0-2-gfc62afb+7f080822af,21.0.0-20-g09baf175d+b753e4a737,21.0.0-3-g357aad2+041fbde335,21.0.0-3-g4be5c26+7f080822af,21.0.0-3-g65f322c+5f9b799490,21.0.0-3-g7d9da8d+3c14b91618,21.0.0-3-gaa929c8+4d6b2593e7,21.0.0-3-ge02ed75+8a90696ee3,21.0.0-4-g3af6bfd+6a1ffca332,21.0.0-4-g591bb35+8a90696ee3,21.0.0-4-g88306b8+fb98652b4f,21.0.0-4-gccdca77+86bf7a300d,21.0.0-4-ge8a399c+2e6fe0c655,21.0.0-46-g880d6fab+d14224996b,21.0.0-6-g2d4f3f3+9f51b1e3f7,21.0.0-6-g4e60332+8a90696ee3,21.0.0-6-g8356267+828d7849ed,21.0.0-6-gb9875a0+49236cfe85,21.0.0-7-g98eecf7+3609eddee2,21.0.0-8-g79a436f+a6e44ac77b,21.0.0-9-g2abd0ea+f5d0ba4120,master-gac4afde19b+8a90696ee3,w.2021.09
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
ItemVariant const * other
Definition: Schema.cc:56
#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:485
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.
table::Key< std::string > name
Definition: Amplifier.cc:116