LSST Applications  21.0.0+c4f5df5339,21.0.0+e70536a077,21.0.0-1-ga51b5d4+7c60f8a6ea,21.0.0-10-g560fb7b+411cd868f8,21.0.0-10-gcf60f90+8c49d86aa0,21.0.0-13-gc485e61d+38156233bf,21.0.0-16-g7a993c7b9+1041c3824f,21.0.0-2-g103fe59+d9ceee3e5a,21.0.0-2-g1367e85+0b2f7db15a,21.0.0-2-g45278ab+e70536a077,21.0.0-2-g5242d73+0b2f7db15a,21.0.0-2-g7f82c8f+feb9862f5e,21.0.0-2-g8f08a60+9c9a9cfcc8,21.0.0-2-ga326454+feb9862f5e,21.0.0-2-gde069b7+bedfc5e1fb,21.0.0-2-gecfae73+417509110f,21.0.0-2-gfc62afb+0b2f7db15a,21.0.0-3-g21c7a62+a91f7c0b59,21.0.0-3-g357aad2+062581ff1a,21.0.0-3-g4be5c26+0b2f7db15a,21.0.0-3-g65f322c+85aa0ead76,21.0.0-3-g7d9da8d+c4f5df5339,21.0.0-3-gaa929c8+411cd868f8,21.0.0-3-gc44e71e+fd4029fd48,21.0.0-3-ge02ed75+5d9b90b8aa,21.0.0-38-g070523fc+44fda2b515,21.0.0-4-g591bb35+5d9b90b8aa,21.0.0-4-g88306b8+3cdc83ea97,21.0.0-4-gc004bbf+d52368b591,21.0.0-4-gccdca77+a5c54364a0,21.0.0-5-g7ebb681+81e2098694,21.0.0-5-gdf36809+87b8d260e6,21.0.0-6-g2d4f3f3+e70536a077,21.0.0-6-g4e60332+5d9b90b8aa,21.0.0-6-g5ef7dad+3f4e29eeae,21.0.0-7-gc8ca178+0f5e56d48f,21.0.0-9-g9eb8d17+cc2c7a81aa,master-gac4afde19b+5d9b90b8aa,w.2021.07
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.