NCBI C++ ToolKit
pythonpp_object.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: pythonpp_object.hpp 81119 2018-02-05 17:07:29Z ucko $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Sergey Sikorskiy
27 *
28 * File Description: Tiny Python API wrappers
29 *
30 * Status: *Initial*
31 *
32 * ===========================================================================
33 */
34 
35 #ifndef PYTHONPP_OBJECT_H
36 #define PYTHONPP_OBJECT_H
37 
38 #include "pythonpp_error.hpp"
39 
41 
42 namespace pythonpp
43 {
44  bool g_CleaningUp = false;
45 
46 #if PY_VERSION_HEX >= 0x02050000
47  typedef Py_ssize_t py_ssize_t;
48 #else
49  typedef int py_ssize_t;
50 #endif
51 
54 
55 class CType;
56 class CString;
57 
58 // Strong-typed operation ...
59 inline PyObject* IncRefCount(PyObject* obj)
60 {
61  if ( !g_CleaningUp ) {
62  Py_INCREF(obj); // NCBI_FAKE_WARNING
63  }
64  return obj;
65 }
66 inline PyObject* DecRefCount(PyObject* obj)
67 {
68  if ( !g_CleaningUp ) {
69  Py_DECREF(obj);
70  }
71  return obj;
72 }
73 
74 // PyObject
75 // PyVarObject
76 class CObject
77 {
78 // ???
79 ///* Generic operations on objects */
80 //PyAPI_FUNC(CInt) PyObject_Print(PyObject *, FILE *, int);
81 //PyAPI_FUNC(void) _PyObject_Dump(PyObject *);
82 //#ifdef Py_USING_UNICODE
83 //PyAPI_FUNC(PyObject *) PyObject_Unicode(PyObject *);
84 //#endif
85 //PyAPI_FUNC(PyObject *) PyObject_RichCompare(PyObject *, PyObject *, int);
86 //PyAPI_FUNC(CInt) PyObject_RichCompareBool(PyObject *, PyObject *, int);
87 //PyAPI_FUNC(PyObject *) PyObject_GetAttr(PyObject *, PyObject *);
88 //PyAPI_FUNC(CInt) PyObject_HasAttr(PyObject *, PyObject *);
89 //PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *);
90 //PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *);
91 //PyAPI_FUNC(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *);
92 //PyAPI_FUNC(CInt) PyObject_GenericSetAttr(PyObject *,
93 // PyObject *, PyObject *);
94 //PyAPI_FUNC(CInt) PyObject_Not(PyObject *);
95 //PyAPI_FUNC(CInt) PyCallable_Check(PyObject *);
96 //PyAPI_FUNC(CInt) PyNumber_Coerce(PyObject **, PyObject **);
97 //PyAPI_FUNC(CInt) PyNumber_CoerceEx(PyObject **, PyObject **);
98 
99 //PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *);
100 
101 ///* A slot function whose address we need to compare */
102 //extern int _PyObject_SlotCompare(PyObject *, PyObject *);
103 
104 public:
105 
106 public:
107  /// Creates a python None object
108  CObject(void)
109  : m_PyObject(Py_None)
110  // , m_Ownership(eOwned)
111  {
112  IncRefCount(Get());
113  }
114  explicit CObject(PyObject* obj, EOwnership ownership = eAcquireOwnership)
115  : m_PyObject(obj)
116  // , m_Ownership(eAcquireOwnership ? eAcquired : eOwned) // !!! Currently this parameter does not much value of "ownership"
117  {
118  _ASSERT(Get());
119  if ( ownership == eAcquireOwnership ) {
120  IncRefCount(Get());
121  }
122  }
123  CObject(const CObject& obj)
124  : m_PyObject(obj)
125  // , m_Ownership(eOwned)
126  {
127  _ASSERT(Get());
128  IncRefCount(Get());
129  }
130  ~CObject(void)
131  {
132  Release();
133  }
134 
136  {
137  if (this != &obj)
138  {
139  Set(obj);
140  }
141  return *this;
142  }
143 
144  CObject& operator= (PyObject* obj)
145  {
146  if (Get() != obj) {
147  Set (obj);
148  }
149  return *this;
150  }
151 
152 public:
153  // Implicit conversion to the PyObject* type
154  operator PyObject* (void) const
155  {
156  return m_PyObject;
157  }
158  PyObject* Get(void) const
159  {
160  return m_PyObject;
161  }
162  /// Not exception-safe this time
163  void Set(PyObject* obj, EOwnership ownership = eAcquireOwnership)
164  {
165  _ASSERT(obj);
166 
167  Release();
168  m_PyObject = obj;
169  if ( ownership == eAcquireOwnership )
170  {
171  IncRefCount(*this);
172  }
173  }
174  void Release(void)
175  {
176  // PyAPI_FUNC(void) IncRefCount(PyObject *);
177  // PyAPI_FUNC(void) Py_DecRef(PyObject *);
178  if ( !g_CleaningUp ) {
179  Py_XDECREF(m_PyObject); // NCBI_FAKE_WARNING
180  }
181  m_PyObject = NULL;
182  }
183 
184 public:
185  // Atributes ...
186  CObject GetAttr (const std::string& name) const
187  {
188  PyObject* obj = PyObject_GetAttrString(Get(), const_cast<char*>(name.c_str()));
189  if ( !obj ) {
190  throw CAttributeError("Attribute does not exist");
191  }
192  return CObject(obj, eTakeOwnership);
193  }
194  void SetAttr(const std::string& name, const CObject& value)
195  {
196  if(PyObject_SetAttrString (Get(), const_cast<char*>(name.c_str()), value.Get()) == -1) {
197  throw CAttributeError("SetAttr failed");
198  }
199  }
200  void DelAttr (const std::string& name)
201  {
202  if(PyObject_DelAttrString (Get(), const_cast<char*>(name.c_str())) == -1) {
203  throw CAttributeError("DelAttr failed");
204  }
205  }
206  bool HasAttr (const std::string& name) const
207  {
208  return PyObject_HasAttrString (Get(), const_cast<char*>(name.c_str())) != 0;
209  }
210 
211 public:
212  // Itemss ...
213  CObject GetItem (const CObject& key) const
214  {
215  PyObject* obj = PyObject_GetItem(Get(), key.Get());
216  if ( !obj ) {
217  throw CKeyError("Item does not exist");
218  }
219  return CObject(obj, eTakeOwnership);
220  }
221  /* Do not delete this ...
222  void SetItem(const CObject& key, const CObject& value)
223  {
224  if(PyObject_SetItem (Get(), key.Get(), value.Get()) == -1) {
225  throw CKeyError ("SetItem failed");
226  }
227  }
228  */
229  void DelItem (const CObject& key)
230  {
231  if(PyObject_DelItem (Get(), key.Get()) == -1) {
232  throw CKeyError ("DelItem failed");
233  }
234  }
235 
236 public:
237  long GetHashValue (void) const
238  {
239  long value = PyObject_Hash (Get());
240 
241  if ( value == -1) {
242  throw CSystemError("Invalid hash value");
243  }
244  return value;
245  }
246 
247 public:
248  // There's really no reason to use this function instead of the common
249  // expression m_PyObject->ob_type, which returns a pointer of type PyTypeObject*,
250  // except when the incremented reference count is needed.
251  CType GetType(void) const;
252  PyTypeObject* GetObjType(void) const
253  {
254  return m_PyObject->ob_type;
255  }
256  // CString GetString(void) const;
257  // CString GetRepresentation() const;
258  // std::string as_string(void) const;
259 
260 public:
261  // Equality and comparison based on PyObject_Compare
262  bool operator==(const CObject& obj) const
263  {
264  CObject result(PyObject_RichCompare(Get(), obj, Py_EQ),
266  CError::Check();
267  return PyObject_IsTrue(result);
268  }
269  bool operator!=(const CObject& obj) const
270  {
271  CObject result(PyObject_RichCompare(Get(), obj, Py_NE),
273  CError::Check();
274  return PyObject_IsTrue(result);
275  }
276  bool operator>=(const CObject& obj) const
277  {
278  CObject result(PyObject_RichCompare(Get(), obj, Py_GE),
280  CError::Check();
281  return PyObject_IsTrue(result);
282  }
283  bool operator<=(const CObject& obj) const
284  {
285  CObject result(PyObject_RichCompare(Get(), obj, Py_LE),
287  CError::Check();
288  return PyObject_IsTrue(result);
289  }
290  bool operator<(const CObject& obj) const
291  {
292  CObject result(PyObject_RichCompare(Get(), obj, Py_LT),
294  CError::Check();
295  return PyObject_IsTrue(result);
296  }
297  bool operator>(const CObject& obj) const
298  {
299  CObject result(PyObject_RichCompare(Get(), obj, Py_GT),
301  CError::Check();
302  return PyObject_IsTrue(result);
303  }
304 
305 protected:
306  bool IsNumeric (void) const
307  {
308  return PyNumber_Check (Get()) != 0;
309  }
310  bool IsSequence (void) const
311  {
312  return PySequence_Check (Get()) != 0;
313  }
314  bool IsTrue (void) const
315  {
316  return PyObject_IsTrue (Get()) != 0;
317  }
318  bool IsObjectType (const CType& t) const;
319 
320 private:
321  PyObject* m_PyObject;
322  // EOwnershipFuture m_Ownership;
323 };
324 
325 class CNone : public CObject
326 {
327 public:
328  CNone(void)
329  : CObject(Py_None)
330  {
331  }
332  CNone(const CObject& obj)
333  : CObject(obj)
334  {
335  if ( !HasExactSameType(obj) ) {
336  throw CTypeError("Invalid conversion");
337  }
338  }
339 
340  CNone& operator= (const CNone& obj)
341  {
342  if ( this != &obj) {
343  Set(obj);
344  }
345  return *this;
346  }
347  CNone& operator= (const CObject& obj)
348  {
349  if ( this != &obj) {
350  if ( !HasExactSameType(obj) ) {
351  throw CTypeError("Invalid conversion");
352  }
353  Set(obj);
354  }
355  return *this;
356  }
357 
358 public:
359  static bool HasSameType(PyObject* obj)
360  {
361  // Py_None is an object of undefined type ...
362  // So, we can compare only objects themelf ...
363  return obj == Py_None;
364  }
365  static bool HasExactSameType(PyObject* obj)
366  {
367  // Py_None is an object of undefined type ...
368  // So, we can compare only objects themelf ...
369  return obj == Py_None;
370  }
371 };
372 
373 // PyTypeObject
374 // PyHeapTypeObject
375 class CType : public CObject
376 {
377 // int PyType_HasFeature( PyObject *o, int feature)
378 // int PyType_IS_GC( PyObject *o)
379 // int PyType_IsSubtype( PyTypeObject *a, PyTypeObject *b)
380 // PyAPI_FUNC(PyObject *) PyType_GenericAlloc(PyTypeObject *, int);
381 // PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *, PyObject *, PyObject *);
382 // PyAPI_FUNC(CInt) PyType_Ready(PyTypeObject *);
383 
384 public:
385  CType(PyObject* obj, EOwnership ownership = eAcquireOwnership)
386  : CObject(obj, ownership)
387  {
388  }
389  CType(const CObject& obj)
390  : CObject(obj)
391  {
392  if ( !HasExactSameType(obj) ) {
393  throw CTypeError("Invalid conversion");
394  }
395  }
396  CType(const CType& obj)
397  : CObject(obj)
398  {
399  }
400 
401  CType& operator= (const CObject& obj)
402  {
403  if ( this != &obj) {
404  if ( !HasExactSameType(obj) ) {
405  throw CTypeError("Invalid conversion");
406  }
407  Set(obj);
408  }
409  return *this;
410  }
411 
412  CType& operator= (PyObject* obj)
413  {
414  if ( Get() != obj ) {
415  Set(obj);
416  }
417  return *this;
418  }
419 
420 public:
421  static bool HasSameType(PyObject* obj)
422  {
423  return PyType_Check (obj);
424  }
425  static bool HasExactSameType(PyObject* obj)
426  {
427  return PyType_CheckExact (obj);
428  }
429 };
430 
431 inline
432 bool operator ==(const CType& l, const CType& r)
433 {
434  return l.Get() == r.Get();
435 }
436 
437 ///////////////////////////////////////////////////////////////////////////
438 // Numeric interface
439 inline CObject operator+ (const CObject& a)
440 {
441  PyObject* tmp_obj = PyNumber_Positive(a.Get());
442  if ( !tmp_obj ) {
443  throw CArithmeticError("PyNumber_Positive");
444  }
445  return CObject(tmp_obj, eTakeOwnership);
446 }
447 inline CObject operator- (const CObject& a)
448 {
449  PyObject* tmp_obj = PyNumber_Negative(a.Get());
450  if ( !tmp_obj ) {
451  throw CArithmeticError("PyNumber_Negative");
452  }
453  return CObject(tmp_obj, eTakeOwnership);
454 }
455 
456 inline CObject abs(const CObject& a)
457 {
458  PyObject* tmp_obj = PyNumber_Absolute(a.Get());
459  if ( !tmp_obj ) {
460  throw CArithmeticError("PyNumber_Absolute");
461  }
462  return CObject(tmp_obj, eTakeOwnership);
463 }
464 
465 #if 0
466 inline std::pair<CObject, CObject> coerce(const CObject& a, const CObject& b)
467 {
468  PyObject* p1;
469  PyObject* p2;
470  p1 = a.Get();
471  p2 = b.Get();
472  if(PyNumber_Coerce(&p1, &p2) == -1) {
473  throw CArithmeticError("PyNumber_Coerce");
474  }
475  return std::pair<CObject, CObject>(CObject(p1, eTakeOwnership), CObject(p2, eTakeOwnership));
476 }
477 #endif
478 
479 inline CObject operator+ (const CObject& a, const CObject& b)
480 {
481  PyObject* tmp_obj = PyNumber_Add(a.Get(), b.Get());
482  if ( !tmp_obj ) {
483  throw CArithmeticError("PyNumber_Add");
484  }
485  return CObject(tmp_obj, eTakeOwnership);
486 }
487 
488 inline CObject operator- (const CObject& a, const CObject& b)
489 {
490  PyObject* tmp_obj = PyNumber_Subtract(a.Get(), b.Get());
491  if ( !tmp_obj ) {
492  throw CArithmeticError("PyNumber_Subtract");
493  }
494  return CObject(tmp_obj, eTakeOwnership);
495 }
496 
497 inline CObject operator* (const CObject& a, const CObject& b)
498 {
499  PyObject* tmp_obj = PyNumber_Multiply(a.Get(), b.Get());
500  if ( !tmp_obj ) {
501  throw CArithmeticError("PyNumber_Multiply");
502  }
503  return CObject(tmp_obj, eTakeOwnership);
504 }
505 
506 inline CObject operator/ (const CObject& a, const CObject& b)
507 {
508  PyObject* tmp_obj = PyNumber_TrueDivide(a.Get(), b.Get());
509  if ( !tmp_obj ) {
510  throw CArithmeticError("PyNumber_TrueDivide");
511  }
512  return CObject(tmp_obj, eTakeOwnership);
513 }
514 
515 inline CObject operator% (const CObject& a, const CObject& b)
516 {
517  PyObject* tmp_obj = PyNumber_Remainder(a.Get(), b.Get());
518  if ( !tmp_obj ) {
519  throw CArithmeticError("PyNumber_Remainder");
520  }
521  return CObject(tmp_obj, eTakeOwnership);
522 }
523 
524 //////////////////////////////////////////////////////////////////////////
525 inline
526 CType
527 CObject::GetType(void) const
528 {
529  // ???
530  PyObject* obj = PyObject_Type (Get());
531  if ( !obj ) {
532  throw CTypeError("Type does not exist");
533  }
534  return CType(obj, eTakeOwnership);
535 }
536 
537 /* Do not delete this code ...
538 inline
539 CString
540 CObject::GetString(void) const
541 {
542  // ???
543  PyObject* obj = PyObject_Str (Get());
544  if ( !obj ) {
545  throw CTypeError("Unable to convert an object to a string");
546  }
547  return CString(obj, eTakeOwnership);
548 }
549 
550 inline
551 CString
552 CObject::GetRepresentation() const
553 {
554  // ???
555  PyObject* obj = PyObject_Repr(Get());
556  if ( !obj ) {
557  throw CTypeError("Unable to convert an object to a representation");
558  }
559  return CString(obj, eTakeOwnership);
560 }
561 
562 inline
563 std::string
564 CObject::as_string(void) const
565 {
566  return static_cast<std::string>(GetString());
567 }
568 */
569 
570 inline
571 bool
573 {
574  return GetType().Get() == t.Get();
575 }
576 
577 }
578  // namespace pythonpp
580 
581 #endif // PYTHONPP_OBJECT_H
582 
CObject –.
Definition: ncbiobj.hpp:180
static void Check(void)
static bool HasExactSameType(PyObject *obj)
static bool HasSameType(PyObject *obj)
CNone & operator=(const CNone &obj)
CNone(const CObject &obj)
void SetAttr(const std::string &name, const CObject &value)
bool IsObjectType(const CType &t) const
void DelItem(const CObject &key)
CObject(void)
* Generic operations on objects *‍/
CType GetType(void) const
void Set(PyObject *obj, EOwnership ownership=eAcquireOwnership)
Not exception-safe this time.
bool IsTrue(void) const
CObject(PyObject *obj, EOwnership ownership=eAcquireOwnership)
CObject & operator=(const CObject &obj)
PyTypeObject * GetObjType(void) const
bool operator<(const CObject &obj) const
PyObject * Get(void) const
CObject GetAttr(const std::string &name) const
bool operator>(const CObject &obj) const
bool IsNumeric(void) const
bool operator>=(const CObject &obj) const
CObject(const CObject &obj)
long GetHashValue(void) const
void DelAttr(const std::string &name)
CObject GetItem(const CObject &key) const
bool HasAttr(const std::string &name) const
bool operator!=(const CObject &obj) const
bool operator==(const CObject &obj) const
bool operator<=(const CObject &obj) const
bool IsSequence(void) const
CType(PyObject *obj, EOwnership ownership=eAcquireOwnership)
static bool HasSameType(PyObject *obj)
CType & operator=(const CObject &obj)
static bool HasExactSameType(PyObject *obj)
CType(const CObject &obj)
CType(const CType &obj)
char value[7]
Definition: config.c:431
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
const struct ncbi::grid::netcache::search::fields::KEY key
CObject operator+(const CObject &a)
CObject operator%(const CObject &a, const CObject &b)
PyObject * DecRefCount(PyObject *obj)
CObject operator*(const CObject &a, const CObject &b)
CObject abs(const CObject &a)
PyObject * IncRefCount(PyObject *obj)
bool operator==(const CObject &l, const CExtType &r)
CObject operator-(const CObject &a)
CObject operator/(const CObject &a, const CObject &b)
unsigned int a
Definition: ncbi_localip.c:102
EIPRangeType t
Definition: ncbi_localip.c:101
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
#define _ASSERT
else result
Definition: token2.c:20
Modified on Sat Dec 02 09:19:17 2023 by modify_doxy.py rev. 669887