Browse Source

interrogate: support static properties

rdb 8 years ago
parent
commit
d1c34c3360
56 changed files with 973 additions and 677 deletions
  1. 588 632
      dtool/src/cppparser/cppBison.cxx.prebuilt
  2. 4 0
      dtool/src/cppparser/cppBison.yxx
  3. 5 0
      dtool/src/dtoolutil/executionEnvironment.h
  4. 15 0
      dtool/src/dtoolutil/pandaSystem.h
  5. 1 0
      dtool/src/dtoolutil/textEncoder.h
  6. 2 1
      dtool/src/interrogate/interfaceMaker.cxx
  7. 1 0
      dtool/src/interrogate/interfaceMaker.h
  8. 127 41
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  9. 136 3
      dtool/src/interrogatedb/py_panda.cxx
  10. 3 0
      dtool/src/interrogatedb/py_panda.h
  11. 4 0
      dtool/src/pystub/pystub.cxx
  12. 1 0
      panda/src/audio/audioManager.h
  13. 1 0
      panda/src/collide/collisionNode.h
  14. 2 0
      panda/src/display/windowProperties.h
  15. 13 0
      panda/src/express/memoryUsage.h
  16. 1 0
      panda/src/express/multifile.h
  17. 2 0
      panda/src/gobj/textureStage.h
  18. 1 0
      panda/src/gobj/textureStagePool.h
  19. 1 0
      panda/src/gobj/vertexDataPage.h
  20. 17 0
      panda/src/parametrics/ropeNode.h
  21. 1 0
      panda/src/pgraph/alphaTestAttrib.h
  22. 1 0
      panda/src/pgraph/antialiasAttrib.h
  23. 1 0
      panda/src/pgraph/audioVolumeAttrib.h
  24. 1 0
      panda/src/pgraph/auxBitplaneAttrib.h
  25. 1 0
      panda/src/pgraph/clipPlaneAttrib.h
  26. 1 0
      panda/src/pgraph/colorAttrib.h
  27. 1 0
      panda/src/pgraph/colorBlendAttrib.h
  28. 1 0
      panda/src/pgraph/colorScaleAttrib.h
  29. 1 0
      panda/src/pgraph/colorWriteAttrib.h
  30. 1 0
      panda/src/pgraph/cullBinAttrib.h
  31. 1 0
      panda/src/pgraph/cullFaceAttrib.h
  32. 1 0
      panda/src/pgraph/depthOffsetAttrib.h
  33. 1 0
      panda/src/pgraph/depthTestAttrib.h
  34. 1 0
      panda/src/pgraph/depthWriteAttrib.h
  35. 1 0
      panda/src/pgraph/fogAttrib.h
  36. 1 0
      panda/src/pgraph/geomNode.h
  37. 1 0
      panda/src/pgraph/lightAttrib.h
  38. 1 0
      panda/src/pgraph/lightRampAttrib.h
  39. 1 0
      panda/src/pgraph/logicOpAttrib.h
  40. 1 0
      panda/src/pgraph/materialAttrib.h
  41. 2 0
      panda/src/pgraph/pandaNode.h
  42. 1 0
      panda/src/pgraph/renderAttrib.h
  43. 1 0
      panda/src/pgraph/renderModeAttrib.h
  44. 1 0
      panda/src/pgraph/rescaleNormalAttrib.h
  45. 1 0
      panda/src/pgraph/scissorAttrib.h
  46. 1 0
      panda/src/pgraph/shadeModelAttrib.h
  47. 1 0
      panda/src/pgraph/shaderAttrib.h
  48. 1 0
      panda/src/pgraph/stencilAttrib.h
  49. 1 0
      panda/src/pgraph/texGenAttrib.h
  50. 1 0
      panda/src/pgraph/texMatrixAttrib.h
  51. 1 0
      panda/src/pgraph/textureAttrib.h
  52. 1 0
      panda/src/pgraph/transparencyAttrib.h
  53. 1 0
      panda/src/pgui/pgButton.h
  54. 10 0
      panda/src/pipeline/thread.h
  55. 3 0
      panda/src/speedtree/speedTreeNode.h
  56. 1 0
      panda/src/vision/webcamVideo.h

File diff suppressed because it is too large
+ 588 - 632
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 4 - 0
dtool/src/cppparser/cppBison.yxx

@@ -4051,6 +4051,10 @@ name:
         | KW_STATIC
 {
   $$ = new CPPIdentifier("static", @1);
+}
+        | KW_DEFAULT
+{
+  $$ = new CPPIdentifier("default", @1);
 }
         ;
 

+ 5 - 0
dtool/src/dtoolutil/executionEnvironment.h

@@ -51,6 +51,11 @@ PUBLISHED:
 
   static Filename get_cwd();
 
+  MAKE_SEQ_PROPERTY(args, get_num_args, get_arg);
+  MAKE_PROPERTY(binary_name, get_binary_name, set_binary_name);
+  MAKE_PROPERTY(dtool_name, get_dtool_name, set_dtool_name);
+  MAKE_PROPERTY(cwd, get_cwd);
+
 private:
   bool ns_has_environment_variable(const string &var) const;
   string ns_get_environment_variable(const string &var) const;

