[CalendarServer-changes] [3308] PyOpenDirectory/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Mon Nov 3 07:34:05 PST 2008
Revision: 3308
http://trac.macosforge.org/projects/calendarserver/changeset/3308
Author: cdaboo at apple.com
Date: 2008-11-03 07:34:04 -0800 (Mon, 03 Nov 2008)
Log Message:
-----------
recordType argument can now be a tuple or list in addition to a string so that more than one
recordType can be queried at a time.
Modified Paths:
--------------
PyOpenDirectory/trunk/pysrc/opendirectory.py
PyOpenDirectory/trunk/src/CDirectoryService.cpp
PyOpenDirectory/trunk/src/CDirectoryService.h
PyOpenDirectory/trunk/src/PythonWrapper.cpp
PyOpenDirectory/trunk/test.py
Modified: PyOpenDirectory/trunk/pysrc/opendirectory.py
===================================================================
--- PyOpenDirectory/trunk/pysrc/opendirectory.py 2008-11-01 00:06:48 UTC (rev 3307)
+++ PyOpenDirectory/trunk/pysrc/opendirectory.py 2008-11-03 15:34:04 UTC (rev 3308)
@@ -34,7 +34,7 @@
is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
@param obj: C{object} the object obtained from an odInit call.
- @param recordType: C{str} containing the OD record type to lookup.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@return: C{dict} containing a C{dict} of attributes for each record found,
or C{None} otherwise.
@@ -51,7 +51,7 @@
@param value: C{str} containing the value to search for.
@param matchType: C{int} DS match type to use when searching.
@param casei: C{True} to do case-insenstive match, C{False} otherwise.
- @param recordType: C{str} containing the OD record type to lookup.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@return: C{dict} containing a C{dict} of attributes for each record found,
or C{None} otherwise.
@@ -66,7 +66,7 @@
@param obj: C{object} the object obtained from an odInit call.
@param compound: C{str} containing the compound search query to use.
@param casei: C{True} to do case-insenstive match, C{False} otherwise.
- @param recordType: C{str} containing the OD record type to lookup.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@return: C{dict} containing a C{dict} of attributes for each record found,
or C{None} otherwise.
@@ -79,7 +79,7 @@
is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
@param obj: C{object} the object obtained from an odInit call.
- @param recordType: C{str} containing the OD record type to lookup.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
for each record found, or C{None} otherwise.
@@ -96,7 +96,7 @@
@param value: C{str} containing the value to search for.
@param matchType: C{int} DS match type to use when searching.
@param casei: C{True} to do case-insenstive match, C{False} otherwise.
- @param recordType: C{str} containing the OD record type to lookup.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
for each record found, or C{None} otherwise.
@@ -111,7 +111,7 @@
@param obj: C{object} the object obtained from an odInit call.
@param compound: C{str} containing the compound search query to use.
@param casei: C{True} to do case-insenstive match, C{False} otherwise.
- @param recordType: C{str} containing the OD record type to lookup.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
for each record found, or C{None} otherwise.
Modified: PyOpenDirectory/trunk/src/CDirectoryService.cpp
===================================================================
--- PyOpenDirectory/trunk/src/CDirectoryService.cpp 2008-11-01 00:06:48 UTC (rev 3307)
+++ PyOpenDirectory/trunk/src/CDirectoryService.cpp 2008-11-03 15:34:04 UTC (rev 3308)
@@ -81,21 +81,21 @@
//
// Get specific attributes for one or more user records in the directory.
//
-// @param recordType: the record type to list.
+// @param recordTypes: the record types to list.
// @param attributes: CFArray of CFString listing the attributes to return for each record.
// @return: CFMutableArrayRef composed of CFMutableArrayRef with a CFStringRef/CFMutableDictionaryRef tuple for
// each record, where the CFStringRef is the record name and CFMutableDictionaryRef of CFStringRef key
// and value entries for each attribute/value requested in the record indexed by uid,
// or NULL if it fails.
//
-CFMutableArrayRef CDirectoryService::ListAllRecordsWithAttributes(const char* recordType, CFDictionaryRef attributes, bool using_python)
+CFMutableArrayRef CDirectoryService::ListAllRecordsWithAttributes(CFArrayRef recordTypes, CFDictionaryRef attributes, bool using_python)
{
try
{
StPythonThreadState threading(using_python);
// Get attribute map
- return _ListAllRecordsWithAttributes(recordType, NULL, attributes);
+ return _ListAllRecordsWithAttributes(recordTypes, NULL, attributes);
}
catch(CDirectoryServiceException& dserror)
{
@@ -118,21 +118,21 @@
// @param value: the value to query.
// @param matchType: the match type to use.
// @param casei: true if case-insensitive match is to be used, false otherwise.
-// @param recordType: the record type to list.
+// @param recordTypes: the record types to list.
// @param attributes: CFArray of CFString listing the attributes to return for each record.
// @return: CFMutableArrayRef composed of CFMutableArrayRef with a CFStringRef/CFMutableDictionaryRef tuple for
// each record, where the CFStringRef is the record name and CFMutableDictionaryRef of CFStringRef key
// and value entries for each attribute/value requested in the record indexed by uid,
// or NULL if it fails.
//
-CFMutableArrayRef CDirectoryService::QueryRecordsWithAttribute(const char* attr, const char* value, int matchType, bool casei, const char* recordType, CFDictionaryRef attributes, bool using_python)
+CFMutableArrayRef CDirectoryService::QueryRecordsWithAttribute(const char* attr, const char* value, int matchType, bool casei, CFArrayRef recordTypes, CFDictionaryRef attributes, bool using_python)
{
try
{
StPythonThreadState threading(using_python);
// Get attribute map
- return _QueryRecordsWithAttributes(attr, value, matchType, NULL, casei, recordType, attributes);
+ return _QueryRecordsWithAttributes(attr, value, matchType, NULL, casei, recordTypes, attributes);
}
catch(CDirectoryServiceException& dserror)
{
@@ -153,21 +153,21 @@
//
// @param query: the compund query string to use.
// @param casei: true if case-insensitive match is to be used, false otherwise.
-// @param recordType: the record type to list.
+// @param recordTypes: the record types to list.
// @param attributes: CFArray of CFString listing the attributes to return for each record.
// @return: CFMutableArrayRef composed of CFMutableArrayRef with a CFStringRef/CFMutableDictionaryRef tuple for
// each record, where the CFStringRef is the record name and CFMutableDictionaryRef of CFStringRef key
// and value entries for each attribute/value requested in the record indexed by uid,
// or NULL if it fails.
//
-CFMutableArrayRef CDirectoryService::QueryRecordsWithAttributes(const char* query, bool casei, const char* recordType, CFDictionaryRef attributes, bool using_python)
+CFMutableArrayRef CDirectoryService::QueryRecordsWithAttributes(const char* query, bool casei, CFArrayRef recordTypes, CFDictionaryRef attributes, bool using_python)
{
try
{
StPythonThreadState threading(using_python);
// Get attribute map
- return _QueryRecordsWithAttributes(NULL, NULL, 0, query, casei, recordType, attributes);
+ return _QueryRecordsWithAttributes(NULL, NULL, 0, query, casei, recordTypes, attributes);
}
catch(CDirectoryServiceException& dserror)
{
@@ -258,7 +258,7 @@
// and value entries for each attribute/value requested in the record indexed by uid,
// or NULL if it fails.
//
-CFMutableArrayRef CDirectoryService::_ListAllRecordsWithAttributes(const char* type, CFArrayRef names, CFDictionaryRef attributes)
+CFMutableArrayRef CDirectoryService::_ListAllRecordsWithAttributes(CFArrayRef recordTypes, CFArrayRef names, CFDictionaryRef attributes)
{
CFMutableArrayRef result = NULL;
CFMutableArrayRef record_tuple = NULL;
@@ -297,7 +297,7 @@
// Build data list of types
recTypes = ::dsDataListAllocate(mDir);
ThrowIfNULL(recTypes);
- ThrowIfDSErr(::dsBuildListFromStringsAlloc(mDir, recTypes, type, NULL));
+ BuildStringDataList(recordTypes, recTypes);
// Build data list of attributes
attrTypes = ::dsDataListAllocate(mDir);
@@ -499,14 +499,14 @@
// @param matchType: the match type to use (0 if compound is being used).
// @param attr: the compound query to use rather than single attribute/value (NULL if compound is not being used).
// @param casei: true if case-insensitive match is to be used, false otherwise.
-// @param type: the record type to check.
+// @param recordTypes: the record type to check.
// @param attributes: a list of attributes to return.
// @return: CFMutableArrayRef composed of CFMutableArrayRef with a CFStringRef/CFMutableDictionaryRef tuple for
// each record, where the CFStringRef is the record name and CFMutableDictionaryRef of CFStringRef key
// and value entries for each attribute/value requested in the record indexed by uid,
// or NULL if it fails.
//
-CFMutableArrayRef CDirectoryService::_QueryRecordsWithAttributes(const char* attr, const char* value, int matchType, const char* compound, bool casei, const char* type, CFDictionaryRef attributes)
+CFMutableArrayRef CDirectoryService::_QueryRecordsWithAttributes(const char* attr, const char* value, int matchType, const char* compound, bool casei, CFArrayRef recordTypes, CFDictionaryRef attributes)
{
CFMutableArrayRef result = NULL;
CFMutableArrayRef record_tuple = NULL;
@@ -563,7 +563,7 @@
// Build data list of types
recTypes = ::dsDataListAllocate(mDir);
ThrowIfNULL(recTypes);
- ThrowIfDSErr(::dsBuildListFromStringsAlloc(mDir, recTypes, type, NULL));
+ BuildStringDataList(recordTypes, recTypes);
// Build data list of attributes
attrTypes = ::dsDataListAllocate(mDir);
Modified: PyOpenDirectory/trunk/src/CDirectoryService.h
===================================================================
--- PyOpenDirectory/trunk/src/CDirectoryService.h 2008-11-01 00:06:48 UTC (rev 3307)
+++ PyOpenDirectory/trunk/src/CDirectoryService.h 2008-11-03 15:34:04 UTC (rev 3308)
@@ -31,9 +31,9 @@
CDirectoryService(const char* nodename);
~CDirectoryService();
- CFMutableArrayRef ListAllRecordsWithAttributes(const char* recordType, CFDictionaryRef attributes, bool using_python=true);
- CFMutableArrayRef QueryRecordsWithAttribute(const char* attr, const char* value, int matchType, bool casei, const char* recordType, CFDictionaryRef attributes, bool using_python=true);
- CFMutableArrayRef QueryRecordsWithAttributes(const char* query, bool casei, const char* recordType, CFDictionaryRef attributes, bool using_python=true);
+ CFMutableArrayRef ListAllRecordsWithAttributes(CFArrayRef recordTypes, CFDictionaryRef attributes, bool using_python=true);
+ CFMutableArrayRef QueryRecordsWithAttribute(const char* attr, const char* value, int matchType, bool casei, CFArrayRef recordTypes, CFDictionaryRef attributes, bool using_python=true);
+ CFMutableArrayRef QueryRecordsWithAttributes(const char* query, bool casei, CFArrayRef recordTypes, CFDictionaryRef attributes, bool using_python=true);
bool AuthenticateUserBasic(const char* nodename, const char* user, const char* pswd, bool& result, bool using_python=true);
bool AuthenticateUserDigest(const char* nodename, const char* user, const char* challenge, const char* response, const char* method, bool& result, bool using_python=true);
@@ -67,8 +67,8 @@
tDataBufferPtr mData;
UInt32 mDataSize;
- CFMutableArrayRef _ListAllRecordsWithAttributes(const char* type, CFArrayRef names, CFDictionaryRef attrs);
- CFMutableArrayRef _QueryRecordsWithAttributes(const char* attr, const char* value, int matchType, const char* compound, bool casei, const char* recordType, CFDictionaryRef attrs);
+ CFMutableArrayRef _ListAllRecordsWithAttributes(CFArrayRef recordTypes, CFArrayRef names, CFDictionaryRef attrs);
+ CFMutableArrayRef _QueryRecordsWithAttributes(const char* attr, const char* value, int matchType, const char* compound, bool casei, CFArrayRef recordTypes, CFDictionaryRef attrs);
bool NativeAuthenticationBasicToNode(const char* nodename, const char* user, const char* pswd);
bool NativeAuthenticationDigestToNode(const char* nodename, const char* user, const char* challenge, const char* response, const char* method);
Modified: PyOpenDirectory/trunk/src/PythonWrapper.cpp
===================================================================
--- PyOpenDirectory/trunk/src/PythonWrapper.cpp 2008-11-01 00:06:48 UTC (rev 3307)
+++ PyOpenDirectory/trunk/src/PythonWrapper.cpp 2008-11-03 15:34:04 UTC (rev 3308)
@@ -127,6 +127,53 @@
}
// Utility function - not exposed to Python
+static CFArrayRef PyStringTupleOrListToCFArray(PyObject* item)
+{
+ if (PyTuple_Check(item) || PyList_Check(item))
+ {
+ PyTupleOrList pyitem(item);
+ CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorDefault, pyitem.getSize(), &kCFTypeArrayCallBacks);
+ for(int i = 0; i < pyitem.getSize(); i++)
+ {
+ PyObject* str = pyitem.get(i);
+ if ((str == NULL) || !PyString_Check(str))
+ {
+ CFRelease(result);
+ throw PyObjectException("Expecting a str type in 'PyStringTupleOrListToCFArray'.");
+ }
+ const char* cstr = PyString_AsString(str);
+ if (cstr == NULL)
+ {
+ CFRelease(result);
+ throw PyObjectException("Could not extract string in 'PyStringTupleOrListToCFArray'.");
+ }
+ CFStringUtil cfstr(cstr);
+ CFArrayAppendValue(result, cfstr.get());
+ }
+
+ return result;
+ }
+ else if (PyString_Check(item))
+ {
+ CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks);
+ const char* cstr = PyString_AsString(item);
+ if (cstr == NULL)
+ {
+ CFRelease(result);
+ throw PyObjectException("Could not extract string in 'PyStringTupleOrListToCFArray'.");
+ }
+ CFStringUtil cfstr(cstr);
+ CFArrayAppendValue(result, cfstr.get());
+
+ return result;
+ }
+ else
+ {
+ throw PyObjectException("Could not extract string, tuple or list in 'PyStringTupleOrListToCFArray'.");
+ }
+}
+
+// Utility function - not exposed to Python
static CFArrayRef PyTupleOrListToCFArray(PyObject* item)
{
PyTupleOrList pyitem(item);
@@ -334,68 +381,33 @@
PyObject* ODException_class = NULL;
/*
- This is an automatic destructor for the object obtained by odInit. It is not directly
- exposed to Python, instead Python calls it automatically when reclaiming the object.
+ Internal method.
*/
-extern "C" void odDestroy(void* obj)
+static PyObject *_listAllRecordsWithAttributes(PyObject *self, PyObject *args, bool list)
{
- CDirectoryServiceManager* dsmgr = static_cast<CDirectoryServiceManager*>(obj);
- delete dsmgr;
-}
-
-/*
- def odInit(nodename):
- """
- Create an Open Directory object to operate on the specified directory service node name.
-
- @param nodename: C{str} containing the node name.
- @return: C{object} an object to be passed to all subsequent functions on success,
- C{None} on failure.
- """
- */
-extern "C" PyObject* odInit(PyObject* self, PyObject* args)
-{
- const char* nodename;
- if (!PyArg_ParseTuple(args, "s", &nodename))
- {
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices odInit: could not parse arguments", 0));
- return NULL;
- }
-
- CDirectoryServiceManager* dsmgr = new CDirectoryServiceManager(nodename);
- if (dsmgr != NULL)
- {
- return PyCObject_FromVoidPtr(dsmgr, odDestroy);
- }
-
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices odInit: could not initialize directory service", 0));
- return NULL;
-}
-
-/*
-def listAllRecordsWithAttributes(obj, recordType, attributes):
- """
- List records in Open Directory, and return key attributes for each one. The attributes
- can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
- is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
-
- @param obj: C{object} the object obtained from an odInit call.
- @param recordType: C{str} containing the OD record type to lookup.
- @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
- @return: C{dict} containing a C{dict} of attributes for each record found,
- or C{None} otherwise.
- */
-extern "C" PyObject *listAllRecordsWithAttributes(PyObject *self, PyObject *args)
-{
PyObject* pyds;
- const char* recordType;
+ PyObject* recordType;
PyObject* attributes;
- if (!PyArg_ParseTuple(args, "OsO", &pyds, &recordType, &attributes) || !PyCObject_Check(pyds) || !PyTupleOrList::typeOK(attributes))
+ if (!PyArg_ParseTuple(args, "OOO", &pyds, &recordType, &attributes) || !PyCObject_Check(pyds) || !PyTupleOrList::typeOK(attributes))
{
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices listAllRecordsWithAttributes: could not parse arguments", 0));
return NULL;
}
+ // Convert string/tuple/list to CFArray
+ CFArrayRef cfrecordtypes = NULL;
+ try
+ {
+ cfrecordtypes = PyStringTupleOrListToCFArray(recordType);
+ }
+ catch(PyObjectException& ex)
+ {
+ std::string msg("DirectoryServices listAllRecordsWithAttributes: could not parse recordTypes: ");
+ msg += ex.what();
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
+ return NULL;
+ }
+
// Convert list to CFArray of CFString
CFDictionaryRef cfattributes = NULL;
try
@@ -407,6 +419,7 @@
std::string msg("DirectoryServices listAllRecordsWithAttributes: could not parse attributes list: ");
msg += ex.what();
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
+ CFRelease(cfrecordtypes);
return NULL;
}
@@ -414,13 +427,14 @@
if (dsmgr != NULL)
{
std::auto_ptr<CDirectoryService> ds(dsmgr->GetService());
- CFMutableArrayRef list = NULL;
- list = ds->ListAllRecordsWithAttributes(recordType, cfattributes);
- if (list != NULL)
+ CFMutableArrayRef results = NULL;
+ results = ds->ListAllRecordsWithAttributes(cfrecordtypes, cfattributes);
+ if (results != NULL)
{
- PyObject* result = CFArrayArrayDictionaryToPyDict(list);
- CFRelease(list);
+ PyObject* result = list ? CFArrayArrayDictionaryToPyList(results) : CFArrayArrayDictionaryToPyDict(results);
+ CFRelease(results);
CFRelease(cfattributes);
+ CFRelease(cfrecordtypes);
return result;
}
@@ -429,28 +443,11 @@
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices listAllRecordsWithAttributes: invalid directory service argument", 0));
CFRelease(cfattributes);
+ CFRelease(cfrecordtypes);
return NULL;
}
-/*
-def queryRecordsWithAttribute(obj, attr, value, matchType, casei, recordType, attributes):
- """
- List records in Open Directory matching specified attribute and value, and return key attributes for each one.
- The attributes can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
- is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
-
- @param obj: C{object} the object obtained from an odInit call.
- @param attr: C{str} for the attribute to query.
- @param value: C{str} for the attribute value to query.
- @param matchType: C{int} DS match type to use when searching.
- @param casei: C{True} to do case-insenstive match, C{False} otherwise.
- @param recordType: C{str} containing the OD record type to lookup.
- @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
- @return: C{dict} containing a C{dict} of attributes for each record found,
- or C{None} otherwise.
- """
- */
-extern "C" PyObject *queryRecordsWithAttribute(PyObject *self, PyObject *args)
+static PyObject *_queryRecordsWithAttribute(PyObject *self, PyObject *args, bool list)
{
PyObject* pyds;
const char* attr;
@@ -458,9 +455,9 @@
int matchType;
PyObject* caseio;
bool casei;
- const char* recordType;
+ PyObject* recordType;
PyObject* attributes;
- if (!PyArg_ParseTuple(args, "OssiOsO", &pyds, &attr, &value, &matchType, &caseio, &recordType, &attributes) ||
+ if (!PyArg_ParseTuple(args, "OssiOOO", &pyds, &attr, &value, &matchType, &caseio, &recordType, &attributes) ||
!PyCObject_Check(pyds) || !PyBool_Check(caseio) || !PyTupleOrList::typeOK(attributes))
{
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices queryRecordsWithAttribute: could not parse arguments", 0));
@@ -469,6 +466,20 @@
casei = (caseio == Py_True);
+ // Convert string/tuple/list to CFArray
+ CFArrayRef cfrecordtypes = NULL;
+ try
+ {
+ cfrecordtypes = PyStringTupleOrListToCFArray(recordType);
+ }
+ catch(PyObjectException& ex)
+ {
+ std::string msg("DirectoryServices listAllRecordsWithAttributes: could not parse recordTypes: ");
+ msg += ex.what();
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
+ return NULL;
+ }
+
// Convert list to CFArray of CFString
CFDictionaryRef cfattributes = NULL;
try
@@ -480,6 +491,7 @@
std::string msg("DirectoryServices queryRecordsWithAttribute: could not parse attributes list: ");
msg += ex.what();
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
+ CFRelease(cfrecordtypes);
return NULL;
}
@@ -487,13 +499,14 @@
if (dsmgr != NULL)
{
std::auto_ptr<CDirectoryService> ds(dsmgr->GetService());
- CFMutableArrayRef list = NULL;
- list = ds->QueryRecordsWithAttribute(attr, value, matchType, casei, recordType, cfattributes);
- if (list != NULL)
+ CFMutableArrayRef results = NULL;
+ results = ds->QueryRecordsWithAttribute(attr, value, matchType, casei, cfrecordtypes, cfattributes);
+ if (results != NULL)
{
- PyObject* result = CFArrayArrayDictionaryToPyDict(list);
- CFRelease(list);
+ PyObject* result = list ? CFArrayArrayDictionaryToPyList(results) : CFArrayArrayDictionaryToPyDict(results);
+ CFRelease(results);
CFRelease(cfattributes);
+ CFRelease(cfrecordtypes);
return result;
}
@@ -502,34 +515,19 @@
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices queryRecordsWithAttribute: invalid directory service argument", 0));
CFRelease(cfattributes);
+ CFRelease(cfrecordtypes);
return NULL;
}
-/*
-def queryRecordsWithAttributes(obj, query, casei, recordType, attributes):
- """
- List records in Open Directory matching specified compound query, and return key attributes for each one.
- The attributes can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
- is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
-
- @param obj: C{object} the object obtained from an odInit call.
- @param query: C{str} the compound query string.
- @param casei: C{True} to do case-insenstive match, C{False} otherwise.
- @param recordType: C{str} containing the OD record type to lookup.
- @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
- @return: C{dict} containing a C{dict} of attributes for each record found,
- or C{None} otherwise.
- """
- */
-extern "C" PyObject *queryRecordsWithAttributes(PyObject *self, PyObject *args)
+static PyObject *_queryRecordsWithAttributes(PyObject *self, PyObject *args, bool list)
{
PyObject* pyds;
const char* query;
PyObject* caseio;
bool casei;
- const char* recordType;
+ PyObject* recordType;
PyObject* attributes;
- if (!PyArg_ParseTuple(args, "OsOsO", &pyds, &query, &caseio, &recordType, &attributes) ||
+ if (!PyArg_ParseTuple(args, "OsOOO", &pyds, &query, &caseio, &recordType, &attributes) ||
!PyCObject_Check(pyds) || !PyBool_Check(caseio) || !PyTupleOrList::typeOK(attributes))
{
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices queryRecordsWithAttributes: could not parse arguments", 0));
@@ -538,6 +536,20 @@
casei = (caseio == Py_True);
+ // Convert string/tuple/list to CFArray
+ CFArrayRef cfrecordtypes = NULL;
+ try
+ {
+ cfrecordtypes = PyStringTupleOrListToCFArray(recordType);
+ }
+ catch(PyObjectException& ex)
+ {
+ std::string msg("DirectoryServices listAllRecordsWithAttributes: could not parse recordTypes: ");
+ msg += ex.what();
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
+ return NULL;
+ }
+
// Convert list to CFArray of CFString
CFDictionaryRef cfattributes = NULL;
try
@@ -549,6 +561,7 @@
std::string msg("DirectoryServices queryRecordsWithAttributes: could not parse attributes list: ");
msg += ex.what();
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
+ CFRelease(cfrecordtypes);
return NULL;
}
@@ -556,13 +569,14 @@
if (dsmgr != NULL)
{
std::auto_ptr<CDirectoryService> ds(dsmgr->GetService());
- CFMutableArrayRef list = NULL;
- list = ds->QueryRecordsWithAttributes(query, casei, recordType, cfattributes);
- if (list != NULL)
+ CFMutableArrayRef results = NULL;
+ results = ds->QueryRecordsWithAttributes(query, casei, cfrecordtypes, cfattributes);
+ if (results != NULL)
{
- PyObject* result = CFArrayArrayDictionaryToPyDict(list);
- CFRelease(list);
+ PyObject* result = list ? CFArrayArrayDictionaryToPyList(results) : CFArrayArrayDictionaryToPyDict(results);
+ CFRelease(results);
CFRelease(cfattributes);
+ CFRelease(cfrecordtypes);
return result;
}
@@ -571,73 +585,70 @@
PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices queryRecordsWithAttributes: invalid directory service argument", 0));
CFRelease(cfattributes);
+ CFRelease(cfrecordtypes);
return NULL;
}
/*
-def listAllRecordsWithAttributes_list(obj, recordType, attributes):
+ This is an automatic destructor for the object obtained by odInit. It is not directly
+ exposed to Python, instead Python calls it automatically when reclaiming the object.
+ */
+extern "C" void odDestroy(void* obj)
+{
+ CDirectoryServiceManager* dsmgr = static_cast<CDirectoryServiceManager*>(obj);
+ delete dsmgr;
+}
+
+/*
+ def odInit(nodename):
"""
- List records in Open Directory, and return key attributes for each one.
- The attributes can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
- is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
+ Create an Open Directory object to operate on the specified directory service node name.
- @param obj: C{object} the object obtained from an odInit call.
- @param recordType: C{str} containing the OD record type to lookup.
- @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
- @return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
- for each record found, or C{None} otherwise.
+ @param nodename: C{str} containing the node name.
+ @return: C{object} an object to be passed to all subsequent functions on success,
+ C{None} on failure.
"""
*/
-extern "C" PyObject *listAllRecordsWithAttributes_list(PyObject *self, PyObject *args)
+extern "C" PyObject* odInit(PyObject* self, PyObject* args)
{
- PyObject* pyds;
- const char* recordType;
- PyObject* attributes;
- if (!PyArg_ParseTuple(args, "OsO", &pyds, &recordType, &attributes) || !PyCObject_Check(pyds) || !PyTupleOrList::typeOK(attributes))
+ const char* nodename;
+ if (!PyArg_ParseTuple(args, "s", &nodename))
{
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices listAllRecordsWithAttributes_list: could not parse arguments", 0));
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices odInit: could not parse arguments", 0));
return NULL;
}
- // Convert list to CFArray of CFString
- CFDictionaryRef cfattributes = NULL;
- try
- {
- cfattributes = AttributesToCFDictionary(attributes);
- }
- catch(PyObjectException& ex)
- {
- std::string msg("DirectoryServices listAllRecordsWithAttributes_list: could not parse attributes list: ");
- msg += ex.what();
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
- return NULL;
- }
-
- CDirectoryServiceManager* dsmgr = static_cast<CDirectoryServiceManager*>(PyCObject_AsVoidPtr(pyds));
+ CDirectoryServiceManager* dsmgr = new CDirectoryServiceManager(nodename);
if (dsmgr != NULL)
{
- std::auto_ptr<CDirectoryService> ds(dsmgr->GetService());
- CFMutableArrayRef list = NULL;
- list = ds->ListAllRecordsWithAttributes(recordType, cfattributes);
- if (list != NULL)
- {
- PyObject* result = CFArrayArrayDictionaryToPyList(list);
- CFRelease(list);
- CFRelease(cfattributes);
-
- return result;
- }
+ return PyCObject_FromVoidPtr(dsmgr, odDestroy);
}
- else
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices listAllRecordsWithAttributes_list: invalid directory service argument", 0));
- CFRelease(cfattributes);
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices odInit: could not initialize directory service", 0));
return NULL;
}
/*
-def queryRecordsWithAttribute_list(obj, attr, value, matchType, casei, recordType, attributes):
+def listAllRecordsWithAttributes(obj, recordType, attributes):
"""
+ List records in Open Directory, and return key attributes for each one. The attributes
+ can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
+ is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
+
+ @param obj: C{object} the object obtained from an odInit call.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
+ @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
+ @return: C{dict} containing a C{dict} of attributes for each record found,
+ or C{None} otherwise.
+ */
+extern "C" PyObject *listAllRecordsWithAttributes(PyObject *self, PyObject *args)
+{
+ return _listAllRecordsWithAttributes(self, args, false);
+}
+
+/*
+def queryRecordsWithAttribute(obj, attr, value, matchType, casei, recordType, attributes):
+ """
List records in Open Directory matching specified attribute and value, and return key attributes for each one.
The attributes can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
@@ -647,65 +658,78 @@
@param value: C{str} for the attribute value to query.
@param matchType: C{int} DS match type to use when searching.
@param casei: C{True} to do case-insenstive match, C{False} otherwise.
- @param recordType: C{str} containing the OD record type to lookup.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
- @return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
- for each record found, or C{None} otherwise.
+ @return: C{dict} containing a C{dict} of attributes for each record found,
+ or C{None} otherwise.
"""
*/
-extern "C" PyObject *queryRecordsWithAttribute_list(PyObject *self, PyObject *args)
+extern "C" PyObject *queryRecordsWithAttribute(PyObject *self, PyObject *args)
{
- PyObject* pyds;
- const char* attr;
- const char* value;
- int matchType;
- PyObject* caseio;
- bool casei;
- const char* recordType;
- PyObject* attributes;
- if (!PyArg_ParseTuple(args, "OssiOsO", &pyds, &attr, &value, &matchType, &caseio, &recordType, &attributes) ||
- !PyCObject_Check(pyds) || !PyBool_Check(caseio) || !PyTupleOrList::typeOK(attributes))
- {
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices queryRecordsWithAttribute_list: could not parse arguments", 0));
- return NULL;
- }
+ return _queryRecordsWithAttribute(self, args, false);
+}
- casei = (caseio == Py_True);
+/*
+def queryRecordsWithAttributes(obj, query, casei, recordType, attributes):
+ """
+ List records in Open Directory matching specified compound query, and return key attributes for each one.
+ The attributes can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
+ is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
- // Convert list to CFArray of CFString
- CFDictionaryRef cfattributes = NULL;
- try
- {
- cfattributes = AttributesToCFDictionary(attributes);
- }
- catch(PyObjectException& ex)
- {
- std::string msg("DirectoryServices queryRecordsWithAttribute_list: could not parse attributes list: ");
- msg += ex.what();
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
- return NULL;
- }
+ @param obj: C{object} the object obtained from an odInit call.
+ @param query: C{str} the compound query string.
+ @param casei: C{True} to do case-insenstive match, C{False} otherwise.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
+ @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
+ @return: C{dict} containing a C{dict} of attributes for each record found,
+ or C{None} otherwise.
+ """
+ */
+extern "C" PyObject *queryRecordsWithAttributes(PyObject *self, PyObject *args)
+{
+ return _queryRecordsWithAttributes(self, args, false);
+}
- CDirectoryServiceManager* dsmgr = static_cast<CDirectoryServiceManager*>(PyCObject_AsVoidPtr(pyds));
- if (dsmgr != NULL)
- {
- std::auto_ptr<CDirectoryService> ds(dsmgr->GetService());
- CFMutableArrayRef list = NULL;
- list = ds->QueryRecordsWithAttribute(attr, value, matchType, casei, recordType, cfattributes);
- if (list != NULL)
- {
- PyObject* result = CFArrayArrayDictionaryToPyList(list);
- CFRelease(list);
- CFRelease(cfattributes);
+/*
+def listAllRecordsWithAttributes_list(obj, recordType, attributes):
+ """
+ List records in Open Directory, and return key attributes for each one.
+ The attributes can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
+ is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
- return result;
- }
- }
- else
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices queryRecordsWithAttribute_list: invalid directory service argument", 0));
+ @param obj: C{object} the object obtained from an odInit call.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
+ @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
+ @return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
+ for each record found, or C{None} otherwise.
+ """
+ */
+extern "C" PyObject *listAllRecordsWithAttributes_list(PyObject *self, PyObject *args)
+{
+ return _listAllRecordsWithAttributes(self, args, true);
+}
- CFRelease(cfattributes);
- return NULL;
+/*
+def queryRecordsWithAttribute_list(obj, attr, value, matchType, casei, recordType, attributes):
+ """
+ List records in Open Directory matching specified attribute and value, and return key attributes for each one.
+ The attributes can be a C{str} for the attribute name, or a C{tuple} or C{list} where the first C{str}
+ is the attribute name, and the second C{str} is an encoding type, either "str" or "base64".
+
+ @param obj: C{object} the object obtained from an odInit call.
+ @param attr: C{str} for the attribute to query.
+ @param value: C{str} for the attribute value to query.
+ @param matchType: C{int} DS match type to use when searching.
+ @param casei: C{True} to do case-insenstive match, C{False} otherwise.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
+ @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
+ @return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
+ for each record found, or C{None} otherwise.
+ """
+ */
+extern "C" PyObject *queryRecordsWithAttribute_list(PyObject *self, PyObject *args)
+{
+ return _queryRecordsWithAttribute(self, args, true);
}
/*
@@ -718,7 +742,7 @@
@param obj: C{object} the object obtained from an odInit call.
@param query: C{str} the compound query string.
@param casei: C{True} to do case-insenstive match, C{False} otherwise.
- @param recordType: C{str} containing the OD record type to lookup.
+ @param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
for each record found, or C{None} otherwise.
@@ -726,55 +750,7 @@
*/
extern "C" PyObject *queryRecordsWithAttributes_list(PyObject *self, PyObject *args)
{
- PyObject* pyds;
- const char* query;
- PyObject* caseio;
- bool casei;
- const char* recordType;
- PyObject* attributes;
- if (!PyArg_ParseTuple(args, "OsOsO", &pyds, &query, &caseio, &recordType, &attributes) ||
- !PyCObject_Check(pyds) || !PyBool_Check(caseio) || !PyTupleOrList::typeOK(attributes))
- {
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices queryRecordsWithAttributes_list: could not parse arguments", 0));
- return NULL;
- }
-
- casei = (caseio == Py_True);
-
- // Convert list to CFArray of CFString
- CFDictionaryRef cfattributes = NULL;
- try
- {
- cfattributes = AttributesToCFDictionary(attributes);
- }
- catch(PyObjectException& ex)
- {
- std::string msg("DirectoryServices queryRecordsWithAttributes_list: could not parse attributes list: ");
- msg += ex.what();
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", msg.c_str(), 0));
- return NULL;
- }
-
- CDirectoryServiceManager* dsmgr = static_cast<CDirectoryServiceManager*>(PyCObject_AsVoidPtr(pyds));
- if (dsmgr != NULL)
- {
- std::auto_ptr<CDirectoryService> ds(dsmgr->GetService());
- CFMutableArrayRef list = NULL;
- list = ds->QueryRecordsWithAttributes(query, casei, recordType, cfattributes);
- if (list != NULL)
- {
- PyObject* result = CFArrayArrayDictionaryToPyList(list);
- CFRelease(list);
- CFRelease(cfattributes);
-
- return result;
- }
- }
- else
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices queryRecordsWithAttributes_list: invalid directory service argument", 0));
-
- CFRelease(cfattributes);
- return NULL;
+ return _queryRecordsWithAttributes(self, args, true);
}
/*
Modified: PyOpenDirectory/trunk/test.py
===================================================================
--- PyOpenDirectory/trunk/test.py 2008-11-01 00:06:48 UTC (rev 3307)
+++ PyOpenDirectory/trunk/test.py 2008-11-03 15:34:04 UTC (rev 3308)
@@ -266,26 +266,68 @@
[dsattributes.kDS1AttrGeneratedUID, dsattributes.kDS1AttrDistinguishedName,]
)
+ def listResourcesPlaces_list():
+ d = opendirectory.listAllRecordsWithAttributes_list(
+ ref,
+ (dsattributes.kDSStdRecordTypeResources, dsattributes.kDSStdRecordTypePlaces,),
+ [dsattributes.kDSNAttrRecordType, dsattributes.kDS1AttrGeneratedUID, dsattributes.kDS1AttrDistinguishedName,]
+ )
+ if d is None:
+ print "Failed to list resources/places"
+ else:
+ d.sort(cmp=lambda x, y: x[0] < y[0])
+ print "\nlistResourcesPlaces_list number of results = %d" % (len(d),)
+ for name, record in d:
+ print "Name: %s" % name
+ print "dict: %s" % str(record)
+
+ def queryUsersGroups_list():
+ querySimple_list(
+ "queryUsersGroups_list",
+ dsattributes.kDS1AttrDistinguishedName,
+ "burns",
+ dsattributes.eDSContains,
+ True,
+ (dsattributes.kDSStdRecordTypeUsers, dsattributes.kDSStdRecordTypeGroups,),
+ [dsattributes.kDS1AttrGeneratedUID, dsattributes.kDS1AttrDistinguishedName,]
+ )
+
+ def queryUsersGroupsPlaces_list():
+ querySimple_list(
+ "queryUsersGroupsPlaces_list",
+ dsattributes.kDS1AttrDistinguishedName,
+ "tom",
+ dsattributes.eDSContains,
+ True,
+ (dsattributes.kDSStdRecordTypeUsers, dsattributes.kDSStdRecordTypeGroups, dsattributes.kDSStdRecordTypePlaces,),
+ [dsattributes.kDS1AttrGeneratedUID, dsattributes.kDS1AttrDistinguishedName,]
+ )
+
def authentciateBasic():
if opendirectory.authenticateUserBasic(ref, "gooeyed", "test", "test"):
print "Authenticated user"
else:
print "Failed to authenticate user"
- listUsers()
- listGroups()
- listComputers()
- queryUsers()
- queryUsersCompoundOr()
- queryUsersCompoundOrExact()
- queryUsersCompoundAnd()
- listUsers_list()
- listGroups_list()
- listComputers_list()
- queryUsers_list()
- queryUsersCompoundOr_list()
- queryUsersCompoundOrExact_list()
- queryUsersCompoundAnd_list()
+ #listUsers()
+ #listGroups()
+ #listComputers()
+ #queryUsers()
+ #queryUsersCompoundOr()
+ #queryUsersCompoundOrExact()
+ #queryUsersCompoundAnd()
+ #listUsers_list()
+ #listGroups_list()
+ #listComputers_list()
+ #queryUsers_list()
+ #queryUsersCompoundOr_list()
+ #queryUsersCompoundOrExact_list()
+ #queryUsersCompoundAnd_list()
+
+ listResourcesPlaces_list()
+ queryUsersGroups_list()
+ queryUsersGroupsPlaces_list()
+
#authentciateBasic()
ref = None
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20081103/4099dcea/attachment-0001.html>
More information about the calendarserver-changes
mailing list