Update of /cvsroot/pywin32/pywin32/com/win32com/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24405/src
Modified Files:
PyComHelpers.cpp PythonCOM.cpp oleargs.cpp univgw_dataconv.cpp
Log Message:
With help from Roger Upole:
* Add PyObject_AsCurrency and PyObject_FromCurrency to convert CY/CURRENCY
structs to/from Python objects.
* Invent a pythoncom.__future_currency__ scheme, allowing us to move from
the current brain-dead (hiword, loword) currency support into a
decimal.Decimal() object.
See win32com\readme.html for more details.
Index: univgw_dataconv.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/com/win32com/src/univgw_dataconv.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** univgw_dataconv.cpp 14 Dec 2004 10:19:35 -0000 1.7
--- univgw_dataconv.cpp 31 May 2005 12:36:02 -0000 1.8
***************
*** 536,543 ****
{
DATE *pdbl = *(DATE **)pbArg;
- if ( !PyTime_Check(obOutValue) )
- {
- goto Error;
- }
if ( !PyWinObject_AsDATE(obOutValue, pdbl) )
{
--- 536,539 ----
***************
*** 549,564 ****
{
CY *pcy = *(CY **)pbArg;
! if (!PyTuple_Check(obOutValue) || PyTuple_Size(obOutValue) != 2 ||
! !PyLong_Check(PyTuple_GET_ITEM(obOutValue, 0)) ||
! !PyLong_Check(PyTuple_GET_ITEM(obOutValue, 1)))
! {
! PyErr_Format(
! PyExc_TypeError,
! "Return value[%d] is a VT_CY which requires a tuple "
! "containing two Python longs.", i);
goto Error;
- }
- pcy->Hi = PyLong_AsLong(PyTuple_GET_ITEM(obOutValue, 0));
- pcy->Lo = PyLong_AsLong(PyTuple_GET_ITEM(obOutValue, 1));
break;
}
--- 545,550 ----
{
CY *pcy = *(CY **)pbArg;
! if (!PyObject_AsCurrency(obOutValue, pcy))
goto Error;
break;
}
Index: PythonCOM.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/com/win32com/src/PythonCOM.cpp,v
retrieving revision 1.35
retrieving revision 1.36
diff -C2 -d -r1.35 -r1.36
*** PythonCOM.cpp 24 May 2005 14:45:01 -0000 1.35
--- PythonCOM.cpp 31 May 2005 12:36:02 -0000 1.36
***************
*** 16,19 ****
--- 16,22 ----
#include "PyFactory.h"
+ // keep a reference to pythoncom'm __dict__ so the COM currency format can be looked up dynamically
+ extern PyObject *pythoncom_dict=NULL;
+
extern int PyCom_RegisterCoreIIDs(PyObject *dict);
***************
*** 1718,1721 ****
--- 1721,1726 ----
PyObject *dict = PyModule_GetDict(oModule);
if (!dict) return; /* Another serious error!*/
+ pythoncom_dict=dict;
+
PyDict_SetItemString(dict, "TypeIIDs", g_obPyCom_MapIIDToType);
PyDict_SetItemString(dict, "ServerInterfaces", g_obPyCom_MapGatewayIIDToName);
***************
*** 2061,2065 ****
AddConstant(dict, "dcom", 0 );
}
!
PyObject *obfmtid=NULL;
obfmtid=PyWinObject_FromIID(FMTID_DocSummaryInformation);
--- 2066,2070 ----
AddConstant(dict, "dcom", 0 );
}
! AddConstant(dict, "__future_currency__", 0);
PyObject *obfmtid=NULL;
obfmtid=PyWinObject_FromIID(FMTID_DocSummaryInformation);
Index: PyComHelpers.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/com/win32com/src/PyComHelpers.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** PyComHelpers.cpp 26 Jan 2005 02:29:47 -0000 1.8
--- PyComHelpers.cpp 31 May 2005 12:36:02 -0000 1.9
***************
*** 11,14 ****
--- 11,15 ----
extern PyObject *g_obPyCom_MapIIDToType;
extern PyObject *g_obPyCom_MapServerIIDToGateway;
+ extern PyObject *pythoncom_dict;
// String conversions
***************
*** 66,69 ****
--- 67,152 ----
}
+ // Currency conversions.
+ PyObject *PyObject_FromCurrency(CURRENCY &cy)
+ {
+ static BOOL decimal_imported=FALSE;
+ static PyObject *decimal_module=NULL;
+ static BOOL warned_future_currency=FALSE;
+ PyObject *result = NULL;
+
+ // Use decimal module if available and __future_currency__ evaluates to True, otherwise use old behaviour
+ PyObject *__future_currency__;
+ BOOL use_decimal;
+ __future_currency__=PyDict_GetItemString(pythoncom_dict,"__future_currency__");
+ if (__future_currency__==NULL){ // should not happen !
+ PyErr_Print();
+ use_decimal=FALSE;
+ }
+ else
+ use_decimal=PyObject_IsTrue(__future_currency__);
+ if (!use_decimal && !warned_future_currency) {
+ PyErr_Warn(PyExc_FutureWarning,
+ "Currency objects will soon be changed so a decimal.Decimal instance is used."
+ "\n (set pythoncom.__future_currency__ to get these objects now.)");
+ warned_future_currency = TRUE;
+ }
+
+ if (use_decimal && !decimal_imported){
+ decimal_module=PyImport_ImportModule("decimal");
+ if (!decimal_module) {
+ PyErr_Clear();
+ decimal_module=PyImport_ImportModule("win32com.decimal_23");
+ }
+ decimal_imported=TRUE;
+ if (decimal_module==NULL)
+ PyErr_Print();
+ }
+ if (use_decimal && (decimal_module==NULL)){
+ PyErr_Warn(NULL,"Can't find decimal module, reverting to using tuple for currency");
+ use_decimal=FALSE;
+ }
+ if (!use_decimal)
+ result = Py_BuildValue("ll", cy.Hi, cy.Lo);
+ else {
+ PyObject *unscaled_result;
+ unscaled_result=PyObject_CallMethod(decimal_module, "Decimal", "L", cy.int64);
+ if (unscaled_result!=NULL){
+ result=PyObject_CallMethod(unscaled_result, "__div__", "l", 10000);
+ Py_DECREF(unscaled_result);
+ }
+ }
+ return result;
+ }
+
+ PYCOM_EXPORT BOOL PyObject_AsCurrency(PyObject *ob, CURRENCY *pcy)
+ {
+ if (!PyTuple_Check(ob) || PyTuple_Size(ob) != 2 ||
+ !PyLong_Check(PyTuple_GET_ITEM(ob, 0)) ||
+ !PyLong_Check(PyTuple_GET_ITEM(ob, 1)))
+ {
+ if (strcmp(ob->ob_type->tp_name, "Decimal")==0) {
+ PyObject *scaled = PyObject_CallMethod(ob, "__mul__", "l", 10000);
+ if (!scaled) return FALSE;
+ PyObject *longval = PyNumber_Long(scaled);
+ Py_DECREF(scaled);
+ pcy->int64 = PyLong_AsLongLong(longval);
+ Py_DECREF(longval);
+ if (pcy->int64 == -1 && PyErr_Occurred())
+ return FALSE;
+ } else {
+ PyErr_Format(
+ PyExc_TypeError,
+ "Currency object must be either a tuple of 2 longs or a "
+ "Decimal instance (got %s).",
+ ob->ob_type->tp_name);
+ return FALSE;
+ }
+ } else {
+ pcy->Hi = PyLong_AsLong(PyTuple_GET_ITEM(ob, 0));
+ pcy->Lo = PyLong_AsLong(PyTuple_GET_ITEM(ob, 1));
+ }
+ return TRUE;
+ }
+
// If PyCom_PyObjectFromIUnknown is called with bAddRef==FALSE, the
// caller is asking us to take ownership of the COM reference. If we
Index: oleargs.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/com/win32com/src/oleargs.cpp,v
retrieving revision 1.28
retrieving revision 1.29
diff -C2 -d -r1.28 -r1.29
*** oleargs.cpp 13 Jul 2004 07:30:26 -0000 1.28
--- oleargs.cpp 31 May 2005 12:36:02 -0000 1.29
***************
*** 175,178 ****
--- 175,184 ----
V_VT(var) = VT_RECORD;
}
+ else if (strcmp(obj->ob_type->tp_name, "Decimal")==0)
+ {
+ if (!PyObject_AsCurrency(obj, &V_CY(var)))
+ return FALSE;
+ V_VT(var) = VT_CY;
+ }
/*
else if (obj->ob_type == &AutomatedType)
***************
*** 327,333 ****
case VT_CY:
! // Cheesy support borrowed from:
! // PyIPropertyStorage.cpp.
! result = Py_BuildValue("ll", varValue.cyVal.Hi, varValue.cyVal.Lo);
break;
--- 333,337 ----
case VT_CY:
! result = PyObject_FromCurrency(varValue.cyVal);
break;
|