+ 15 - 0
dtool/src/dtoolutil/pandaSystem.h

@@ -48,6 +48,21 @@ PUBLISHED:
 
   static string get_platform();
 
+  MAKE_PROPERTY(version_string, get_version_string);
+  MAKE_PROPERTY(major_version, get_major_version);
+  MAKE_PROPERTY(minor_version, get_minor_version);
+  MAKE_PROPERTY(sequence_version, get_sequence_version);
+  MAKE_PROPERTY(official_version, is_official_version);
+
+  MAKE_PROPERTY(memory_alignment, get_memory_alignment);
+
+  MAKE_PROPERTY(distributor, get_distributor);
+  MAKE_PROPERTY(compiler, get_compiler);
+  MAKE_PROPERTY(build_date, get_build_date);
+  MAKE_PROPERTY(git_commit, get_git_commit);
+
+  MAKE_PROPERTY(platform, get_platform);
+
   bool has_system(const string &system) const;
   size_t get_num_systems() const;
   string get_system(size_t n) const;

+ 1 - 0
dtool/src/dtoolutil/textEncoder.h

@@ -46,6 +46,7 @@ PUBLISHED:
 
   INLINE static void set_default_encoding(Encoding encoding);
   INLINE static Encoding get_default_encoding();
+  MAKE_PROPERTY(default_encoding, get_default_encoding, set_default_encoding);
 
   INLINE void set_text(const string &text);
   INLINE void set_text(const string &text, Encoding encoding);

+ 2 - 1
dtool/src/interrogate/interfaceMaker.cxx

@@ -91,7 +91,8 @@ Property(const InterrogateElement &ielement) :
   _setter(NULL),
   _has_function(NULL),
   _clear_function(NULL),
-  _deleter(NULL)
+  _deleter(NULL),
+  _has_this(false)
 {
 }
 

+ 1 - 0
dtool/src/interrogate/interfaceMaker.h

@@ -132,6 +132,7 @@ public:
     Function *_has_function;
     Function *_clear_function;
     Function *_deleter;
+    bool _has_this;
   };
   typedef vector<Property *> Properties;
 

