diff -r 7794f1e8576e Lib/test/test_msilib.py --- a/Lib/test/test_msilib.py Sat May 28 20:02:44 2011 +0800 +++ b/Lib/test/test_msilib.py Sat May 28 21:52:52 2011 +0800 @@ -1,8 +1,31 @@ """ Test suite for the code in msilib """ import unittest -import os -from test.support import run_unittest, import_module -msilib = import_module('msilib') +from test import support +import datetime + +msilib = support.import_module('msilib') +import msilib.schema + + +LAST_PRINTED_DATE = datetime.datetime(2011, 5, 30, 10, 55, 56) + +def create_temp_db(): + "Create a very simple database to open" + path = support.TESTFN + ".msi" + db = msilib.init_database( + path, msilib.schema, "Python Tests", "product_code", "1.0", "PSF") + db.Commit() + # set a FILETIME property so that we can test retrieving it + si = db.GetSummaryInformation(20) + si.SetProperty( + msilib.PID_LASTPRINTED, LAST_PRINTED_DATE) + si.Persist() + db.Commit() + db = None + return path + +TEST_DB_PATH = create_temp_db() + class Test_make_id(unittest.TestCase): #http://msdn.microsoft.com/en-us/library/aa369212(v=vs.85).aspx @@ -35,12 +58,37 @@ def test_invalid_any_char(self): self.assertEqual( msilib.make_id(".s\x82ort"), "_.s_ort") - self.assertEqual ( + self.assertEqual( msilib.make_id(".s\x82o?*+rt"), "_.s_o___rt") +class TestSummaryInformation(unittest.TestCase): + + def tearDown(self): + self.db = None + + def test_get_property_count(self): + self.db = msilib.OpenDatabase(TEST_DB_PATH, msilib.MSIDBOPEN_READONLY) + si = self.db.GetSummaryInformation(0) + self.assertEqual(si.GetPropertyCount(), 9) + + def test_get_property(self): + self.db = msilib.OpenDatabase(TEST_DB_PATH, msilib.MSIDBOPEN_READONLY) + si = self.db.GetSummaryInformation(0) + self.assertEqual(si.GetProperty(msilib.PID_AUTHOR), b'PSF') + self.assertEqual(si.GetProperty(msilib. PID_WORDCOUNT), 2) + self.assertEqual( + si.GetProperty(msilib.PID_LASTPRINTED), LAST_PRINTED_DATE) + + def test_set_property(self): + self.db = msilib.OpenDatabase(TEST_DB_PATH, msilib.MSIDBOPEN_READONLY) + si = self.db.GetSummaryInformation(0) + + def test_main(): - run_unittest(__name__) + support.run_unittest(__name__) + support.unlink(TEST_DB_PATH) + if __name__ == '__main__': test_main() diff -r 7794f1e8576e PC/_msi.c --- a/PC/_msi.c Sat May 28 20:02:44 2011 +0800 +++ b/PC/_msi.c Sat May 28 21:52:52 2011 +0800 @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -532,9 +533,11 @@ UINT type; INT ival; FILETIME fval; + SYSTEMTIME systime; char sbuf[1000]; char *sval = sbuf; DWORD ssize = sizeof(sval); + PyDateTime_IMPORT; if (!PyArg_ParseTuple(args, "i:GetProperty", &field)) return NULL; @@ -551,8 +554,16 @@ case VT_I2: case VT_I4: return PyLong_FromLong(ival); case VT_FILETIME: - PyErr_SetString(PyExc_NotImplementedError, "FILETIME result"); - return NULL; + + // returns zero on failure + status = FileTimeToSystemTime(&fval, &systime); + if (!status) { + PyErr_SetString(MSIError, "could not convert FILETIME to datetime"); + return NULL; + } + result = PyDateTime_FromDateAndTime(systime.wYear, systime.wMonth, systime.wDay, + systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds/1000); + return result; case VT_LPSTR: result = PyBytes_FromStringAndSize(sval, ssize); if (sval != sbuf) @@ -582,6 +593,7 @@ int status; int field; PyObject* data; + PyDateTime_IMPORT; if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data)) return NULL; @@ -596,6 +608,24 @@ } status = MsiSummaryInfoSetProperty(si->h, field, VT_I4, value, NULL, NULL); + } else if (PyDateTime_CheckExact(data)) { + SYSTEMTIME systime; + FILETIME fval; + systime.wYear = PyDateTime_GET_YEAR(data); + systime.wMonth = PyDateTime_GET_MONTH(data); + systime.wDay = PyDateTime_GET_DAY(data); + systime.wHour = PyDateTime_DATE_GET_HOUR(data); + systime.wMinute = PyDateTime_DATE_GET_MINUTE(data); + systime.wSecond = PyDateTime_DATE_GET_SECOND(data); + systime.wMilliseconds = PyDateTime_DATE_GET_MICROSECOND(data) * 1000; + + status = SystemTimeToFileTime(&systime, &fval); + if (!status) { + PyErr_SetString(PyExc_ValueError, "error converting to FILETIME"); + return NULL; + } + status = MsiSummaryInfoSetPropertyW(si->h, field, VT_FILETIME, + 0, &fval, NULL); } else { PyErr_SetString(PyExc_TypeError, "unsupported type"); return NULL;