Fix tp_compare, better __repr__/__str__ handling

This commit is contained in:
rdb 2015-03-25 17:34:19 +01:00
parent b894954fda
commit 3371df8403
55 changed files with 328 additions and 183 deletions

View File

@ -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))

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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')):

View File

@ -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)

View File

@ -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:

View File

@ -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] == '.':

View File

@ -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)

View File

@ -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():

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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<FunctionRemap*> 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) {

View File

@ -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 {

View File

@ -834,7 +834,7 @@ is_string(CPPType *type) {
break;
}
return is_basic_string_wchar(type);
return is_basic_string_char(type);
}
////////////////////////////////////////////////////////////////////

View File

@ -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) {

View File

@ -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);

View File

@ -36,6 +36,38 @@ __reduce__(PyObject *self) const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: Extension<Filename>::__repr__
// Access: Published
// Description: Returns a string representation of the filename that
// communicates both its type and value.
////////////////////////////////////////////////////////////////////
PyObject *Extension<Filename>::
__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<Filename>::scan_directory
// Access: Published

View File

@ -33,6 +33,7 @@ template<>
class Extension<Filename> : public ExtensionBase<Filename> {
public:
PyObject *__reduce__(PyObject *self) const;
PyObject *__repr__() const;
PyObject *scan_directory() const;
};

View File

@ -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<FLOATNAME(LMatrix3)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LMatrix3)>::
__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();
}

View File

@ -23,7 +23,7 @@ template<>
class Extension<FLOATNAME(LMatrix3)> : public ExtensionBase<FLOATNAME(LMatrix3)> {
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"

View File

@ -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(

View File

@ -41,13 +41,14 @@ __reduce__(PyObject *self) const {
}
////////////////////////////////////////////////////////////////////
// Function: LMatrix4::python_repr
// Function: LMatrix4::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LMatrix4)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LMatrix4)>::
__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();
}

View File

@ -23,7 +23,7 @@ template<>
class Extension<FLOATNAME(LMatrix4)> : public ExtensionBase<FLOATNAME(LMatrix4)> {
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"

View File

@ -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;

View File

@ -23,15 +23,17 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LPoint2::python_repr
// Function: LPoint2::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LPoint2)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LPoint2)>::
__repr__() const {
ostringstream out;
out << "LPoint2" << FLOATTOKEN << "("
<< MAYBE_ZERO(_this->_v(0)) << ", "
<< MAYBE_ZERO(_this->_v(1)) << ")";
return out.str();
}
////////////////////////////////////////////////////////////////////

View File

@ -24,7 +24,7 @@ class Extension<FLOATNAME(LPoint2)> : public ExtensionBase<FLOATNAME(LPoint2)> {
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"

View File

@ -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() {

View File

@ -23,16 +23,18 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LPoint3::python_repr
// Function: LPoint3::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LPoint3)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LPoint3)>::
__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();
}
////////////////////////////////////////////////////////////////////

View File

@ -24,7 +24,7 @@ class Extension<FLOATNAME(LPoint3)> : public ExtensionBase<FLOATNAME(LPoint3)> {
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"

View File

@ -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() {

View File

@ -23,17 +23,19 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LPoint4::python_repr
// Function: LPoint4::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LPoint4)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LPoint4)>::
__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();
}
////////////////////////////////////////////////////////////////////

View File

@ -24,7 +24,7 @@ class Extension<FLOATNAME(LPoint4)> : public ExtensionBase<FLOATNAME(LPoint4)> {
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"

View File

@ -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() {

View File

@ -29,15 +29,17 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LVecBase2::python_repr
// Function: LVecBase2::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LVecBase2)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LVecBase2)>::
__repr__() const {
ostringstream out;
out << "LVecBase2" << FLOATTOKEN << "("
<< MAYBE_ZERO(_this->_v(0)) << ", "
<< MAYBE_ZERO(_this->_v(1)) << ")";
return out.str();
}
////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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);

View File

@ -29,16 +29,18 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LVecBase3::python_repr
// Function: LVecBase3::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LVecBase3)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LVecBase3)>::
__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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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);

View File

@ -29,17 +29,19 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LVecBase4::python_repr
// Function: LVecBase4::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LVecBase4)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LVecBase4)>::
__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();
}
////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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);

View File

@ -23,15 +23,17 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LVector2::python_repr
// Function: LVector2::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LVector2)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LVector2)>::
__repr__() const {
ostringstream out;
out << "LVector2" << FLOATTOKEN << "("
<< MAYBE_ZERO(_this->_v(0)) << ", "
<< MAYBE_ZERO(_this->_v(1)) << ")";
return out.str();
}
////////////////////////////////////////////////////////////////////

View File

@ -24,7 +24,7 @@ class Extension<FLOATNAME(LVector2)> : public ExtensionBase<FLOATNAME(LVector2)>
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"

View File

@ -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() {

View File

@ -23,16 +23,18 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LVector3::python_repr
// Function: LVector3::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LVector3)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LVector3)>::
__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();
}
////////////////////////////////////////////////////////////////////

View File

@ -24,7 +24,7 @@ class Extension<FLOATNAME(LVector3)> : public ExtensionBase<FLOATNAME(LVector3)>
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"

View File

@ -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() {

View File

@ -23,17 +23,19 @@
#endif
////////////////////////////////////////////////////////////////////
// Function: LVector4::python_repr
// Function: LVector4::__repr__
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE_LINMATH void Extension<FLOATNAME(LVector4)>::
python_repr(ostream &out, const string &class_name) const {
out << class_name << "("
INLINE_LINMATH string Extension<FLOATNAME(LVector4)>::
__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();
}
////////////////////////////////////////////////////////////////////

View File

@ -24,7 +24,7 @@ class Extension<FLOATNAME(LVector4)> : public ExtensionBase<FLOATNAME(LVector4)>
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"

View File

@ -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() {