+ 127 - 41
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -2623,7 +2623,8 @@ write_module_class(ostream &out, Object *obj) {
     for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
       Property *property = (*pit);
       const InterrogateElement &ielem = property->_ielement;
-      if (property->_getter == NULL || !is_function_legal(property->_getter)) {
+      if (!property->_has_this ||
+          property->_getter == NULL || !is_function_legal(property->_getter)) {
         continue;
       }
 
@@ -3169,6 +3170,45 @@ write_module_class(ostream &out, Object *obj) {
     }
   }
 
+  // Also add the static properties, which can't be added via getset.
+  Properties::const_iterator pit;
+  for (pit = obj->_properties.begin(); pit != obj->_properties.end(); ++pit) {
+    Property *property = (*pit);
+    const InterrogateElement &ielem = property->_ielement;
+    if (property->_has_this ||
+        property->_getter == NULL || !is_function_legal(property->_getter)) {
+      continue;
+    }
+
+    string name1 = methodNameFromCppName(ielem.get_name(), "", false);
+    // string name2 = methodNameFromCppName(ielem.get_name(), "", true);
+
+    string getter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter";
+    string setter = "NULL";
+    if (property->_length_function == NULL &&
+        property->_setter != NULL && is_function_legal(property->_setter)) {
+      setter = "&Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter";
+    }
+
+    out << "    static const PyGetSetDef def_" << name1 << " = {(char *)\"" << name1 << "\", " << getter << ", " << setter;
+
+    if (ielem.has_comment()) {
+      out << ", (char *)\n";
+      output_quoted(out, 4, ielem.get_comment());
+      out << ",\n    ";
+    } else {
+      out << ", NULL, ";
+    }
+
+    // Extra void* argument; we don't make use of it.
+    out << "NULL};\n";
+
+    out << "    PyDict_SetItemString(dict, \"" << name1 << "\", Dtool_NewStaticProperty(&Dtool_" << ClassName << "._PyType, &def_" << name1 << "));\n";
+    /* Alternative spelling:
+    out << "    PyDict_SetItemString(\"" << name2 << "\", &def_" << name1 << ");\n";
+    */
+  }
+
   out << "    if (PyType_Ready((PyTypeObject *)&Dtool_" << ClassName << ") < 0) {\n"
          "      Dtool_Raise_TypeError(\"PyType_Ready(" << ClassName << ")\");\n"
          "      return;\n"
@@ -6443,11 +6483,15 @@ write_getset(ostream &out, Object *obj, Property *property) {
         "/**\n"
         " * sequence getter for property " << cClassName << "::" << ielem.get_name() << "\n"
         " */\n"
-        "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getitem(PyObject *self, Py_ssize_t index) {\n"
-        "  " << cClassName << " *local_this = NULL;\n"
-        "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
-        "    return NULL;\n"
-        "  }\n";
+        "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getitem(PyObject *self, Py_ssize_t index) {\n";
+      if (property->_getter->_has_this ||
+          (property->_has_function && property->_has_function->_has_this)) {
+        out <<
+          "  " << cClassName << " *local_this = NULL;\n"
+          "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"
+          "    return NULL;\n"
+          "  }\n";
+      }
 
       // This is a getitem of a sequence type.  This means we *need* to raise
       // IndexError if we're out of bounds.
@@ -6458,8 +6502,12 @@ write_getset(ostream &out, Object *obj, Property *property) {
       out << "  }\n";
 
       if (property->_has_function != NULL) {
-        out << "  if (!local_this->" << property->_has_function->_ifunc.get_name() << "(index)) {\n"
-            << "    Py_INCREF(Py_None);\n"
+        if (property->_has_function->_has_this) {
+          out << "  if (!local_this->" << property->_has_function->_ifunc.get_name() << "(index)) {\n";
+        } else {
+          out << "  if (!" << cClassName << "::" << property->_has_function->_ifunc.get_name() << "(index)) {\n";
+        }
+        out << "    Py_INCREF(Py_None);\n"
             << "    return Py_None;\n"
             << "  }\n";
       }
@@ -6494,16 +6542,22 @@ write_getset(ostream &out, Object *obj, Property *property) {
     // Write out a setitem if this is not a read-only property.
     if (property->_setter != NULL) {
       out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setitem(PyObject *self, Py_ssize_t index, PyObject *arg) {\n";
-      out << "  " << cClassName  << " *local_this = NULL;\n";
-      out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
-          << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
-      out << "    return -1;\n";
-      out << "  }\n\n";
+      if (property->_has_this) {
+        out << "  " << cClassName  << " *local_this = NULL;\n";
+        out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
+            << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
+        out << "    return -1;\n";
+        out << "  }\n\n";
+      }
 
       out << "  if (arg == (PyObject *)NULL) {\n";
       if (property->_deleter != NULL) {
-        out << "    local_this->" << property->_deleter->_ifunc.get_name() << "(index);\n"
-            << "    return 0;\n";
+        if (property->_deleter->_has_this) {
+          out << "    local_this->" << property->_deleter->_ifunc.get_name() << "(index);\n";
+        } else {
+          out << "    " << cClassName << "::" << property->_deleter->_ifunc.get_name() << "(index);\n";
+        }
+        out << "    return 0;\n";
       } else {
         out << "    Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << "[] attribute\");\n"
                "    return -1;\n";
@@ -6511,9 +6565,13 @@ write_getset(ostream &out, Object *obj, Property *property) {
       out << "  }\n";
 
       if (property->_clear_function != NULL) {
-        out << "  if (arg == Py_None) {\n"
-            << "    local_this->" << property->_clear_function->_ifunc.get_name() << "(index);\n"
-            << "    return 0;\n"
+        out << "  if (arg == Py_None) {\n";
+        if (property->_clear_function->_has_this) {
+          out << "    local_this->" << property->_clear_function->_ifunc.get_name() << "(index);\n";
+        } else {
+          out << "    " << cClassName << "::" << property->_clear_function->_ifunc.get_name() << "(index);\n";
+        }
+        out << "    return 0;\n"
             << "  }\n";
       }
 
@@ -6547,9 +6605,14 @@ write_getset(ostream &out, Object *obj, Property *property) {
     }
 
     // Now write the getter, which returns a special wrapper object.
-    out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n"
-           "  Py_INCREF(self);\n"
-           "  Dtool_SequenceWrapper *wrap = PyObject_New(Dtool_SequenceWrapper, &Dtool_SequenceWrapper_Type);\n"
+    out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
+    if (property->_has_this) {
+      out << "  nassertr(self != NULL, NULL);\n"
+             "  Py_INCREF(self);\n";
+    } else {
+      out << "  Py_XINCREF(self);\n";
+    }
+    out << "  Dtool_SequenceWrapper *wrap = PyObject_New(Dtool_SequenceWrapper, &Dtool_SequenceWrapper_Type);\n"
            "  wrap->_base = self;\n"
            "  wrap->_len_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Len;\n"
            "  wrap->_getitem_func = &Dtool_" << ClassName << "_" << ielem.get_name() << "_Getitem;\n";
@@ -6566,20 +6629,26 @@ write_getset(ostream &out, Object *obj, Property *property) {
     out << "static PyObject *Dtool_" + ClassName + "_" + ielem.get_name() + "_Getter(PyObject *self, void *) {\n";
     FunctionRemap *remap = property->_getter->_remaps.front();
 
-    if (remap->_const_method) {
-      out << "  const " << cClassName  << " *local_this = NULL;\n";
-      out << "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
-    } else {
-      out << "  " << cClassName  << " *local_this = NULL;\n";
-      out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
-          << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
+    if (remap->_has_this) {
+      if (remap->_const_method) {
+        out << "  const " << cClassName  << " *local_this = NULL;\n";
+        out << "  if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n";
+      } else {
+        out << "  " << cClassName  << " *local_this = NULL;\n";
+        out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
+            << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
+      }
+      out << "    return NULL;\n";
+      out << "  }\n\n";
     }
-    out << "    return NULL;\n";
-    out << "  }\n\n";
 
     if (property->_has_function != NULL) {
-      out << "  if (!local_this->" << property->_has_function->_ifunc.get_name() << "()) {\n"
-          << "    Py_INCREF(Py_None);\n"
+      if (remap->_has_this) {
+        out << "  if (!local_this->" << property->_has_function->_ifunc.get_name() << "()) {\n";
+      } else {
+        out << "  if (!" << cClassName << "::" << property->_has_function->_ifunc.get_name() << "()) {\n";
+      }
+      out << "    Py_INCREF(Py_None);\n"
           << "    return Py_None;\n"
           << "  }\n";
     }
@@ -6596,16 +6665,21 @@ write_getset(ostream &out, Object *obj, Property *property) {
     // Write out a setter if this is not a read-only property.
     if (property->_setter != NULL) {
       out << "static int Dtool_" + ClassName + "_" + ielem.get_name() + "_Setter(PyObject *self, PyObject *arg, void *) {\n";
-      out << "  " << cClassName  << " *local_this = NULL;\n";
-      out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
-          << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
-      out << "    return -1;\n";
-      out << "  }\n\n";
+      if (remap->_has_this) {
+        out << "  " << cClassName  << " *local_this = NULL;\n";
+        out << "  if (!Dtool_Call_ExtractThisPointer_NonConst(self, Dtool_" << ClassName << ", (void **)&local_this, \""
+            << classNameFromCppName(cClassName, false) << "." << ielem.get_name() << "\")) {\n";
+        out << "    return -1;\n";
+        out << "  }\n\n";
+      }
 
       out << "  if (arg == (PyObject *)NULL) {\n";
-      if (property->_deleter != NULL) {
+      if (property->_deleter != NULL && remap->_has_this) {
         out << "    local_this->" << property->_deleter->_ifunc.get_name() << "();\n"
             << "    return 0;\n";
+      } else if (property->_deleter != NULL) {
+        out << "    " << cClassName << "::" << property->_deleter->_ifunc.get_name() << "();\n"
+            << "    return 0;\n";
       } else {
         out << "    Dtool_Raise_TypeError(\"can't delete " << ielem.get_name() << " attribute\");\n"
                "    return -1;\n";
@@ -6613,9 +6687,13 @@ write_getset(ostream &out, Object *obj, Property *property) {
       out << "  }\n";
 
       if (property->_clear_function != NULL) {
-        out << "  if (arg == Py_None) {\n"
-            << "    local_this->" << property->_clear_function->_ifunc.get_name() << "();\n"
-            << "    return 0;\n"
+        out << "  if (arg == Py_None) {\n";
+        if (remap->_has_this) {
+          out << "    local_this->" << property->_clear_function->_ifunc.get_name() << "();\n";
+        } else {
+          out << "    " << cClassName << "::" << property->_clear_function->_ifunc.get_name() << "();\n";
+        }
+        out << "    return 0;\n"
             << "  }\n";
       }
 
@@ -6744,6 +6822,7 @@ record_object(TypeIndex type_index) {
       Function *setter = record_function(itype, func_index);
       if (is_function_legal(setter)) {
         property->_setter = setter;
+        property->_has_this |= setter->_has_this;
       }
     }
 
@@ -6752,6 +6831,7 @@ record_object(TypeIndex type_index) {
       Function *getter = record_function(itype, func_index);
       if (is_function_legal(getter)) {
         property->_getter = getter;
+        property->_has_this |= getter->_has_this;
       }
     }
 
@@ -6760,6 +6840,7 @@ record_object(TypeIndex type_index) {
       Function *has_function = record_function(itype, func_index);
       if (is_function_legal(has_function)) {
         property->_has_function = has_function;
+        property->_has_this |= has_function->_has_this;
       }
     }
 
@@ -6768,6 +6849,7 @@ record_object(TypeIndex type_index) {
       Function *clear_function = record_function(itype, func_index);
       if (is_function_legal(clear_function)) {
         property->_clear_function = clear_function;
+        property->_has_this |= clear_function->_has_this;
       }
     }
 
@@ -6776,12 +6858,16 @@ record_object(TypeIndex type_index) {
       Function *del_function = record_function(itype, func_index);
       if (is_function_legal(del_function)) {
         property->_deleter = del_function;
+        property->_has_this |= del_function->_has_this;
       }
     }
 
     if (ielement.is_sequence()) {
       FunctionIndex func_index = ielement.get_length_function();
       property->_length_function = record_function(itype, func_index);
+      if (property->_length_function != nullptr) {
+        property->_has_this |= property->_length_function->_has_this;
+      }
     }
 
     if (property->_getter != NULL) {

+ 136 - 3
dtool/src/interrogatedb/py_panda.cxx

@@ -618,8 +618,11 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
     dtool_inited = true;
 
     if (PyType_Ready(&Dtool_SequenceWrapper_Type) < 0) {
-      PyErr_SetString(PyExc_TypeError, "PyType_Ready(Dtool_SequenceWrapper)");
-      return NULL;
+      return Dtool_Raise_TypeError("PyType_Ready(Dtool_SequenceWrapper)");
+    }
+
+    if (PyType_Ready(&Dtool_StaticProperty_Type) < 0) {
+      return Dtool_Raise_TypeError("PyType_Ready(Dtool_StaticProperty_Type)");
     }
 
     // Initialize the base class of everything.
@@ -1035,7 +1038,7 @@ bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args, PyObject *kwds)
 static void Dtool_SequenceWrapper_dealloc(PyObject *self) {
   Dtool_SequenceWrapper *wrap = (Dtool_SequenceWrapper *)self;
   nassertv(wrap);
-  Py_DECREF(wrap->_base);
+  Py_XDECREF(wrap->_base);
 }
 
 static Py_ssize_t Dtool_SequenceWrapper_length(PyObject *self) {
@@ -1131,4 +1134,134 @@ PyTypeObject Dtool_SequenceWrapper_Type = {
 #endif
 };
 
+/**
+ * This is a variant of the Python getset mechanism that permits static
+ * properties.
+ */
+PyObject *
+Dtool_NewStaticProperty(PyTypeObject *type, const PyGetSetDef *getset) {
+  PyGetSetDescrObject *descr;
+  descr = (PyGetSetDescrObject *)PyType_GenericAlloc(&Dtool_StaticProperty_Type, 0);
+  if (descr != nullptr) {
+    Py_XINCREF(type);
+    descr->d_getset = (PyGetSetDef *)getset;
+#if PY_MAJOR_VERSION >= 3
+    descr->d_common.d_type = type;
+    descr->d_common.d_name = PyUnicode_InternFromString(getset->name);
+    descr->d_common.d_qualname = nullptr;
+#else
+    descr->d_type = type;
+    descr->d_name = PyString_InternFromString(getset->name);
+#endif
+  }
+  return (PyObject *)descr;
+}
+
+static void
+Dtool_StaticProperty_dealloc(PyDescrObject *descr) {
+  _PyObject_GC_UNTRACK(descr);
+  Py_XDECREF(descr->d_type);
+  Py_XDECREF(descr->d_name);
+//#if PY_MAJOR_VERSION >= 3
+//  Py_XDECREF(descr->d_qualname);
+//#endif
+  PyObject_GC_Del(descr);
+}
+
+static PyObject *
+Dtool_StaticProperty_repr(PyDescrObject *descr, const char *format) {
+#if PY_MAJOR_VERSION >= 3
+  return PyUnicode_FromFormat("<attribute '%V' of '%s'>", descr->d_name, "?", descr->d_type->tp_name);
+#else
+  return PyString_FromFormat("<attribute '%V' of '%s'>", descr->d_name, "?", descr->d_type->tp_name);
+#endif
+}
+
+static int
+Dtool_StaticProperty_traverse(PyObject *self, visitproc visit, void *arg) {
+  PyDescrObject *descr = (PyDescrObject *)self;
+  Py_VISIT(descr->d_type);
+  return 0;
+}
+
+static PyObject *
+Dtool_StaticProperty_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type) {
+  if (descr->d_getset->get != nullptr) {
+    return descr->d_getset->get(obj, descr->d_getset->closure);
+  } else {
+    return PyErr_Format(PyExc_AttributeError,
+                        "attribute '%V' of type '%.100s' is not readable",
+                        ((PyDescrObject *)descr)->d_name, "?",
+                        ((PyDescrObject *)descr)->d_type->tp_name);
+  }
+}
+
+static int
+Dtool_StaticProperty_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) {
+  if (descr->d_getset->set != nullptr) {
+    return descr->d_getset->set(obj, value, descr->d_getset->closure);
+  } else {
+    PyErr_Format(PyExc_AttributeError,
+                 "attribute '%V' of type '%.100s' is not writable",
+                 ((PyDescrObject *)descr)->d_name, "?",
+                 ((PyDescrObject *)descr)->d_type->tp_name);
+    return -1;
+  }
+}
+
+PyTypeObject Dtool_StaticProperty_Type = {
+  PyVarObject_HEAD_INIT(&PyType_Type, 0)
+  "getset_descriptor",
+  sizeof(PyGetSetDescrObject),
+  0, // tp_itemsize
+  (destructor)Dtool_StaticProperty_dealloc,
+  0, // tp_print
+  0, // tp_getattr
+  0, // tp_setattr
+  0, // tp_reserved
+  (reprfunc)Dtool_StaticProperty_repr,
+  0, // tp_as_number
+  0, // tp_as_sequence
+  0, // tp_as_mapping
+  0, // tp_hash
+  0, // tp_call
+  0, // tp_str
+  PyObject_GenericGetAttr,
+  0, // tp_setattro
+  0, // tp_as_buffer
+  Py_TPFLAGS_DEFAULT,
+  0, // tp_doc
+  Dtool_StaticProperty_traverse,
+  0, // tp_clear
+  0, // tp_richcompare
+  0, // tp_weaklistoffset
+  0, // tp_iter
+  0, // tp_iternext
+  0, // tp_methods
+  0, // tp_members
+  0, // tp_getset
+  0, // tp_base
+  0, // tp_dict
+  (descrgetfunc)Dtool_StaticProperty_get,
+  (descrsetfunc)Dtool_StaticProperty_set,
+  0, // tp_dictoffset
+  0, // tp_init
+  0, // tp_alloc
+  0, // tp_new
+  0, // tp_del
+  0, // tp_is_gc
+  0, // tp_bases
+  0, // tp_mro
+  0, // tp_cache
+  0, // tp_subclasses
+  0, // tp_weaklist
+  0, // tp_del
+#if PY_VERSION_HEX >= 0x02060000
+  0, // tp_version_tag
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+  0, // tp_finalize
+#endif
+};
+
 #endif  // HAVE_PYTHON

+ 3 - 0
dtool/src/interrogatedb/py_panda.h

@@ -471,6 +471,9 @@ struct Dtool_SequenceWrapper {
 };
 
 EXPCL_INTERROGATEDB extern PyTypeObject Dtool_SequenceWrapper_Type;
+EXPCL_INTERROGATEDB extern PyTypeObject Dtool_StaticProperty_Type;
+
+EXPCL_INTERROGATEDB PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
 
 /**
  * These functions check whether the arguments passed to a function conform to

+ 4 - 0
dtool/src/pystub/pystub.cxx

@@ -105,6 +105,7 @@ extern "C" {
   EXPCL_PYSTUB int PyObject_Cmp(...);
   EXPCL_PYSTUB int PyObject_Compare(...);
   EXPCL_PYSTUB int PyObject_Free(...);
+  EXPCL_PYSTUB int PyObject_GC_Del(...);
   EXPCL_PYSTUB int PyObject_GenericGetAttr(...);
   EXPCL_PYSTUB int PyObject_GenericSetAttr(...);
   EXPCL_PYSTUB int PyObject_GetAttrString(...);
@@ -223,6 +224,7 @@ extern "C" {
   EXPCL_PYSTUB extern void *PyExc_SystemExit;
   EXPCL_PYSTUB extern void *PyExc_TypeError;
   EXPCL_PYSTUB extern void *PyExc_ValueError;
+  EXPCL_PYSTUB extern void *PyType_Type;
   EXPCL_PYSTUB extern void *_PyThreadState_Current;
   EXPCL_PYSTUB extern void *_Py_FalseStruct;
   EXPCL_PYSTUB extern void *_Py_NoneStruct;
@@ -324,6 +326,7 @@ int PyObject_CallObject(...) { return 0; }
 int PyObject_Cmp(...) { return 0; }
 int PyObject_Compare(...) { return 0; }
 int PyObject_Free(...) { return 0; }
+int PyObject_GC_Del(...) { return 0; }
 int PyObject_GenericGetAttr(...) { return 0; };
 int PyObject_GenericSetAttr(...) { return 0; };
 int PyObject_GetAttrString(...) { return 0; }
@@ -448,6 +451,7 @@ void *PyExc_StopIteration = (void *)NULL;
 void *PyExc_SystemExit = (void *)NULL;
 void *PyExc_TypeError = (void *)NULL;
 void *PyExc_ValueError = (void *)NULL;
+void *PyType_Type = (void *)NULL;
 void *_PyThreadState_Current = (void *)NULL;
 void *_Py_FalseStruct = (void *)NULL;
 void *_Py_NoneStruct = (void *)NULL;

+ 1 - 0
panda/src/audio/audioManager.h

@@ -172,6 +172,7 @@ PUBLISHED:
   virtual PN_stdfloat audio_3d_get_drop_off_factor() const;
 
   static Filename get_dls_pathname();
+  MAKE_PROPERTY(dls_pathname, get_dls_pathname);
 
   virtual void output(ostream &out) const;
   virtual void write(ostream &out) const;

+ 1 - 0
panda/src/collide/collisionNode.h

@@ -75,6 +75,7 @@ PUBLISHED:
   MAKE_PROPERTY(collider_sort, get_collider_sort, set_collider_sort);
 
   INLINE static CollideMask get_default_collide_mask();
+  MAKE_PROPERTY(default_collide_mask, get_default_collide_mask);
 
 protected:
   virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,

+ 2 - 0
panda/src/display/windowProperties.h

@@ -49,6 +49,8 @@ PUBLISHED:
   static WindowProperties get_default();
   static void set_default(const WindowProperties &default_properties);
   static void clear_default();
+  MAKE_PROPERTY(config_properties, get_config_properties);
+  MAKE_PROPERTY(default, get_default, set_default);
 
   static WindowProperties size(int x_size, int y_size);
 

+ 13 - 0
panda/src/express/memoryUsage.h

@@ -89,6 +89,19 @@ PUBLISHED:
   INLINE static void show_current_ages();
   INLINE static void show_trend_ages();
 
+PUBLISHED:
+  MAKE_PROPERTY(tracking, is_tracking);
+  MAKE_PROPERTY(counting, is_counting);
+  MAKE_PROPERTY(current_cpp_size, get_current_cpp_size);
+  MAKE_PROPERTY(total_cpp_size, get_total_cpp_size);
+
+  MAKE_PROPERTY(panda_heap_single_size, get_panda_heap_single_size);
+  MAKE_PROPERTY(panda_heap_array_size, get_panda_heap_array_size);
+  MAKE_PROPERTY(panda_heap_overhead, get_panda_heap_overhead);
+  MAKE_PROPERTY(panda_mmap_size, get_panda_mmap_size);
+  MAKE_PROPERTY(external_size, get_external_size);
+  MAKE_PROPERTY(total_size, get_total_size);
+
 protected:
   virtual void overflow_heap_size();
 

+ 1 - 0
panda/src/express/multifile.h

@@ -136,6 +136,7 @@ PUBLISHED:
   void ls(ostream &out = cout) const;
 
   static INLINE string get_magic_number();
+  MAKE_PROPERTY(magic_number, get_magic_number);
 
   void set_header_prefix(const string &header_prefix);
   INLINE const string &get_header_prefix() const;

+ 2 - 0
panda/src/gobj/textureStage.h

@@ -201,6 +201,8 @@ PUBLISHED:
 
   MAKE_PROPERTY(tex_view_offset, get_tex_view_offset, set_tex_view_offset);
 
+  MAKE_PROPERTY(default, get_default);
+
 public:
   INLINE static UpdateSeq get_sort_seq();
 

+ 1 - 0
panda/src/gobj/textureStagePool.h

@@ -43,6 +43,7 @@ PUBLISHED:
 
   INLINE static void set_mode(Mode mode);
   INLINE static Mode get_mode();
+  MAKE_PROPERTY(mode, get_mode, set_mode);
 
   INLINE static int garbage_collect();
   INLINE static void list_contents(ostream &out);

+ 1 - 0
panda/src/gobj/vertexDataPage.h

@@ -64,6 +64,7 @@ PUBLISHED:
   INLINE static SimpleLru *get_global_lru(RamClass rclass);
   INLINE static SimpleLru *get_pending_lru();
   INLINE static VertexDataSaveFile *get_save_file();
+  MAKE_PROPERTY(save_file, get_save_file);
 
   INLINE bool save_to_disk();
 

+ 17 - 0
panda/src/parametrics/ropeNode.h

@@ -136,6 +136,23 @@ PUBLISHED:
 
   void reset_bound(const NodePath &rel_to);
 
+PUBLISHED:
+  MAKE_PROPERTY(curve, get_curve, set_curve);
+  MAKE_PROPERTY(render_mode, get_render_mode, set_render_mode);
+  MAKE_PROPERTY(uv_mode, get_uv_mode, set_uv_mode);
+  MAKE_PROPERTY(uv_direction, get_uv_direction, set_uv_direction);
+  MAKE_PROPERTY(uv_scale, get_uv_scale, set_uv_scale);
+  MAKE_PROPERTY(normal_mode, get_normal_mode, set_normal_mode);
+  MAKE_PROPERTY(tube_up, get_tube_up, set_tube_up);
+  MAKE_PROPERTY(use_vertex_color, get_use_vertex_color, set_use_vertex_color);
+  MAKE_PROPERTY(vertex_color_dimension, get_vertex_color_dimension);
+  MAKE_PROPERTY(num_subdiv, get_num_subdiv, set_num_subdiv);
+  MAKE_PROPERTY(num_slices, get_num_slices, set_num_slices);
+  MAKE_PROPERTY(use_vertex_thickness, get_use_vertex_thickness, set_use_vertex_thickness);
+  MAKE_PROPERTY(vertex_thickness_dimension, get_vertex_thickness_dimension);
+  MAKE_PROPERTY(thickness, get_thickness, set_thickness);
+  MAKE_PROPERTY2(matrix, has_matrix, get_matrix, set_matrix, clear_matrix);
+
 protected:
   virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
                                        int &internal_vertices,

+ 1 - 0
panda/src/pgraph/alphaTestAttrib.h

@@ -58,6 +58,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/antialiasAttrib.h

@@ -75,6 +75,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/audioVolumeAttrib.h

@@ -65,6 +65,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/auxBitplaneAttrib.h

@@ -85,6 +85,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/clipPlaneAttrib.h

@@ -123,6 +123,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/colorAttrib.h

@@ -69,6 +69,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/colorBlendAttrib.h

@@ -138,6 +138,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/colorScaleAttrib.h

@@ -74,6 +74,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/colorWriteAttrib.h

@@ -76,6 +76,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static TypeHandle get_class_type() {

+ 1 - 0
panda/src/pgraph/cullBinAttrib.h

@@ -57,6 +57,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/cullFaceAttrib.h

@@ -69,6 +69,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/depthOffsetAttrib.h

@@ -86,6 +86,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/depthTestAttrib.h

@@ -53,6 +53,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/depthWriteAttrib.h

@@ -59,6 +59,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/fogAttrib.h

@@ -54,6 +54,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/geomNode.h

@@ -89,6 +89,7 @@ PUBLISHED:
   void write_verbose(ostream &out, int indent_level) const;
 
   INLINE static CollideMask get_default_collide_mask();
+  MAKE_PROPERTY(default_collide_mask, get_default_collide_mask);
 
 public:
   virtual void output(ostream &out) const;

+ 1 - 0
panda/src/pgraph/lightAttrib.h

@@ -131,6 +131,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   // This data is only needed when reading from a bam file.

+ 1 - 0
panda/src/pgraph/lightRampAttrib.h

@@ -76,6 +76,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/logicOpAttrib.h

@@ -75,6 +75,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/materialAttrib.h

@@ -56,6 +56,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 2 - 0
panda/src/pgraph/pandaNode.h

@@ -234,6 +234,8 @@ PUBLISHED:
   INLINE static DrawMask get_all_camera_mask();
   INLINE bool is_overall_hidden() const;
   INLINE void set_overall_hidden(bool overall_hidden);
+  MAKE_PROPERTY(overall_bit, get_overall_bit);
+  MAKE_PROPERTY(all_camera_mask, get_all_camera_mask);
   MAKE_PROPERTY(overall_hidden, is_overall_hidden, set_overall_hidden);
 
   void adjust_draw_mask(DrawMask show_mask,

+ 1 - 0
panda/src/pgraph/renderAttrib.h

@@ -83,6 +83,7 @@ PUBLISHED:
   static bool validate_attribs();
 
   virtual int get_slot() const=0;
+  MAKE_PROPERTY(slot, get_slot);
 
   enum PandaCompareFunc {   // intentionally defined to match D3DCMPFUNC
     M_none=0,           // alpha-test disabled (always-draw)

+ 1 - 0
panda/src/pgraph/renderModeAttrib.h

@@ -92,6 +92,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/rescaleNormalAttrib.h

@@ -72,6 +72,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/scissorAttrib.h

@@ -70,6 +70,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/shadeModelAttrib.h

@@ -59,6 +59,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/shaderAttrib.h

@@ -158,6 +158,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static TypeHandle get_class_type() {

+ 1 - 0
panda/src/pgraph/stencilAttrib.h

@@ -155,6 +155,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/texGenAttrib.h

@@ -114,6 +114,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/texMatrixAttrib.h

@@ -101,6 +101,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/textureAttrib.h

@@ -157,6 +157,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgraph/transparencyAttrib.h

@@ -70,6 +70,7 @@ PUBLISHED:
   virtual int get_slot() const {
     return get_class_slot();
   }
+  MAKE_PROPERTY(class_slot, get_class_slot);
 
 public:
   static void register_with_read_factory();

+ 1 - 0
panda/src/pgui/pgButton.h

@@ -73,6 +73,7 @@ PUBLISHED:
 
   INLINE static string get_click_prefix();
   INLINE string get_click_event(const ButtonHandle &button) const;
+  MAKE_PROPERTY(click_prefix, get_click_prefix);
 
 private:
   typedef pset<ButtonHandle> Buttons;

+ 10 - 0
panda/src/pipeline/thread.h

@@ -100,6 +100,16 @@ PUBLISHED:
   MAKE_PROPERTY(python_index, get_python_index);
   MAKE_PROPERTY(unique_id, get_unique_id);
   MAKE_PROPERTY(pipeline_stage, get_pipeline_stage, set_pipeline_stage);
+
+  MAKE_PROPERTY(main_thread, get_main_thread);
+  MAKE_PROPERTY(external_thread, get_external_thread);
+  MAKE_PROPERTY(current_thread, get_current_thread);
+  MAKE_PROPERTY(current_pipeline_stage, get_current_pipeline_stage);
+
+  MAKE_PROPERTY(threading_supported, is_threading_supported);
+  MAKE_PROPERTY(true_threads, is_true_threads);
+  MAKE_PROPERTY(simple_threads, is_simple_threads);
+
   MAKE_PROPERTY(started, is_started);
   MAKE_PROPERTY(joinable, is_joinable);
   MAKE_PROPERTY(current_task, get_current_task);

+ 3 - 0
panda/src/speedtree/speedTreeNode.h

@@ -141,6 +141,9 @@ PUBLISHED:
   INLINE double get_time_delta() const;
   INLINE static void set_global_time_delta(double delta);
   INLINE static double get_global_time_delta();
+  MAKE_PROPERTY(time_delta, get_time_delta, set_time_delta);
+  MAKE_PROPERTY(global_time_delta, get_global_time_delta,
+                                   set_global_time_delta);
 
   static bool authorize(const string &license = "");
 

+ 1 - 0
panda/src/vision/webcamVideo.h

@@ -28,6 +28,7 @@ PUBLISHED:
   static int             get_num_options();
   static PT(WebcamVideo) get_option(int n);
   MAKE_SEQ(get_options, get_num_options, get_option);
+  MAKE_SEQ_PROPERTY(options, get_num_options, get_option);
 
   INLINE int get_size_x() const;
   INLINE int get_size_y() const;

Some files were not shown because too many files changed in this diff