diff --git a/direct/src/distributed/ConnectionRepository.py b/direct/src/distributed/ConnectionRepository.py index 18cbbdae8a..c13ed03d21 100644 --- a/direct/src/distributed/ConnectionRepository.py +++ b/direct/src/distributed/ConnectionRepository.py @@ -491,7 +491,7 @@ class ConnectionRepository( elif self.connectMethod == self.CM_NET or (not hasattr(self,"connectNative")): # Try each of the servers in turn. for url in serverList: - self.notify.info("Connecting to %s via NET interface." % (url.cStr())) + self.notify.info("Connecting to %s via NET interface." % (url)) if self.tryConnectNet(url): self.startReaderPollTask() if successCallback: @@ -503,7 +503,7 @@ class ConnectionRepository( failureCallback(0, '', *failureArgs) elif self.connectMethod == self.CM_NATIVE: for url in serverList: - self.notify.info("Connecting to %s via Native interface." % (url.cStr())) + self.notify.info("Connecting to %s via Native interface." % (url)) if self.connectNative(url): self.startReaderPollTask() if successCallback: @@ -536,7 +536,7 @@ class ConnectionRepository( if ch.isConnectionReady(): self.setConnectionHttp(ch) self._serverAddress = serverList[serverIndex-1] - self.notify.info("Successfully connected to %s." % (self._serverAddress.cStr())) + self.notify.info("Successfully connected to %s." % (self._serverAddress)) ## if self.recorder: ## # If we have a recorder, we wrap the connect inside a @@ -562,7 +562,7 @@ class ConnectionRepository( # No connection yet, but keep trying. url = serverList[serverIndex] - self.notify.info("Connecting to %s via HTTP interface." % (url.cStr())) + self.notify.info("Connecting to %s via HTTP interface." % (url)) ch.preserveStatus() ch.beginConnectTo(DocumentSpec(url)) diff --git a/direct/src/distributed/DistributedCartesianGrid.py b/direct/src/distributed/DistributedCartesianGrid.py index e577ee2ba0..ea88ebaf56 100755 --- a/direct/src/distributed/DistributedCartesianGrid.py +++ b/direct/src/distributed/DistributedCartesianGrid.py @@ -250,7 +250,7 @@ class DistributedCartesianGrid(DistributedNode, CartesianGridBase): assert self.notify.debug("removeObjectFromGrid %s" % av) # TODO: WHAT LOCATION SHOULD WE SET THIS TO? #av.reparentTo(hidden) - if (av.getParent().compareTo(self) == 0): + if av.getParent() == self: # only detach if object is directly parented av.detachNode() #av.b_setLocation(0, 0) diff --git a/direct/src/extensions/ConfigVariableFilename-extensions.py b/direct/src/extensions/ConfigVariableFilename-extensions.py deleted file mode 100644 index 61cefc0d82..0000000000 --- a/direct/src/extensions/ConfigVariableFilename-extensions.py +++ /dev/null @@ -1,9 +0,0 @@ - - def __str__(self): - return self.cStr() - - def __len__(self): - return self.length() - - def __getitem__(self, n): - return self.cStr().__getitem__(n) diff --git a/direct/src/extensions/HTTPChannel-extensions.py b/direct/src/extensions/HTTPChannel-extensions.py index f909cceb4f..d3fc500cfb 100644 --- a/direct/src/extensions/HTTPChannel-extensions.py +++ b/direct/src/extensions/HTTPChannel-extensions.py @@ -14,7 +14,7 @@ Returns the newly-spawned task. """ if not name: - name = self.getUrl().cStr() + name = str(self.getUrl()) from direct.task import Task task = Task.Task(self.doTask) task.callback = callback diff --git a/direct/src/extensions_native/HTTPChannel_extensions.py b/direct/src/extensions_native/HTTPChannel_extensions.py index fbbb4421dc..3257c16278 100644 --- a/direct/src/extensions_native/HTTPChannel_extensions.py +++ b/direct/src/extensions_native/HTTPChannel_extensions.py @@ -18,7 +18,7 @@ def spawnTask(self, name = None, callback = None, extraArgs = []): Returns the newly-spawned task. """ if not name: - name = self.getUrl().cStr() + name = str(self.getUrl()) from direct.task import Task task = Task.Task(self.doTask) task.callback = callback diff --git a/direct/src/leveleditor/LevelEditorBase.py b/direct/src/leveleditor/LevelEditorBase.py index 01c6ec23a9..c115468f6c 100755 --- a/direct/src/leveleditor/LevelEditorBase.py +++ b/direct/src/leveleditor/LevelEditorBase.py @@ -111,7 +111,7 @@ class LevelEditorBase(DirectObject): base.direct.deselect(nodePath) self.objectMgr.removeObjectByNodePath(nodePath) - if (base.direct.selected.last != None and nodePath.compareTo(base.direct.selected.last)==0): + if base.direct.selected.last is not None and nodePath == base.direct.selected.last: # if base.direct.selected.last is refering to this # removed obj, clear the reference if (hasattr(__builtins__,'last')): diff --git a/direct/src/p3d/AppRunner.py b/direct/src/p3d/AppRunner.py index b6b86a2c2e..b9a1f17572 100644 --- a/direct/src/p3d/AppRunner.py +++ b/direct/src/p3d/AppRunner.py @@ -175,7 +175,7 @@ class AppRunner(DirectObject): # the current working directory, for convenience; but when we # move to multiple-instance sessions, it may have to be # different for each instance. - self.multifileRoot = ExecutionEnvironment.getCwd().cStr() + self.multifileRoot = str(ExecutionEnvironment.getCwd()) # The "main" object will be exposed to the DOM as a property # of the plugin object; that is, document.pluginobject.main in @@ -554,7 +554,7 @@ class AppRunner(DirectObject): # Write the file to a temporary filename, then atomically move # it to its actual filename, to avoid race conditions when # updating this file. - tfile = Filename.temporary(self.rootDir.cStr(), '.xml') + tfile = Filename.temporary(str(self.rootDir), '.xml') if doc.SaveFile(tfile.toOsSpecific()): tfile.renameTo(filename) diff --git a/direct/src/p3d/FileSpec.py b/direct/src/p3d/FileSpec.py index 822bfccb5f..291149ad77 100644 --- a/direct/src/p3d/FileSpec.py +++ b/direct/src/p3d/FileSpec.py @@ -25,7 +25,7 @@ class FileSpec: if pathname is None: pathname = Filename(packageDir, filename) - self.filename = filename.cStr() + self.filename = str(filename) self.basename = filename.getBasename() if st is None: diff --git a/direct/src/p3d/HostInfo.py b/direct/src/p3d/HostInfo.py index ab033f3383..f22e47cf82 100644 --- a/direct/src/p3d/HostInfo.py +++ b/direct/src/p3d/HostInfo.py @@ -646,7 +646,7 @@ class HostInfo: if hostDirBasename: # If the contents.xml specified a host_dir parameter, use # it. - hostDir = self.rootDir.cStr() + '/hosts' + hostDir = str(self.rootDir) + '/hosts' for component in hostDirBasename.split('/'): if component: if component[0] == '.': diff --git a/direct/src/p3d/PackageInfo.py b/direct/src/p3d/PackageInfo.py index 7f2d382cd2..3e1767b91f 100644 --- a/direct/src/p3d/PackageInfo.py +++ b/direct/src/p3d/PackageInfo.py @@ -1066,7 +1066,7 @@ class PackageInfo: return False # We mount it under its actual location on disk. - root = self.getPackageDir().cStr() + root = self.getPackageDir() vfs = VirtualFileSystem.getGlobalPtr() vfs.mount(mf, root, vfs.MFReadOnly) @@ -1210,7 +1210,7 @@ class PackageInfo: # Write the file to a temporary filename, then atomically move # it to its actual filename, to avoid race conditions when # updating this file. - tfile = Filename.temporary(self.getPackageDir().cStr(), '.xml') + tfile = Filename.temporary(str(self.getPackageDir()), '.xml') if doc.SaveFile(tfile.toOsSpecific()): tfile.renameTo(filename) diff --git a/direct/src/p3d/PatchMaker.py b/direct/src/p3d/PatchMaker.py index e11306b82f..e8fbf80274 100644 --- a/direct/src/p3d/PatchMaker.py +++ b/direct/src/p3d/PatchMaker.py @@ -526,7 +526,7 @@ class PatchMaker: # Also copy the seq to the import desc file, for # documentation purposes. - importDescFilename = self.packageDesc.cStr()[:-3] + 'import.xml' + importDescFilename = str(self.packageDesc)[:-3] + 'import.xml' importDescFullpath = Filename(self.patchMaker.installDir, importDescFilename) doc = TiXmlDocument(importDescFullpath.toOsSpecific()) if doc.LoadFile(): diff --git a/direct/src/p3d/ScanDirectoryNode.py b/direct/src/p3d/ScanDirectoryNode.py index 1569ed642f..94f323551e 100644 --- a/direct/src/p3d/ScanDirectoryNode.py +++ b/direct/src/p3d/ScanDirectoryNode.py @@ -58,7 +58,7 @@ class ScanDirectoryNode: # Now update the usage.xml file with the newly-determined # disk space. xusage.SetAttribute('disk_space', str(self.getTotalSize())) - tfile = Filename.temporary(pathname.cStr(), '.xml') + tfile = Filename.temporary(str(pathname), '.xml') if doc.SaveFile(tfile.toOsSpecific()): tfile.renameTo(usageFilename) diff --git a/direct/src/showbase/VFSImporter.py b/direct/src/showbase/VFSImporter.py index e33f4b551b..6f8c76266f 100644 --- a/direct/src/showbase/VFSImporter.py +++ b/direct/src/showbase/VFSImporter.py @@ -408,7 +408,7 @@ class VFSSharedImporter: path = sys.path for dir in path: - pdir = Filename.fromOsSpecific(dir).cStr() + pdir = str(Filename.fromOsSpecific(dir)) if pdir + '/' + basename == dirname: # We found it! return dir diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index 1e8d35e57f..216192939f 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -1174,7 +1174,7 @@ class Freezer: source = open(sourceFilename.toOsSpecific(), 'r').read() if source and source[-1] != '\n': source = source + '\n' - code = compile(source, sourceFilename.cStr(), 'exec') + code = compile(source, str(sourceFilename), 'exec') self.__addPyc(multifile, filename, code, compressionLevel) diff --git a/dtool/src/dtoolutil/filename.h b/dtool/src/dtoolutil/filename.h index a391407a4e..650f7d84a6 100644 --- a/dtool/src/dtoolutil/filename.h +++ b/dtool/src/dtoolutil/filename.h @@ -122,6 +122,8 @@ PUBLISHED: INLINE size_t length() const; INLINE char operator [] (int n) const; + EXTENSION(PyObject *__repr__() const); + INLINE string substr(size_t begin, size_t end = string::npos) const; INLINE void operator += (const string &other); INLINE Filename operator + (const string &other) const; diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index bd48703e64..4e928c8e6d 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -569,6 +569,24 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, return true; } + if (method_name == "__repr__") { + def._answer_location = "tp_repr"; + def._wrapper_type = WT_no_params; + return true; + } + + if (method_name == "__str__") { + def._answer_location = "tp_str"; + def._wrapper_type = WT_no_params; + return true; + } + + if (method_name == "__cmp__" || (remap->_flags & FunctionRemap::F_compare_to) != 0) { + def._answer_location = "tp_compare"; + def._wrapper_type = WT_compare; + return true; + } + if (remap->_type == FunctionRemap::T_typecast_method) { // A typecast operator. Check for a supported low-level typecast type. if (TypeManager::is_bool(remap->_return_type->get_orig_type())) { @@ -589,6 +607,12 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, def._answer_location = "nb_float"; def._wrapper_type = WT_no_params; return true; + + } else if (remap->_return_type->new_type_is_atomic_string()) { + // A string type. + def._answer_location = "tp_str"; + def._wrapper_type = WT_no_params; + return true; } } @@ -2214,6 +2238,33 @@ write_module_class(ostream &out, Object *obj) { } break; + case WT_compare: + // int func(PyObject *self, Py_ssize_t index) + { + out << "//////////////////\n"; + out << "// A wrapper function to satisfy Python's internal calling conventions.\n"; + out << "// " << ClassName << " slot " << rfi->second._answer_location << " -> " << fname << "\n"; + out << "//////////////////\n"; + out << "static int " << def._wrapper_name << "(PyObject *self, PyObject *arg) {\n"; + out << " " << cClassName << " *local_this = NULL;\n"; + out << " if (!Dtool_Call_ExtractThisPointer(self, Dtool_" << ClassName << ", (void **)&local_this)) {\n"; + out << " return -1;\n"; + out << " }\n\n"; + + string expected_params; + write_function_forset(out, def._remaps, 1, 1, expected_params, 2, true, true, + AT_single_arg, RF_compare, false, true); + + out << " if (!_PyErr_OCCURRED()) {\n"; + out << " Dtool_Raise_BadArgumentsError(\n"; + output_quoted(out, 6, expected_params); + out << ");\n"; + out << " }\n"; + out << " return -1;\n"; + out << "}\n\n"; + } + break; + case WT_none: // Nothing special about the wrapper function: just write it normally. string fname = "static PyObject *" + def._wrapper_name + "(PyObject *self, PyObject *args, PyObject *kwds)\n"; @@ -2261,7 +2312,10 @@ write_module_class(ostream &out, Object *obj) { } } - int need_repr = NeedsAReprFunction(obj->_itype); + int need_repr = 0; + if (slots.count("tp_repr") == 0) { + need_repr = NeedsAReprFunction(obj->_itype); + } if (need_repr > 0) { out << "//////////////////\n"; out << "// A __repr__ function\n"; @@ -2292,7 +2346,10 @@ write_module_class(ostream &out, Object *obj) { has_local_repr = true; } - int need_str = NeedsAStrFunction(obj->_itype); + int need_str = 0; + if (slots.count("tp_str") == 0) { + need_str = NeedsAStrFunction(obj->_itype); + } if (need_str > 0) { out << "//////////////////\n"; out << "// A __str__ function\n"; @@ -2332,7 +2389,6 @@ write_module_class(ostream &out, Object *obj) { out << " }\n\n"; out << " switch (op) {\n"; - Function *compare_to_func = NULL; for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) { std::set remaps; Function *func = (*fi); @@ -2349,77 +2405,66 @@ write_module_class(ostream &out, Object *obj) { } const string &fname = func->_ifunc.get_name(); if (fname == "operator <") { - out << " case Py_LT: {\n"; + out << " case Py_LT:\n"; } else if (fname == "operator <=") { - out << " case Py_LE: {\n"; + out << " case Py_LE:\n"; } else if (fname == "operator ==") { - out << " case Py_EQ: {\n"; + out << " case Py_EQ:\n"; } else if (fname == "operator !=") { - out << " case Py_NE: {\n"; + out << " case Py_NE:\n"; } else if (fname == "operator >") { - out << " case Py_GT: {\n"; + out << " case Py_GT:\n"; } else if (fname == "operator >=") { - out << " case Py_GE: {\n"; - } else if (fname == "compare_to") { - compare_to_func = func; - continue; + out << " case Py_GE:\n"; } else { continue; } + out << " {\n"; string expected_params; - write_function_forset(out, remaps, 1, 1, expected_params, 4, true, false, + write_function_forset(out, remaps, 1, 1, expected_params, 6, true, false, AT_single_arg, RF_pyobject | RF_err_null, false); - out << " break;\n"; - out << " }\n"; + out << " break;\n"; + out << " }\n"; has_local_richcompare = true; } out << " }\n\n"; out << " if (_PyErr_OCCURRED()) {\n"; - out << " return (PyObject *)NULL;\n"; + out << " PyErr_Clear();\n"; out << " }\n\n"; - if (compare_to_func != NULL) { + if (slots.count("tp_compare")) { + // A lot of Panda code depends on comparisons being done via the + // compare_to function, which is mapped to the tp_compare slot, which + // Python 3 no longer has. So, we'll write code to fall back to that if + // no matching comparison operator was found. out << "#if PY_MAJOR_VERSION >= 3\n"; out << " // All is not lost; we still have the compare_to function to fall back onto.\n"; - if (compare_to_func->_args_type == AT_single_arg) { - out << " PyObject *result = " << compare_to_func->_name << "(self, arg);\n"; - } else { - out << " PyObject *args = PyTuple_Pack(1, arg);\n"; - out << " PyObject *result = " << compare_to_func->_name << "(self, args);\n"; - out << " Py_DECREF(args);\n"; - } - out << " if (result != NULL) {\n"; - out << " if (PyLong_Check(result)) {;\n"; - out << " long cmpval = PyLong_AS_LONG(result);\n"; - out << " switch (op) {\n"; - out << " case Py_LT:\n"; - out << " return PyBool_FromLong(cmpval < 0);\n"; - out << " case Py_LE:\n"; - out << " return PyBool_FromLong(cmpval <= 0);\n"; - out << " case Py_EQ:\n"; - out << " return PyBool_FromLong(cmpval == 0);\n"; - out << " case Py_NE:\n"; - out << " return PyBool_FromLong(cmpval != 0);\n"; - out << " case Py_GT:\n"; - out << " return PyBool_FromLong(cmpval > 0);\n"; - out << " case Py_GE:\n"; - out << " return PyBool_FromLong(cmpval >= 0);\n"; - out << " }\n"; - out << " }\n"; - out << " Py_DECREF(result);\n"; - out << " }\n\n"; - - out << " if (_PyErr_OCCURRED()) {\n"; + out << " int cmpval = " << slots["tp_compare"]._wrapper_name << "(self, arg);\n"; + out << " if (cmpval == -1 && _PyErr_OCCURRED()) {\n"; out << " if (PyErr_ExceptionMatches(PyExc_TypeError)) {\n"; out << " PyErr_Clear();\n"; out << " } else {\n"; out << " return (PyObject *)NULL;\n"; out << " }\n"; out << " }\n"; + out << " switch (op) {\n"; + out << " case Py_LT:\n"; + out << " return PyBool_FromLong(cmpval < 0);\n"; + out << " case Py_LE:\n"; + out << " return PyBool_FromLong(cmpval <= 0);\n"; + out << " case Py_EQ:\n"; + out << " return PyBool_FromLong(cmpval == 0);\n"; + out << " case Py_NE:\n"; + out << " return PyBool_FromLong(cmpval != 0);\n"; + out << " case Py_GT:\n"; + out << " return PyBool_FromLong(cmpval > 0);\n"; + out << " case Py_GE:\n"; + out << " return PyBool_FromLong(cmpval >= 0);\n"; + out << " }\n"; out << "#endif\n\n"; } @@ -2606,15 +2651,17 @@ write_module_class(ostream &out, Object *obj) { write_function_slot(out, 4, slots, "tp_setattr"); // cmpfunc tp_compare; (reserved in Python 3) - if (has_local_hash) { - out << "#if PY_MAJOR_VERSION >= 3\n"; - out << " 0,\n"; - out << "#else\n"; - out << " &DTOOL_PyObject_Compare,\n"; - out << "#endif\n"; + out << "#if PY_MAJOR_VERSION >= 3\n"; + out << " 0, // tp_reserved\n"; + out << "#else\n"; + if (slots.count("tp_compare") != 0) { + write_function_slot(out, 4, slots, "tp_compare"); } else { - out << " 0, // tp_compare\n"; + // We can/should still define a comparison in Python 2 that is more + // meaningful that comparing id(x) with id(y). + out << " &DTOOL_PyObject_ComparePointers,\n"; } + out << "#endif\n"; // reprfunc tp_repr; if (has_local_repr) { @@ -2806,11 +2853,40 @@ write_module_class(ostream &out, Object *obj) { out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_bases = PyTuple_Pack(" << bases.size() << baseargs << ");\n"; } - // get dictionary - out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_dict = PyDict_New();\n"; - out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict, \"DtoolClassDict\", Dtool_" << ClassName << ".As_PyTypeObject().tp_dict);\n"; - int num_nested = obj->_itype.number_of_nested_types(); + int num_dict_items = 1; + + // Go through once to estimate the number of elements the dict will hold. + for (int ni = 0; ni < num_nested; ni++) { + TypeIndex nested_index = obj->_itype.get_nested_type(ni); + if (_objects.count(nested_index) == 0) { + continue; + } + Object *nested_obj = _objects[nested_index]; + assert(nested_obj != (Object *)NULL); + + if (nested_obj->_itype.is_class() || nested_obj->_itype.is_struct()) { + num_dict_items += 2; + + } else if (nested_obj->_itype.is_typedef()) { + ++num_dict_items; + + } else if (nested_obj->_itype.is_enum()) { + CPPEnumType *enum_type = nested_obj->_itype._cpptype->as_enum_type(); + num_dict_items += 2 * enum_type->_elements.size(); + } + } + + // Build type dictionary. The size is just an estimation. + if (num_dict_items > 5) { + out << " PyObject *dict = _PyDict_NewPresized(" << num_dict_items << ");\n"; + } else { + out << " PyObject *dict = PyDict_New();\n"; + } + out << " Dtool_" << ClassName << ".As_PyTypeObject().tp_dict = dict;\n"; + out << " PyDict_SetItemString(dict, \"DtoolClassDict\", dict);\n"; + + // Now go through the nested types again to actually add the dict items. for (int ni = 0; ni < num_nested; ni++) { TypeIndex nested_index = obj->_itype.get_nested_type(ni); if (_objects.count(nested_index) == 0) { @@ -2828,9 +2904,9 @@ write_module_class(ostream &out, Object *obj) { out << " Dtool_PyModuleClassInit_" << ClassName1 << "(NULL);\n"; string name1 = classNameFromCppName(ClassName2, false); string name2 = classNameFromCppName(ClassName2, true); - out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; + out << " PyDict_SetItemString(dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; if (name1 != name2) { - out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict, \"" << name2 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; + out << " PyDict_SetItemString(dict, \"" << name2 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; } } else if (nested_obj->_itype.is_typedef()) { @@ -2849,7 +2925,7 @@ write_module_class(ostream &out, Object *obj) { string ClassName2 = make_safe_name(interrogate_type_name(wrapped)); string name1 = classNameFromCppName(ClassName2, false); - out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; + out << " PyDict_SetItemString(dict, \"" << name1 << "\", (PyObject *)&Dtool_" << ClassName1 << ".As_PyTypeObject());\n"; // No need to support mangled names for nested typedefs; we only added support recently. } else if (nested_obj->_itype.is_enum()) { @@ -2867,9 +2943,9 @@ write_module_class(ostream &out, Object *obj) { name2 = name1; } string enum_value = obj->_itype.get_scoped_name() + "::" + (*ei)->get_simple_name(); - out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict, \"" << name1 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n"; + out << " PyDict_SetItemString(dict, \"" << name1 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n"; if (name1 != name2) { - out << " PyDict_SetItemString(Dtool_" << ClassName << ".As_PyTypeObject().tp_dict, \"" << name2 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n"; + out << " PyDict_SetItemString(dict, \"" << name2 << "\", PyLongOrInt_FromLong(" << enum_value << "));\n"; } } } @@ -5566,7 +5642,13 @@ write_function_instance(ostream &out, FunctionRemap *remap, << "return DTool_PyInit_Finalize(self, " << return_expr << ", &" << CLASS_PREFIX << make_safe_name(itype.get_scoped_name()) << ", true, false);\n"; } else if (TypeManager::is_integer(orig_type)) { - indent(out, indent_level) << "return " << return_expr << ";\n"; + if (return_flags & RF_compare) { + // Make sure it returns -1, 0, or 1, or Python complains with: + // RuntimeWarning: tp_compare didn't return -1, 0 or 1 + indent(out, indent_level) << "return (int)(" << return_expr << " > 0) - (int)(" << return_expr << " < 0);\n"; + } else { + indent(out, indent_level) << "return " << return_expr << ";\n"; + } } else if (TypeManager::is_void(orig_type)) { indent(out, indent_level) << "return 0;\n"; @@ -6613,6 +6695,10 @@ HasAGetClassTypeFunction(const InterrogateType &itype_class) { // Returns 1 if the class defines write(ostream). // // Returns 2 if the class defines write(ostream, int). +// +// Note that if you want specific behavior for Python +// str(), you should just define a __str__ function, +// which maps directly to the appropriate type slot. //////////////////////////////////////////////////////////////////// int InterfaceMakerPythonNative:: NeedsAStrFunction(const InterrogateType &itype_class) { @@ -6682,6 +6768,10 @@ NeedsAStrFunction(const InterrogateType &itype_class) { // // Returns 3 if the class defines an extension // function for python_repr(ostream, string). +// +// Note that defining python_repr is deprecated in +// favor of defining a __repr__ that returns a string, +// which maps directly to the appropriate type slot. //////////////////////////////////////////////////////////////////// int InterfaceMakerPythonNative:: NeedsAReprFunction(const InterrogateType &itype_class) { diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index 7db5800336..972a589233 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -81,13 +81,17 @@ private: WT_inplace_binary_operator, WT_inplace_ternary_operator, WT_traverse, + WT_compare, }; // This enum is passed to the wrapper generation functions to indicate // what sort of values the wrapper function is expected to return. enum ReturnFlags { // -1 on failure, 0 on success. - RF_int = 0x100, + RF_int = 0x100, + + // Like RF_int, but special case that it returns -1, 0, or 1. + RF_compare = RF_int | 0x200, // Returns the actual return value as PyObject*. RF_pyobject = 0x010, @@ -104,7 +108,7 @@ private: RF_err_false = 0x008, // Decref temporary args object before returning. - RF_decref_args = 0x200, + RF_decref_args = 0x1000, }; class SlottedFunctionDef { diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 911ae81b36..fa78d89664 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -834,7 +834,7 @@ is_string(CPPType *type) { break; } - return is_basic_string_wchar(type); + return is_basic_string_char(type); } //////////////////////////////////////////////////////////////////// diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index f90a938bd8..3edfffe89c 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -637,6 +637,30 @@ inline long DTool_HashKey(PyObject * inst) XXX of error. */ +int DTOOL_PyObject_ComparePointers(PyObject *v1, PyObject *v2) { + // try this compare + void *v1_this = DTOOL_Call_GetPointerThis(v1); + void *v2_this = DTOOL_Call_GetPointerThis(v2); + if (v1_this != NULL && v2_this != NULL) { // both are our types... + if (v1_this < v2_this) { + return -1; + } + if (v1_this > v2_this) { + return 1; + } + return 0; + } + + // ok self compare... + if (v1 < v2) { + return -1; + } + if (v1 > v2) { + return 1; + } + return 0; +} + int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2) { // First try compareTo function.. PyObject * func = PyObject_GetAttrString(v1, "compare_to"); @@ -685,27 +709,7 @@ int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2) { } } - // try this compare - void *v1_this = DTOOL_Call_GetPointerThis(v1); - void *v2_this = DTOOL_Call_GetPointerThis(v2); - if (v1_this != NULL && v2_this != NULL) { // both are our types... - if (v1_this < v2_this) { - return -1; - } - if (v1_this > v2_this) { - return 1; - } - return 0; - } - - // ok self compare... - if (v1 < v2) { - return -1; - } - if (v1 > v2) { - return 1; - } - return 0; + return DTOOL_PyObject_ComparePointers(v1, v2); } PyObject *DTOOL_PyObject_RichCompare(PyObject *v1, PyObject *v2, int op) { diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index 16c1574cc8..e05f90794e 100755 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -532,6 +532,7 @@ EXPCL_DTOOLCONFIG long DTool_HashKey(PyObject * inst) XXX of error. */ +EXPCL_DTOOLCONFIG int DTOOL_PyObject_ComparePointers(PyObject *v1, PyObject *v2); EXPCL_DTOOLCONFIG int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2); EXPCL_DTOOLCONFIG PyObject *DTOOL_PyObject_RichCompare(PyObject *v1, PyObject *v2, int op); diff --git a/panda/src/express/filename_ext.cxx b/panda/src/express/filename_ext.cxx index 6c4017a9c8..70d5bfba2c 100644 --- a/panda/src/express/filename_ext.cxx +++ b/panda/src/express/filename_ext.cxx @@ -36,6 +36,38 @@ __reduce__(PyObject *self) const { return result; } +//////////////////////////////////////////////////////////////////// +// Function: Extension::__repr__ +// Access: Published +// Description: Returns a string representation of the filename that +// communicates both its type and value. +//////////////////////////////////////////////////////////////////// +PyObject *Extension:: +__repr__() const { +#if PY_MAJOR_VERSION >= 3 + // Python 3 case: return a unicode object. + wstring filename = _this->get_fullpath_w(); + PyObject *str = PyUnicode_FromWideChar(filename.data(), (Py_ssize_t)filename.size()); + +#if PY_VERSION_HEX >= 0x03040000 + PyObject *result = PyUnicode_FromFormat("Filename(%R)", str); +#else + static PyObject *format = PyUnicode_FromString("Filename(%r)"); + PyObject *result = PyUnicode_Format(format, str); +#endif + +#else + // Python 2 case: return a regular string. + string filename = _this->get_fullpath(); + PyObject *str = PyString_FromStringAndSize(filename.data(), (Py_ssize_t)filename.size()); + static PyObject *format = PyString_FromString("Filename(%r)"); + PyObject *result = PyString_Format(format, str); +#endif + + Py_DECREF(str); + return result; +} + //////////////////////////////////////////////////////////////////// // Function: Extension::scan_directory // Access: Published diff --git a/panda/src/express/filename_ext.h b/panda/src/express/filename_ext.h index 7c7ef0dc17..866f8f41a4 100644 --- a/panda/src/express/filename_ext.h +++ b/panda/src/express/filename_ext.h @@ -33,6 +33,7 @@ template<> class Extension : public ExtensionBase { public: PyObject *__reduce__(PyObject *self) const; + PyObject *__repr__() const; PyObject *scan_directory() const; }; diff --git a/panda/src/linmath/lmatrix3_ext_src.I b/panda/src/linmath/lmatrix3_ext_src.I index cf917c34fa..f6aa52a247 100644 --- a/panda/src/linmath/lmatrix3_ext_src.I +++ b/panda/src/linmath/lmatrix3_ext_src.I @@ -30,7 +30,7 @@ __reduce__(PyObject *self) const { return NULL; } - PyObject *result = Py_BuildValue("(O(fffffffff))", this_class, + PyObject *result = Py_BuildValue("(O(fffffffff))", this_class, _this->_m(0, 0), _this->_m(0, 1), _this->_m(0, 2), _this->_m(1, 0), _this->_m(1, 1), _this->_m(1, 2), _this->_m(2, 0), _this->_m(2, 1), _this->_m(2, 2)); @@ -40,13 +40,14 @@ __reduce__(PyObject *self) const { } //////////////////////////////////////////////////////////////////// -// Function: LMatrix3::python_repr +// Function: LMatrix3::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LMatrix3" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_m(0, 0)) << ", " << MAYBE_ZERO(_this->_m(0, 1)) << ", " << MAYBE_ZERO(_this->_m(0, 2)) << ", " @@ -58,5 +59,5 @@ python_repr(ostream &out, const string &class_name) const { << MAYBE_ZERO(_this->_m(2, 0)) << ", " << MAYBE_ZERO(_this->_m(2, 1)) << ", " << MAYBE_ZERO(_this->_m(2, 2)) << ")"; + return out.str(); } - diff --git a/panda/src/linmath/lmatrix3_ext_src.h b/panda/src/linmath/lmatrix3_ext_src.h index dee0eb434d..99583af4bb 100644 --- a/panda/src/linmath/lmatrix3_ext_src.h +++ b/panda/src/linmath/lmatrix3_ext_src.h @@ -23,7 +23,7 @@ template<> class Extension : public ExtensionBase { public: INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; }; #include "lmatrix3_ext_src.I" diff --git a/panda/src/linmath/lmatrix3_src.h b/panda/src/linmath/lmatrix3_src.h index 4d48ab782a..8bcae35c6c 100644 --- a/panda/src/linmath/lmatrix3_src.h +++ b/panda/src/linmath/lmatrix3_src.h @@ -291,7 +291,7 @@ PUBLISHED: void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; void generate_hash( diff --git a/panda/src/linmath/lmatrix4_ext_src.I b/panda/src/linmath/lmatrix4_ext_src.I index a9f5992dd5..4cc50e89a8 100644 --- a/panda/src/linmath/lmatrix4_ext_src.I +++ b/panda/src/linmath/lmatrix4_ext_src.I @@ -41,13 +41,14 @@ __reduce__(PyObject *self) const { } //////////////////////////////////////////////////////////////////// -// Function: LMatrix4::python_repr +// Function: LMatrix4::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LMatrix4" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_m(0, 0)) << ", " << MAYBE_ZERO(_this->_m(0, 1)) << ", " << MAYBE_ZERO(_this->_m(0, 2)) << ", " @@ -67,5 +68,5 @@ python_repr(ostream &out, const string &class_name) const { << MAYBE_ZERO(_this->_m(3, 1)) << ", " << MAYBE_ZERO(_this->_m(3, 2)) << ", " << MAYBE_ZERO(_this->_m(3, 3)) << ")"; + return out.str(); } - diff --git a/panda/src/linmath/lmatrix4_ext_src.h b/panda/src/linmath/lmatrix4_ext_src.h index 405ebdd9c5..268d9b615e 100644 --- a/panda/src/linmath/lmatrix4_ext_src.h +++ b/panda/src/linmath/lmatrix4_ext_src.h @@ -23,7 +23,7 @@ template<> class Extension : public ExtensionBase { public: INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; }; #include "lmatrix4_ext_src.I" diff --git a/panda/src/linmath/lmatrix4_src.h b/panda/src/linmath/lmatrix4_src.h index 7a8e90564b..14fe9fe869 100644 --- a/panda/src/linmath/lmatrix4_src.h +++ b/panda/src/linmath/lmatrix4_src.h @@ -265,7 +265,7 @@ PUBLISHED: void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen) const; void generate_hash(ChecksumHashGenerator &hashgen, FLOATTYPE scale) const; diff --git a/panda/src/linmath/lpoint2_ext_src.I b/panda/src/linmath/lpoint2_ext_src.I index 3b66477d6d..ba9eb8e1ca 100644 --- a/panda/src/linmath/lpoint2_ext_src.I +++ b/panda/src/linmath/lpoint2_ext_src.I @@ -23,15 +23,17 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LPoint2::python_repr +// Function: LPoint2::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LPoint2" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lpoint2_ext_src.h b/panda/src/linmath/lpoint2_ext_src.h index 83620bbf48..2bf9a6c8f9 100644 --- a/panda/src/linmath/lpoint2_ext_src.h +++ b/panda/src/linmath/lpoint2_ext_src.h @@ -24,7 +24,7 @@ class Extension : public ExtensionBase { public: INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; }; #include "lpoint2_ext_src.I" diff --git a/panda/src/linmath/lpoint2_src.h b/panda/src/linmath/lpoint2_src.h index 5218cfc483..03b264ffdc 100644 --- a/panda/src/linmath/lpoint2_src.h +++ b/panda/src/linmath/lpoint2_src.h @@ -54,7 +54,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint2) project(const FLOATNAME(LVecBase2) &onto) const; #endif - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); public: static TypeHandle get_class_type() { diff --git a/panda/src/linmath/lpoint3_ext_src.I b/panda/src/linmath/lpoint3_ext_src.I index 2eaca34737..79215517a5 100644 --- a/panda/src/linmath/lpoint3_ext_src.I +++ b/panda/src/linmath/lpoint3_ext_src.I @@ -23,16 +23,18 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LPoint3::python_repr +// Function: LPoint3::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LPoint3" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ", " << MAYBE_ZERO(_this->_v(2)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lpoint3_ext_src.h b/panda/src/linmath/lpoint3_ext_src.h index 2e4c38f3e1..e9131b891d 100644 --- a/panda/src/linmath/lpoint3_ext_src.h +++ b/panda/src/linmath/lpoint3_ext_src.h @@ -24,7 +24,7 @@ class Extension : public ExtensionBase { public: INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; }; #include "lpoint3_ext_src.I" diff --git a/panda/src/linmath/lpoint3_src.h b/panda/src/linmath/lpoint3_src.h index 11c1ccc29d..76e06982d4 100644 --- a/panda/src/linmath/lpoint3_src.h +++ b/panda/src/linmath/lpoint3_src.h @@ -75,7 +75,7 @@ PUBLISHED: FLOATTYPE up, CoordinateSystem cs = CS_default); - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); public: static TypeHandle get_class_type() { diff --git a/panda/src/linmath/lpoint4_ext_src.I b/panda/src/linmath/lpoint4_ext_src.I index 9a89e56a0a..88a83d20d5 100644 --- a/panda/src/linmath/lpoint4_ext_src.I +++ b/panda/src/linmath/lpoint4_ext_src.I @@ -23,17 +23,19 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LPoint4::python_repr +// Function: LPoint4::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LPoint4" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ", " << MAYBE_ZERO(_this->_v(2)) << ", " << MAYBE_ZERO(_this->_v(3)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lpoint4_ext_src.h b/panda/src/linmath/lpoint4_ext_src.h index 93c59ca58c..05d1e4b3c2 100644 --- a/panda/src/linmath/lpoint4_ext_src.h +++ b/panda/src/linmath/lpoint4_ext_src.h @@ -24,7 +24,7 @@ class Extension : public ExtensionBase { public: INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; }; #include "lpoint4_ext_src.I" diff --git a/panda/src/linmath/lpoint4_src.h b/panda/src/linmath/lpoint4_src.h index 877c3fe766..b71e328c62 100644 --- a/panda/src/linmath/lpoint4_src.h +++ b/panda/src/linmath/lpoint4_src.h @@ -56,7 +56,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LPoint4) project(const FLOATNAME(LVecBase4) &onto) const; #endif - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); public: static TypeHandle get_class_type() { diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index 1498b8a32b..8a2c8221b4 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -29,15 +29,17 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LVecBase2::python_repr +// Function: LVecBase2::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LVecBase2" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lvecBase2_ext_src.h b/panda/src/linmath/lvecBase2_ext_src.h index 15ea7fa0c3..c19c8a49d4 100644 --- a/panda/src/linmath/lvecBase2_ext_src.h +++ b/panda/src/linmath/lvecBase2_ext_src.h @@ -25,7 +25,7 @@ public: INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; INLINE_LINMATH FLOATNAME(LVecBase2) __pow__(FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); diff --git a/panda/src/linmath/lvecBase2_src.h b/panda/src/linmath/lvecBase2_src.h index 7983c04e7d..5cb049429e 100644 --- a/panda/src/linmath/lvecBase2_src.h +++ b/panda/src/linmath/lvecBase2_src.h @@ -144,7 +144,7 @@ PUBLISHED: INLINE_LINMATH bool almost_equal(const FLOATNAME(LVecBase2) &other) const; INLINE_LINMATH void output(ostream &out) const; - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const; INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source); diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index 2aa1f0420a..6ecd5eefe0 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -29,16 +29,18 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LVecBase3::python_repr +// Function: LVecBase3::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LVecBase3" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ", " << MAYBE_ZERO(_this->_v(2)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lvecBase3_ext_src.h b/panda/src/linmath/lvecBase3_ext_src.h index 69e7ed929d..cf9f60a0d7 100644 --- a/panda/src/linmath/lvecBase3_ext_src.h +++ b/panda/src/linmath/lvecBase3_ext_src.h @@ -25,7 +25,7 @@ public: INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; INLINE_LINMATH FLOATNAME(LVecBase3) __pow__(FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); diff --git a/panda/src/linmath/lvecBase3_src.h b/panda/src/linmath/lvecBase3_src.h index e6567428c2..c126e0fb6c 100644 --- a/panda/src/linmath/lvecBase3_src.h +++ b/panda/src/linmath/lvecBase3_src.h @@ -159,7 +159,7 @@ PUBLISHED: INLINE_LINMATH bool almost_equal(const FLOATNAME(LVecBase3) &other) const; INLINE_LINMATH void output(ostream &out) const; - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const; INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source); diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index b1e624dc6f..a0400690a5 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -29,17 +29,19 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LVecBase4::python_repr +// Function: LVecBase4::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LVecBase4" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ", " << MAYBE_ZERO(_this->_v(2)) << ", " << MAYBE_ZERO(_this->_v(3)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lvecBase4_ext_src.h b/panda/src/linmath/lvecBase4_ext_src.h index e25341c50a..97924376ba 100644 --- a/panda/src/linmath/lvecBase4_ext_src.h +++ b/panda/src/linmath/lvecBase4_ext_src.h @@ -25,7 +25,7 @@ public: INLINE_LINMATH PyObject *__reduce__(PyObject *self) const; INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; INLINE_LINMATH FLOATNAME(LVecBase4) __pow__(FLOATTYPE exponent) const; INLINE_LINMATH PyObject *__ipow__(PyObject *self, FLOATTYPE exponent); diff --git a/panda/src/linmath/lvecBase4_src.h b/panda/src/linmath/lvecBase4_src.h index ff226b747f..4abd48ed98 100644 --- a/panda/src/linmath/lvecBase4_src.h +++ b/panda/src/linmath/lvecBase4_src.h @@ -163,7 +163,7 @@ PUBLISHED: INLINE_LINMATH bool almost_equal(const FLOATNAME(LVecBase4) &other) const; INLINE_LINMATH void output(ostream &out) const; - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); INLINE_LINMATH void write_datagram_fixed(Datagram &destination) const; INLINE_LINMATH void read_datagram_fixed(DatagramIterator &source); diff --git a/panda/src/linmath/lvector2_ext_src.I b/panda/src/linmath/lvector2_ext_src.I index 42db030bce..e0ae2bea6d 100644 --- a/panda/src/linmath/lvector2_ext_src.I +++ b/panda/src/linmath/lvector2_ext_src.I @@ -23,15 +23,17 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LVector2::python_repr +// Function: LVector2::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LVector2" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lvector2_ext_src.h b/panda/src/linmath/lvector2_ext_src.h index 00c410d96b..56a48aeaa3 100644 --- a/panda/src/linmath/lvector2_ext_src.h +++ b/panda/src/linmath/lvector2_ext_src.h @@ -24,7 +24,7 @@ class Extension : public ExtensionBase public: INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; }; #include "lvector2_ext_src.I" diff --git a/panda/src/linmath/lvector2_src.h b/panda/src/linmath/lvector2_src.h index 417379b37f..81b2475af6 100644 --- a/panda/src/linmath/lvector2_src.h +++ b/panda/src/linmath/lvector2_src.h @@ -49,7 +49,7 @@ PUBLISHED: INLINE_LINMATH FLOATTYPE signed_angle_deg(const FLOATNAME(LVector2) &other) const; #endif - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); public: static TypeHandle get_class_type() { diff --git a/panda/src/linmath/lvector3_ext_src.I b/panda/src/linmath/lvector3_ext_src.I index 6aa0897546..451b713dee 100644 --- a/panda/src/linmath/lvector3_ext_src.I +++ b/panda/src/linmath/lvector3_ext_src.I @@ -23,16 +23,18 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LVector3::python_repr +// Function: LVector3::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LVector3" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ", " << MAYBE_ZERO(_this->_v(2)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lvector3_ext_src.h b/panda/src/linmath/lvector3_ext_src.h index 11e496e8b6..33ab4ab140 100644 --- a/panda/src/linmath/lvector3_ext_src.h +++ b/panda/src/linmath/lvector3_ext_src.h @@ -24,7 +24,7 @@ class Extension : public ExtensionBase public: INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; }; #include "lvector3_ext_src.I" diff --git a/panda/src/linmath/lvector3_src.h b/panda/src/linmath/lvector3_src.h index bac80207a4..7fc0316b06 100644 --- a/panda/src/linmath/lvector3_src.h +++ b/panda/src/linmath/lvector3_src.h @@ -85,7 +85,7 @@ PUBLISHED: INLINE_LINMATH static FLOATNAME(LVector3) rfu(FLOATTYPE right, FLOATTYPE fwd,FLOATTYPE up, CoordinateSystem cs = CS_default); - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); public: static TypeHandle get_class_type() { diff --git a/panda/src/linmath/lvector4_ext_src.I b/panda/src/linmath/lvector4_ext_src.I index fa96998001..04edba6a06 100644 --- a/panda/src/linmath/lvector4_ext_src.I +++ b/panda/src/linmath/lvector4_ext_src.I @@ -23,17 +23,19 @@ #endif //////////////////////////////////////////////////////////////////// -// Function: LVector4::python_repr +// Function: LVector4::__repr__ // Access: Published // Description: //////////////////////////////////////////////////////////////////// -INLINE_LINMATH void Extension:: -python_repr(ostream &out, const string &class_name) const { - out << class_name << "(" +INLINE_LINMATH string Extension:: +__repr__() const { + ostringstream out; + out << "LVector4" << FLOATTOKEN << "(" << MAYBE_ZERO(_this->_v(0)) << ", " << MAYBE_ZERO(_this->_v(1)) << ", " << MAYBE_ZERO(_this->_v(2)) << ", " << MAYBE_ZERO(_this->_v(3)) << ")"; + return out.str(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lvector4_ext_src.h b/panda/src/linmath/lvector4_ext_src.h index 9eb1bc2a92..5bc319ad13 100644 --- a/panda/src/linmath/lvector4_ext_src.h +++ b/panda/src/linmath/lvector4_ext_src.h @@ -24,7 +24,7 @@ class Extension : public ExtensionBase public: INLINE_LINMATH PyObject *__getattr__(const string &attr_name) const; INLINE_LINMATH int __setattr__(PyObject *self, const string &attr_name, PyObject *assign); - INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const; + INLINE_LINMATH string __repr__() const; }; #include "lvector4_ext_src.I" diff --git a/panda/src/linmath/lvector4_src.h b/panda/src/linmath/lvector4_src.h index 179ccfdbfd..1cce8f0db5 100644 --- a/panda/src/linmath/lvector4_src.h +++ b/panda/src/linmath/lvector4_src.h @@ -50,7 +50,7 @@ PUBLISHED: INLINE_LINMATH FLOATNAME(LVector4) project(const FLOATNAME(LVecBase4) &onto) const; #endif - EXTENSION(INLINE_LINMATH void python_repr(ostream &out, const string &class_name) const); + EXTENSION(INLINE_LINMATH string __repr__() const); public: static TypeHandle get_class_type() {