<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12127] twext/trunk/twext/who/opendirectory</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/12127">12127</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2013-12-18 10:29:24 -0800 (Wed, 18 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add more tests, remove opendirectory wrapper and associated modules</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#twexttrunktwextwhoopendirectorytesttest_servicepy">twext/trunk/twext/who/opendirectory/test/test_service.py</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#twexttrunktwextwhoopendirectorydsattributespy">twext/trunk/twext/who/opendirectory/dsattributes.py</a></li>
<li><a href="#twexttrunktwextwhoopendirectorydsquerypy">twext/trunk/twext/who/opendirectory/dsquery.py</a></li>
<li><a href="#twexttrunktwextwhoopendirectoryopendirectorypy">twext/trunk/twext/who/opendirectory/opendirectory.py</a></li>
<li><a href="#twexttrunktwextwhoopendirectorysetup_directorypy">twext/trunk/twext/who/opendirectory/setup_directory.py</a></li>
<li><a href="#twexttrunktwextwhoopendirectorysetup_testuserspy">twext/trunk/twext/who/opendirectory/setup_testusers.py</a></li>
<li><a href="#twexttrunktwextwhoopendirectorytesttest_opendirectorypy">twext/trunk/twext/who/opendirectory/test/test_opendirectory.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="twexttrunktwextwhoopendirectorydsattributespy"></a>
<div class="delfile"><h4>Deleted: twext/trunk/twext/who/opendirectory/dsattributes.py (12126 => 12127)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/who/opendirectory/dsattributes.py        2013-12-18 00:50:59 UTC (rev 12126)
+++ twext/trunk/twext/who/opendirectory/dsattributes.py        2013-12-18 18:29:24 UTC (rev 12127)
</span><span class="lines">@@ -1,1894 +0,0 @@
</span><del>-##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-&quot;&quot;&quot;
-Record types and attribute names from Directory Service.
-This comes directly (with C-&gt;Python conversion) from &lt;DirectoryServices/DirServicesConst.h&gt;
-&quot;&quot;&quot;
-
-# Specific match types
-
-eDSExact             =    0x2001
-eDSStartsWith        =    0x2002
-eDSEndsWith          =    0x2003
-eDSContains          =    0x2004
-
-eDSLessThan          =    0x2005
-eDSGreaterThan       =    0x2006
-eDSLessEqual         =    0x2007
-eDSGreaterEqual      =    0x2008
-
-# Specific Record Type Constants
-
-&quot;&quot;&quot;
- DirectoryService Specific Record Type Constants
-&quot;&quot;&quot;

-&quot;&quot;&quot;
- kDSStdRecordTypeAccessControls
-  Record type that contains directory access control directives.
-&quot;&quot;&quot;
-kDSStdRecordTypeAccessControls = &quot;dsRecTypeStandard:AccessControls&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeAFPServer
-  Record type of AFP server records.
-&quot;&quot;&quot;
-kDSStdRecordTypeAFPServer = &quot;dsRecTypeStandard:AFPServer&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeAFPUserAliases
-  Record type of AFP user aliases used exclusively by AFP processes.
-&quot;&quot;&quot;
-kDSStdRecordTypeAFPUserAliases = &quot;dsRecTypeStandard:AFPUserAliases&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeAliases
-  Used to represent alias records.
-&quot;&quot;&quot;
-kDSStdRecordTypeAliases = &quot;dsRecTypeStandard:Aliases&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeAugments
-  Used to store augmented record data.
-&quot;&quot;&quot;
-kDSStdRecordTypeAugments = &quot;dsRecTypeStandard:Augments&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeAutomount
-  Used to store automount record data.
-&quot;&quot;&quot;
-kDSStdRecordTypeAutomount = &quot;dsRecTypeStandard:Automount&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeAutomountMap
-  Used to store automountMap record data.
-&quot;&quot;&quot;
-kDSStdRecordTypeAutomountMap = &quot;dsRecTypeStandard:AutomountMap&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeAutoServerSetup
-  Used to discover automated server setup information.
-&quot;&quot;&quot;
-kDSStdRecordTypeAutoServerSetup = &quot;dsRecTypeStandard:AutoServerSetup&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeBootp
-  Record in the local node for storing bootp info.
-&quot;&quot;&quot;
-kDSStdRecordTypeBootp = &quot;dsRecTypeStandard:Bootp&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeCertificateAuthority
-  Record type that contains certificate authority information.
-&quot;&quot;&quot;
-kDSStdRecordTypeCertificateAuthorities = &quot;dsRecTypeStandard:CertificateAuthorities&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeComputerLists
-  Identifies computer list records.
-&quot;&quot;&quot;
-kDSStdRecordTypeComputerLists = &quot;dsRecTypeStandard:ComputerLists&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeComputerGroups
-  Identifies computer group records.
-&quot;&quot;&quot;
-kDSStdRecordTypeComputerGroups = &quot;dsRecTypeStandard:ComputerGroups&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeComputers
-  Identifies computer records.
-&quot;&quot;&quot;
-kDSStdRecordTypeComputers = &quot;dsRecTypeStandard:Computers&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeConfig
-  Identifies config records.
-&quot;&quot;&quot;
-kDSStdRecordTypeConfig = &quot;dsRecTypeStandard:Config&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeEthernets
-  Record in the local node for storing ethernets.
-&quot;&quot;&quot;
-kDSStdRecordTypeEthernets = &quot;dsRecTypeStandard:Ethernets&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeFileMakerServers
-  FileMaker servers record type. Describes available FileMaker servers, 
-  used for service discovery.
-&quot;&quot;&quot;
-kDSStdRecordTypeFileMakerServers = &quot;dsRecTypeStandard:FileMakerServers&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeFTPServer
-  Identifies ftp server records.
-&quot;&quot;&quot;
-kDSStdRecordTypeFTPServer = &quot;dsRecTypeStandard:FTPServer&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeGroupAliases
-  No longer supported in Mac OS X 10.4 or later.
-&quot;&quot;&quot;
-kDSStdRecordTypeGroupAliases = &quot;dsRecTypeStandard:GroupAliases&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeGroups
-  Identifies group records.
-&quot;&quot;&quot;
-kDSStdRecordTypeGroups = &quot;dsRecTypeStandard:Groups&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeHostServices
-  Record in the local node for storing host services.
-&quot;&quot;&quot;
-kDSStdRecordTypeHostServices = &quot;dsRecTypeStandard:HostServices&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeHosts
-  Identifies host records.
-&quot;&quot;&quot;
-kDSStdRecordTypeHosts = &quot;dsRecTypeStandard:Hosts&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeLDAPServer
-  Identifies LDAP server records.
-&quot;&quot;&quot;
-kDSStdRecordTypeLDAPServer = &quot;dsRecTypeStandard:LDAPServer&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeLocations
-  Location record type.
-&quot;&quot;&quot;
-kDSStdRecordTypeLocations = &quot;dsRecTypeStandard:Locations&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeMachines
-  Identifies machine records.
-&quot;&quot;&quot;
-kDSStdRecordTypeMachines = &quot;dsRecTypeStandard:Machines&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeMaps
-  Identifies map records.
-&quot;&quot;&quot;
-kDSStdRecordTypeMaps = &quot;dsRecTypeStandard:Maps&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeMeta
-  Identifies meta records.
-&quot;&quot;&quot;
-kDSStdRecordTypeMeta = &quot;dsRecTypeStandard:AppleMetaRecord&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeMounts
-  Identifies mount records.
-&quot;&quot;&quot;
-kDSStdRecordTypeMounts = &quot;dsRecTypeStandard:Mounts&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypMounts
-  Supported only for backward compatibility to kDSStdRecordTypeMounts.
-&quot;&quot;&quot;
-kDSStdRecordTypMounts = &quot;dsRecTypeStandard:Mounts&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeNeighborhoods
-  Neighborhood record type. Describes a list of computers and other
-  neighborhoods, used for network browsing.
-&quot;&quot;&quot;
-kDSStdRecordTypeNeighborhoods = &quot;dsRecTypeStandard:Neighborhoods&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeNFS
-  Identifies NFS records.
-&quot;&quot;&quot;
-kDSStdRecordTypeNFS = &quot;dsRecTypeStandard:NFS&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeNetDomains
-  Record in the local node for storing net domains.
-&quot;&quot;&quot;
-kDSStdRecordTypeNetDomains = &quot;dsRecTypeStandard:NetDomains&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeNetGroups
-  Record in the local node for storing net groups.
-&quot;&quot;&quot;
-kDSStdRecordTypeNetGroups = &quot;dsRecTypeStandard:NetGroups&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeNetworks
-  Identifies network records.
-&quot;&quot;&quot;
-kDSStdRecordTypeNetworks = &quot;dsRecTypeStandard:Networks&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePasswordServer
-  Used to discover password servers via Bonjour.
-&quot;&quot;&quot;
-kDSStdRecordTypePasswordServer = &quot;dsRecTypeStandard:PasswordServer&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePeople
-  Record type that contains &quot;People&quot; records used for contact information.
-&quot;&quot;&quot;
-kDSStdRecordTypePeople = &quot;dsRecTypeStandard:People&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePlaces
-  Identifies places (rooms) records.
-&quot;&quot;&quot;
-kDSStdRecordTypePlaces = &quot;dsRecTypeStandard:Places&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePresetComputers
-  The computer record type used for presets in record creation.
-&quot;&quot;&quot;
-kDSStdRecordTypePresetComputers = &quot;dsRecTypeStandard:PresetComputers&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePresetComputerGroups
-  The computer group record type used for presets in record creation.
-&quot;&quot;&quot;
-kDSStdRecordTypePresetComputerGroups = &quot;dsRecTypeStandard:PresetComputerGroups&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePresetComputerLists
-  The computer list record type used for presets in record creation.
-&quot;&quot;&quot;
-kDSStdRecordTypePresetComputerLists = &quot;dsRecTypeStandard:PresetComputerLists&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePresetGroups
-  The group record type used for presets in record creation.
-&quot;&quot;&quot;
-kDSStdRecordTypePresetGroups = &quot;dsRecTypeStandard:PresetGroups&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePresetUsers
-  The user record type used for presets in record creation.
-&quot;&quot;&quot;
-kDSStdRecordTypePresetUsers = &quot;dsRecTypeStandard:PresetUsers&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePrintService
-  Identifies print service records.
-&quot;&quot;&quot;
-kDSStdRecordTypePrintService = &quot;dsRecTypeStandard:PrintService&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePrintServiceUser
-  Record in the local node for storing quota usage for a user.
-&quot;&quot;&quot;
-kDSStdRecordTypePrintServiceUser = &quot;dsRecTypeStandard:PrintServiceUser&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypePrinters
-  Identifies printer records.
-&quot;&quot;&quot;
-kDSStdRecordTypePrinters = &quot;dsRecTypeStandard:Printers&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeProtocols
-  Identifies protocol records.
-&quot;&quot;&quot;
-kDSStdRecordTypeProtocols = &quot;dsRecTypeStandard:Protocols&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypProtocols
-  Supported only for backward compatibility to kDSStdRecordTypeProtocols.
-&quot;&quot;&quot;
-kDSStdRecordTypProtocols = &quot;dsRecTypeStandard:Protocols&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeQTSServer
-  Identifies quicktime streaming server records.
-&quot;&quot;&quot;
-kDSStdRecordTypeQTSServer = &quot;dsRecTypeStandard:QTSServer&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeResources
-  Identifies resources used in group services.
-&quot;&quot;&quot;
-kDSStdRecordTypeResources = &quot;dsRecTypeStandard:Resources&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeRPC
-  Identifies remote procedure call records.
-&quot;&quot;&quot;
-kDSStdRecordTypeRPC = &quot;dsRecTypeStandard:RPC&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypRPC
-  Supported only for backward compatibility to kDSStdRecordTypeRPC.
-&quot;&quot;&quot;
-kDSStdRecordTypRPC = &quot;dsRecTypeStandard:RPC&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeSMBServer
-  Identifies SMB server records.
-&quot;&quot;&quot;
-kDSStdRecordTypeSMBServer = &quot;dsRecTypeStandard:SMBServer&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeServer
-  Identifies generic server records.
-&quot;&quot;&quot;
-kDSStdRecordTypeServer = &quot;dsRecTypeStandard:Server&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeServices
-  Identifies directory based service records.
-&quot;&quot;&quot;
-kDSStdRecordTypeServices = &quot;dsRecTypeStandard:Services&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeSharePoints
-  Share point record type.
-&quot;&quot;&quot;
-kDSStdRecordTypeSharePoints = &quot;dsRecTypeStandard:SharePoints&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeUserAliases
-  No longer supported in Mac OS X 10.4 or later.
-&quot;&quot;&quot;
-kDSStdRecordTypeUserAliases = &quot;dsRecTypeStandard:UserAliases&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeUsers
-  Identifies user records.
-&quot;&quot;&quot;
-kDSStdRecordTypeUsers = &quot;dsRecTypeStandard:Users&quot;
-
-&quot;&quot;&quot;
- kDSStdRecordTypeWebServer
-  Identifies web server records.
-&quot;&quot;&quot;
-kDSStdRecordTypeWebServer = &quot;dsRecTypeStandard:WebServer&quot;
-
-# Specific Attribute Type Constants
-
-
-&quot;&quot;&quot;
- DirectoryService Specific Attribute Type Constants
- As a guideline for the attribute types the following legend is used:
-
-        eDS1xxxxxx  Single Valued Attribute
-
-        eDSNxxxxxx  Multi-Valued Attribute
-
-    NOTE #1: Access controls may prevent any particular client from reading/writting
-            various attribute types.  In addition some attribute types may not be stored at
-            all and could also represent &quot;real-time&quot; data generated by the directory node
-            plug-in.
-
-    NOTE #2: Attributes in the model are available for records and directory nodes.
-&quot;&quot;&quot;

-
-# Single Valued Specific Attribute Type Constants
-
-
-&quot;&quot;&quot;
- DirectoryService Single Valued Specific Attribute Type Constants
-&quot;&quot;&quot;
-
-&quot;&quot;&quot;
-    kDS1AttrAdminLimits
-    XML plist indicating what an admin user can edit.
-        Found in kDSStdRecordTypeUsers records.
-&quot;&quot;&quot;
-kDS1AttrAdminLimits = &quot;dsAttrTypeStandard:AdminLimits&quot;
-
-&quot;&quot;&quot;
- kDS1AttrAliasData
- Used to identify alias data.
-&quot;&quot;&quot;
-kDS1AttrAliasData = &quot;dsAttrTypeStandard:AppleAliasData&quot;
-
-&quot;&quot;&quot;
- kDS1AttrAlternateDatastoreLocation
- Unix path used for determining where a user's email is stored.
-&quot;&quot;&quot;
-kDS1AttrAlternateDatastoreLocation = &quot;dsAttrTypeStandard:AlternateDatastoreLocation&quot;
-
-&quot;&quot;&quot;
- kDS1AttrAuthenticationHint
- Used to identify the authentication hint phrase.
-&quot;&quot;&quot;
-kDS1AttrAuthenticationHint = &quot;dsAttrTypeStandard:AuthenticationHint&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAttributeTypes
- Used to indicated recommended attribute types for a record type in the Config node.
-&quot;&quot;&quot;
-kDSNAttrAttributeTypes = &quot;dsAttrTypeStandard:AttributeTypes&quot;
-
-&quot;&quot;&quot;
- kDS1AttrAuthorityRevocationList
- Attribute containing the binary of the authority revocation list.
- A certificate revocation list that defines certificate authority certificates
- which are no longer trusted.  No user certificates are included in this list.
- Usually found in kDSStdRecordTypeCertificateAuthority records.
-&quot;&quot;&quot;
-kDS1AttrAuthorityRevocationList = &quot;dsAttrTypeStandard:AuthorityRevocationList&quot;
-
-&quot;&quot;&quot;
- kDS1AttrBirthday
- Single-valued attribute that defines the user's birthday.
- Format is x.208 standard YYYYMMDDHHMMSSZ which we will require as GMT time.
-&quot;&quot;&quot;
-kDS1AttrBirthday = &quot;dsAttrTypeStandard:Birthday&quot;
-
-
-&quot;&quot;&quot;
- kDS1AttrBootFile
- Attribute type in host or machine records for the name of the 
-        kernel that this machine will use by default when NetBooting.
-&quot;&quot;&quot;
-kDS1AttrBootFile = &quot;dsAttrTypeStandard:BootFile&quot;
-
-&quot;&quot;&quot;
- kDS1AttrCACertificate
- Attribute containing the binary of the certificate of a
- certificate authority. Its corresponding private key is used to sign certificates.
- Usually found in kDSStdRecordTypeCertificateAuthority records.
-&quot;&quot;&quot;
-kDS1AttrCACertificate = &quot;dsAttrTypeStandard:CACertificate&quot;
-
-&quot;&quot;&quot;
- kDS1AttrCapabilities
- Used with directory nodes so that clients can &quot;discover&quot; the
- API capabilities for this Directory Node.
-&quot;&quot;&quot;
-kDS1AttrCapabilities = &quot;dsAttrTypeStandard:Capabilities&quot;
-
-&quot;&quot;&quot;
- kDS1AttrCapacity
- Attribute type for the capacity of a resource. 
-     found in resource records (kDSStdRecordTypeResources). 
-    Example: 50
-&quot;&quot;&quot;
-kDS1AttrCapacity = &quot;dsAttrTypeStandard:Capacity&quot;
-
-&quot;&quot;&quot;
-    kDS1AttrCategory
-    The category of an item used for browsing
-&quot;&quot;&quot;
-kDS1AttrCategory = &quot;dsAttrTypeStandard:Category&quot;
-
-&quot;&quot;&quot;
- kDS1AttrCertificateRevocationList
- Attribute containing the binary of the certificate revocation list.
- This is a list of certificates which are no longer trusted.
- Usually found in kDSStdRecordTypeCertificateAuthority records.
-&quot;&quot;&quot;
-kDS1AttrCertificateRevocationList = &quot;dsAttrTypeStandard:CertificateRevocationList&quot;
-
-&quot;&quot;&quot;
- kDS1AttrChange
- Retained for backward compatibility.
-&quot;&quot;&quot;
-kDS1AttrChange = &quot;dsAttrTypeStandard:Change&quot;
-
-&quot;&quot;&quot;
- kDS1AttrComment
- Attribute used for unformatted comment.
-&quot;&quot;&quot;
-kDS1AttrComment = &quot;dsAttrTypeStandard:Comment&quot;
-
-&quot;&quot;&quot;
- kDS1AttrContactGUID
- Attribute type for the contact GUID of a group. 
-     found in group records (kDSStdRecordTypeGroups). 
-&quot;&quot;&quot;
-kDS1AttrContactGUID = &quot;dsAttrTypeStandard:ContactGUID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrContactPerson
- Attribute type for the contact person of the machine. 
-        Found in host or machine records.
-&quot;&quot;&quot;
-kDS1AttrContactPerson = &quot;dsAttrTypeStandard:ContactPerson&quot;
-
-&quot;&quot;&quot;
- kDS1AttrCreationTimestamp
- Attribute showing date/time of record creation.
- Format is x.208 standard YYYYMMDDHHMMSSZ which we will require as GMT time.
-&quot;&quot;&quot;
-kDS1AttrCreationTimestamp = &quot;dsAttrTypeStandard:CreationTimestamp&quot;
-
-&quot;&quot;&quot;
- kDS1AttrCrossCertificatePair
- Attribute containing the binary of a pair of certificates which 
- verify each other.  Both certificates have the same level of authority.
- Usually found in kDSStdRecordTypeCertificateAuthority records.
-&quot;&quot;&quot;
-kDS1AttrCrossCertificatePair = &quot;dsAttrTypeStandard:CrossCertificatePair&quot;
-
-&quot;&quot;&quot;
- kDS1AttrDataStamp
- checksum/meta data
-&quot;&quot;&quot;
-kDS1AttrDataStamp = &quot;dsAttrTypeStandard:DataStamp&quot;
-
-&quot;&quot;&quot;
- kDS1AttrDistinguishedName
- Users distinguished or real name
-&quot;&quot;&quot;
-kDS1AttrDistinguishedName = &quot;dsAttrTypeStandard:RealName&quot;
-
-&quot;&quot;&quot;
- kDS1AttrDNSDomain
- DNS Resolver domain attribute.
-&quot;&quot;&quot;
-kDS1AttrDNSDomain = &quot;dsAttrTypeStandard:DNSDomain&quot;
-
-&quot;&quot;&quot;
- kDS1AttrDNSNameServer
- DNS Resolver nameserver attribute.
-&quot;&quot;&quot;
-kDS1AttrDNSNameServer = &quot;dsAttrTypeStandard:DNSNameServer&quot;
-
-&quot;&quot;&quot;
- kDS1AttrENetAddress
- Single-valued attribute for hardware Ethernet address (MAC address).
-        Found in machine records (kDSStdRecordTypeMachines) and computer records
-        (kDSStdRecordTypeComputers).
-&quot;&quot;&quot;
-kDS1AttrENetAddress = &quot;dsAttrTypeStandard:ENetAddress&quot;
-
-&quot;&quot;&quot;
- kDS1AttrExpire
- Used for expiration date or time depending on association.
-&quot;&quot;&quot;
-kDS1AttrExpire = &quot;dsAttrTypeStandard:Expire&quot;
-
-&quot;&quot;&quot;
- kDS1AttrFirstName
- Used for first name of user or person record.
-&quot;&quot;&quot;
-kDS1AttrFirstName = &quot;dsAttrTypeStandard:FirstName&quot;
-
-&quot;&quot;&quot;
- kDS1AttrGeneratedUID
- Used for 36 character (128 bit) unique ID. Usually found in user, 
- group, and computer records. An example value is &quot;A579E95E-CDFE-4EBC-B7E7-F2158562170F&quot;.
- The standard format contains 32 hex characters and four hyphen characters.
-&quot;&quot;&quot;
-kDS1AttrGeneratedUID = &quot;dsAttrTypeStandard:GeneratedUID&quot;
-
-&quot;&quot;&quot;
-    kDS1AttrHomeDirectoryQuota
-    Represents the allowed usage for a user's home directory in bytes.
-        Found in user records (kDSStdRecordTypeUsers).
-&quot;&quot;&quot;
-kDS1AttrHomeDirectoryQuota = &quot;dsAttrTypeStandard:HomeDirectoryQuota&quot;
-
-&quot;&quot;&quot;
- kDS1AttrHomeDirectorySoftQuota
- Used to define home directory size limit in bytes when user is notified
- that the hard limit is approaching.
-&quot;&quot;&quot;
-kDS1AttrHomeDirectorySoftQuota = &quot;dsAttrTypeStandard:HomeDirectorySoftQuota&quot;
-
-&quot;&quot;&quot;
-    kDS1AttrHomeLocOwner
-    Represents the owner of a workgroup's shared home directory.
-        Typically found in kDSStdRecordTypeGroups records.
-&quot;&quot;&quot;
-kDS1AttrHomeLocOwner = &quot;dsAttrTypeStandard:HomeLocOwner&quot;
-
-&quot;&quot;&quot;
-    kDS1StandardAttrHomeLocOwner
-    Retained for backward compatibility.
-&quot;&quot;&quot;
-kDS1StandardAttrHomeLocOwner = kDS1AttrHomeLocOwner
-
-&quot;&quot;&quot;
- kDS1AttrInternetAlias
- Used to track internet alias.
-&quot;&quot;&quot;
-kDS1AttrInternetAlias = &quot;dsAttrTypeStandard:InetAlias&quot;
-
-&quot;&quot;&quot;
- kDS1AttrKDCConfigData
- Contents of the kdc.conf file.
-&quot;&quot;&quot;
-kDS1AttrKDCConfigData = &quot;dsAttrTypeStandard:KDCConfigData&quot;
-
-&quot;&quot;&quot;
- kDS1AttrLastName
- Used for the last name of user or person record.
-&quot;&quot;&quot;
-kDS1AttrLastName = &quot;dsAttrTypeStandard:LastName&quot;
-
-&quot;&quot;&quot;
- kDS1AttrLDAPSearchBaseSuffix
- Search base suffix for a LDAP server.
-&quot;&quot;&quot;
-kDS1AttrLDAPSearchBaseSuffix = &quot;dsAttrTypeStandard:LDAPSearchBaseSuffix&quot;
-
-&quot;&quot;&quot;
- kDS1AttrLocation
- Represents the location a service is available from (usually domain name).
-     Typically found in service record types including kDSStdRecordTypeAFPServer,
-     kDSStdRecordTypeLDAPServer, and kDSStdRecordTypeWebServer.
-&quot;&quot;&quot;
-kDS1AttrLocation = &quot;dsAttrTypeStandard:Location&quot;
-
-&quot;&quot;&quot;
- kDS1AttrMapGUID
- Represents the GUID for a record's map.
-&quot;&quot;&quot;
-kDS1AttrMapGUID = &quot;dsAttrTypeStandard:MapGUID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrMCXFlags
- Used by MCX.
-&quot;&quot;&quot;
-kDS1AttrMCXFlags = &quot;dsAttrTypeStandard:MCXFlags&quot;
-
-&quot;&quot;&quot;
- kDS1AttrMCXSettings
- Used by MCX.
-&quot;&quot;&quot;
-kDS1AttrMCXSettings = &quot;dsAttrTypeStandard:MCXSettings&quot;
-
-&quot;&quot;&quot;
- kDS1AttrMailAttribute
- Holds the mail account config data.
-&quot;&quot;&quot;
-kDS1AttrMailAttribute = &quot;dsAttrTypeStandard:MailAttribute&quot;
-
-&quot;&quot;&quot;
- kDS1AttrMetaAutomountMap
- Used to query for kDSStdRecordTypeAutomount entries associated with a specific 
- kDSStdRecordTypeAutomountMap.
-&quot;&quot;&quot;
-kDS1AttrMetaAutomountMap = &quot;dsAttrTypeStandard:MetaAutomountMap&quot;
-
-&quot;&quot;&quot;
- kDS1AttrMiddleName
- Used for the middle name of user or person record.
-&quot;&quot;&quot;
-kDS1AttrMiddleName = &quot;dsAttrTypeStandard:MiddleName&quot;
-
-&quot;&quot;&quot;
- kDS1AttrModificationTimestamp
- Attribute showing date/time of record modification.
- Format is x.208 standard YYYYMMDDHHMMSSZ which we will require as GMT time.
-&quot;&quot;&quot;
-kDS1AttrModificationTimestamp = &quot;dsAttrTypeStandard:ModificationTimestamp&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNeighborhoodAlias
- Attribute type in Neighborhood records describing sub-neighborhood records.
-&quot;&quot;&quot;
-kDSNAttrNeighborhoodAlias = &quot;dsAttrTypeStandard:NeighborhoodAlias&quot;
-
-&quot;&quot;&quot;
- kDS1AttrNeighborhoodType
- Attribute type in Neighborhood records describing their function.
-&quot;&quot;&quot;
-kDS1AttrNeighborhoodType = &quot;dsAttrTypeStandard:NeighborhoodType&quot;
-
-&quot;&quot;&quot;
- kDS1AttrNetworkView
- The name of the managed network view a computer should use for browsing.
-&quot;&quot;&quot;
-kDS1AttrNetworkView = &quot;dsAttrTypeStandard:NetworkView&quot;
-
-&quot;&quot;&quot;
- kDS1AttrNFSHomeDirectory
- Defines a user's home directory mount point on the local machine.
-&quot;&quot;&quot;
-kDS1AttrNFSHomeDirectory = &quot;dsAttrTypeStandard:NFSHomeDirectory&quot;
-
-&quot;&quot;&quot;
- kDS1AttrNote
- Note attribute. Commonly used in printer records.
-&quot;&quot;&quot;
-kDS1AttrNote = &quot;dsAttrTypeStandard:Note&quot;
-
-&quot;&quot;&quot;
- kDS1AttrOwner
- Attribute type for the owner of a record. 
-        Typically the value is a LDAP distinguished name.
-&quot;&quot;&quot;
-kDS1AttrOwner = &quot;dsAttrTypeStandard:Owner&quot;
-
-&quot;&quot;&quot;
- kDS1AttrOwnerGUID
- Attribute type for the owner GUID of a group. 
-     found in group records (kDSStdRecordTypeGroups). 
-&quot;&quot;&quot;
-kDS1AttrOwnerGUID = &quot;dsAttrTypeStandard:OwnerGUID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPassword
- Holds the password or credential value.
-&quot;&quot;&quot;
-kDS1AttrPassword = &quot;dsAttrTypeStandard:Password&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPasswordPlus
- Holds marker data to indicate possible authentication redirection.
-&quot;&quot;&quot;
-kDS1AttrPasswordPlus = &quot;dsAttrTypeStandard:PasswordPlus&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPasswordPolicyOptions
- Collection of password policy options in single attribute.
- Used in user presets record.
-&quot;&quot;&quot;
-kDS1AttrPasswordPolicyOptions = &quot;dsAttrTypeStandard:PasswordPolicyOptions&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPasswordServerList
- Represents the attribute for storing the password server's replication information.
-&quot;&quot;&quot;
-kDS1AttrPasswordServerList = &quot;dsAttrTypeStandard:PasswordServerList&quot;
-
-&quot;&quot;&quot;
-    kDS1AttrPasswordServerLocation
-    Specifies the IP address or domain name of the Password Server associated
-        with a given directory node. Found in a config record named PasswordServer.
-&quot;&quot;&quot;
-kDS1AttrPasswordServerLocation = &quot;dsAttrTypeStandard:PasswordServerLocation&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPicture
- Represents the path of the picture for each user displayed in the login window.
- Found in user records (kDSStdRecordTypeUsers).
-&quot;&quot;&quot;
-kDS1AttrPicture = &quot;dsAttrTypeStandard:Picture&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPort
- Represents the port number a service is available on.
-     Typically found in service record types including kDSStdRecordTypeAFPServer,
-     kDSStdRecordTypeLDAPServer, and kDSStdRecordTypeWebServer.
-&quot;&quot;&quot;
-kDS1AttrPort = &quot;dsAttrTypeStandard:Port&quot;
-
-&quot;&quot;&quot;
-    kDS1AttrPresetUserIsAdmin
-    Flag to indicate whether users created from this preset are administrators
-        by default. Found in kDSStdRecordTypePresetUsers records.
-&quot;&quot;&quot;
-kDS1AttrPresetUserIsAdmin = &quot;dsAttrTypeStandard:PresetUserIsAdmin&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrimaryComputerGUID
- Single-valued attribute that defines a primary computer of the computer group.  
- added via extensible object for computer group record type (kDSStdRecordTypeComputerGroups)
-&quot;&quot;&quot;
-kDS1AttrPrimaryComputerGUID = &quot;dsAttrTypeStandard:PrimaryComputerGUID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrimaryComputerList
- The GUID of the computer list with which this computer record is associated.
-&quot;&quot;&quot;
-kDS1AttrPrimaryComputerList = &quot;dsAttrTypeStandard:PrimaryComputerList&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrimaryGroupID
- This is the 32 bit unique ID that represents the primary group 
- a user is part of, or the ID of a group. Format is a signed 32 bit integer
- represented as a string.
-&quot;&quot;&quot;
-kDS1AttrPrimaryGroupID = &quot;dsAttrTypeStandard:PrimaryGroupID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrinter1284DeviceID
- Single-valued attribute that defines the IEEE 1284 DeviceID of a printer.
-              This is used when configuring a printer.
-&quot;&quot;&quot;
-kDS1AttrPrinter1284DeviceID = &quot;dsAttrTypeStandard:Printer1284DeviceID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrinterLPRHost
- Standard attribute type for kDSStdRecordTypePrinters.
-&quot;&quot;&quot;
-kDS1AttrPrinterLPRHost = &quot;dsAttrTypeStandard:PrinterLPRHost&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrinterLPRQueue
- Standard attribute type for kDSStdRecordTypePrinters.
-&quot;&quot;&quot;
-kDS1AttrPrinterLPRQueue = &quot;dsAttrTypeStandard:PrinterLPRQueue&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrinterMakeAndModel
- Single-valued attribute for definition of the Printer Make and Model.  An example
-              Value would be &quot;HP LaserJet 2200&quot;.  This would be used to determine the proper PPD
-              file to be used when configuring a printer from the Directory.  This attribute
-              is based on the IPP Printing Specification RFC and IETF IPP-LDAP Printer Record.
-&quot;&quot;&quot;
-kDS1AttrPrinterMakeAndModel = &quot;dsAttrTypeStandard:PrinterMakeAndModel&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrinterType
- Standard attribute type for kDSStdRecordTypePrinters.
-&quot;&quot;&quot;
-kDS1AttrPrinterType = &quot;dsAttrTypeStandard:PrinterType&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrinterURI
- Single-valued attribute that defines the URI of a printer &quot;ipp://address&quot; or
-              &quot;smb://server/queue&quot;.  This is used when configuring a printer. This attribute
-                is based on the IPP Printing Specification RFC and IETF IPP-LDAP Printer Record.
-&quot;&quot;&quot;
-kDS1AttrPrinterURI = &quot;dsAttrTypeStandard:PrinterURI&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrinterXRISupported
- Multi-valued attribute that defines additional URIs supported by a printer.
-              This is used when configuring a printer. This attribute is based on the IPP 
-                Printing Specification RFC and IETF IPP-LDAP Printer Record.
-&quot;&quot;&quot;
-kDSNAttrPrinterXRISupported = &quot;dsAttrTypeStandard:PrinterXRISupported&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrintServiceInfoText
- Standard attribute type for kDSStdRecordTypePrinters.
-&quot;&quot;&quot;
-kDS1AttrPrintServiceInfoText = &quot;dsAttrTypeStandard:PrintServiceInfoText&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrintServiceInfoXML
- Standard attribute type for kDSStdRecordTypePrinters.
-&quot;&quot;&quot;
-kDS1AttrPrintServiceInfoXML = &quot;dsAttrTypeStandard:PrintServiceInfoXML&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrintServiceUserData
- Single-valued attribute for print quota configuration or statistics
-        (XML data). Found in user records (kDSStdRecordTypeUsers) or print service
-        statistics records (kDSStdRecordTypePrintServiceUser).
-&quot;&quot;&quot;
-kDS1AttrPrintServiceUserData = &quot;dsAttrTypeStandard:PrintServiceUserData&quot;
-
-&quot;&quot;&quot;
- kDS1AttrRealUserID
- Used by MCX.
-&quot;&quot;&quot;
-kDS1AttrRealUserID = &quot;dsAttrTypeStandard:RealUserID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrRelativeDNPrefix
- Used to map the first native LDAP attribute type required in the building of the
-  Relative Distinguished Name for LDAP record creation.
-&quot;&quot;&quot;
-kDS1AttrRelativeDNPrefix = &quot;dsAttrTypeStandard:RelativeDNPrefix&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBAcctFlags
- Account control flag.
-&quot;&quot;&quot;
-kDS1AttrSMBAcctFlags = &quot;dsAttrTypeStandard:SMBAccountFlags&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBGroupRID
- Constant for supporting PDC SMB interaction with DS.
-&quot;&quot;&quot;
-kDS1AttrSMBGroupRID = &quot;dsAttrTypeStandard:SMBGroupRID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBHome

-     UNC address of Windows homedirectory mount point (\\server\\sharepoint).
-&quot;&quot;&quot;
-kDS1AttrSMBHome = &quot;dsAttrTypeStandard:SMBHome&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBHomeDrive

-     Drive letter for homedirectory mount point.
-&quot;&quot;&quot;
-kDS1AttrSMBHomeDrive = &quot;dsAttrTypeStandard:SMBHomeDrive&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBKickoffTime
- Attribute in support of SMB interaction.
-&quot;&quot;&quot;
-kDS1AttrSMBKickoffTime = &quot;dsAttrTypeStandard:SMBKickoffTime&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBLogoffTime
- Attribute in support of SMB interaction.
-&quot;&quot;&quot;
-kDS1AttrSMBLogoffTime = &quot;dsAttrTypeStandard:SMBLogoffTime&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBLogonTime
- Attribute in support of SMB interaction.
-&quot;&quot;&quot;
-kDS1AttrSMBLogonTime = &quot;dsAttrTypeStandard:SMBLogonTime&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBPrimaryGroupSID
- SMB Primary Group Security ID, stored as a string attribute of
-    up to 64 bytes. Found in user, group, and computer records
-    (kDSStdRecordTypeUsers, kDSStdRecordTypeGroups, kDSStdRecordTypeComputers).
-&quot;&quot;&quot;
-kDS1AttrSMBPrimaryGroupSID = &quot;dsAttrTypeStandard:SMBPrimaryGroupSID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBPWDLastSet
- Attribute in support of SMB interaction.
-&quot;&quot;&quot;
-kDS1AttrSMBPWDLastSet = &quot;dsAttrTypeStandard:SMBPasswordLastSet&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBProfilePath
- Desktop management info (dock, desktop links, etc).
-&quot;&quot;&quot;
-kDS1AttrSMBProfilePath = &quot;dsAttrTypeStandard:SMBProfilePath&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBRID
- Attribute in support of SMB interaction.
-&quot;&quot;&quot;
-kDS1AttrSMBRID = &quot;dsAttrTypeStandard:SMBRID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBScriptPath
- Login script path.
-&quot;&quot;&quot;
-kDS1AttrSMBScriptPath = &quot;dsAttrTypeStandard:SMBScriptPath&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBSID
- SMB Security ID, stored as a string attribute of up to 64 bytes.
-    Found in user, group, and computer records (kDSStdRecordTypeUsers, 
-    kDSStdRecordTypeGroups, kDSStdRecordTypeComputers).
-&quot;&quot;&quot;
-kDS1AttrSMBSID = &quot;dsAttrTypeStandard:SMBSID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBUserWorkstations
- List of workstations user can login from (machine account names).
-&quot;&quot;&quot;
-kDS1AttrSMBUserWorkstations = &quot;dsAttrTypeStandard:SMBUserWorkstations&quot;
-
-&quot;&quot;&quot;
- kDS1AttrServiceType
- Represents the service type for the service.  This is the raw service type of the
-     service.  For example a service record type of kDSStdRecordTypeWebServer 
-     might have a service type of &quot;http&quot; or &quot;https&quot;.
-&quot;&quot;&quot;
-kDS1AttrServiceType = &quot;dsAttrTypeStandard:ServiceType&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSetupAdvertising
- Used for Setup Assistant automatic population.
-&quot;&quot;&quot;
-kDS1AttrSetupAdvertising = &quot;dsAttrTypeStandard:SetupAssistantAdvertising&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSetupAutoRegister
- Used for Setup Assistant automatic population.
-&quot;&quot;&quot;
-kDS1AttrSetupAutoRegister = &quot;dsAttrTypeStandard:SetupAssistantAutoRegister&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSetupLocation
- Used for Setup Assistant automatic population.
-&quot;&quot;&quot;
-kDS1AttrSetupLocation = &quot;dsAttrTypeStandard:SetupAssistantLocation&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSetupOccupation
- Used for Setup Assistant automatic population.
-&quot;&quot;&quot;
-kDS1AttrSetupOccupation = &quot;dsAttrTypeStandard:Occupation&quot;
-
-&quot;&quot;&quot;
- kDS1AttrTimeToLive
- Attribute recommending how long to cache the record's attribute values.
- Format is an unsigned 32 bit representing seconds. ie. 300 is 5 minutes.
-&quot;&quot;&quot;
-kDS1AttrTimeToLive = &quot;dsAttrTypeStandard:TimeToLive&quot;
-
-&quot;&quot;&quot;
- kDS1AttrUniqueID
- This is the 32 bit unique ID that represents the user in the legacy manner.
- Format is a signed integer represented as a string.
-&quot;&quot;&quot;
-kDS1AttrUniqueID = &quot;dsAttrTypeStandard:UniqueID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrUserCertificate
- Attribute containing the binary of the user's certificate.
- Usually found in user records. The certificate is data which identifies a user.
- This data is attested to by a known party, and can be independently verified 
- by a third party.
-&quot;&quot;&quot;
-kDS1AttrUserCertificate = &quot;dsAttrTypeStandard:UserCertificate&quot;
-
-&quot;&quot;&quot;
- kDS1AttrUserPKCS12Data
- Attribute containing binary data in PKCS #12 format. 
- Usually found in user records. The value can contain keys, certificates,
- and other related information and is encrypted with a passphrase.
-&quot;&quot;&quot;
-kDS1AttrUserPKCS12Data = &quot;dsAttrTypeStandard:UserPKCS12Data&quot;
-
-&quot;&quot;&quot;
- kDS1AttrUserShell
- Used to represent the user's shell setting.
-&quot;&quot;&quot;
-kDS1AttrUserShell = &quot;dsAttrTypeStandard:UserShell&quot;
-
-&quot;&quot;&quot;
- kDS1AttrUserSMIMECertificate
- Attribute containing the binary of the user's SMIME certificate.
- Usually found in user records. The certificate is data which identifies a user.
- This data is attested to by a known party, and can be independently verified 
- by a third party. SMIME certificates are often used for signed or encrypted
- emails.
-&quot;&quot;&quot;
-kDS1AttrUserSMIMECertificate = &quot;dsAttrTypeStandard:UserSMIMECertificate&quot;
-
-&quot;&quot;&quot;
- kDS1AttrVFSDumpFreq
- Attribute used to support mount records.
-&quot;&quot;&quot;
-kDS1AttrVFSDumpFreq = &quot;dsAttrTypeStandard:VFSDumpFreq&quot;
-
-&quot;&quot;&quot;
- kDS1AttrVFSLinkDir
- Attribute used to support mount records.
-&quot;&quot;&quot;
-kDS1AttrVFSLinkDir = &quot;dsAttrTypeStandard:VFSLinkDir&quot;
-
-&quot;&quot;&quot;
- kDS1AttrVFSPassNo
- Attribute used to support mount records.
-&quot;&quot;&quot;
-kDS1AttrVFSPassNo = &quot;dsAttrTypeStandard:VFSPassNo&quot;
-
-&quot;&quot;&quot;
- kDS1AttrVFSType
- Attribute used to support mount records.
-&quot;&quot;&quot;
-kDS1AttrVFSType = &quot;dsAttrTypeStandard:VFSType&quot;
-
-&quot;&quot;&quot;
- kDS1AttrWeblogURI
- Single-valued attribute that defines the URI of a user's weblog.
-    Usually found in user records (kDSStdRecordTypeUsers). 
-    Example: http://example.com/blog/jsmith
-&quot;&quot;&quot;
-kDS1AttrWeblogURI = &quot;dsAttrTypeStandard:WeblogURI&quot;
-
-&quot;&quot;&quot;
-    kDS1AttrXMLPlist
-    SA config settings plist.
-&quot;&quot;&quot;
-kDS1AttrXMLPlist = &quot;dsAttrTypeStandard:XMLPlist&quot;
-
-&quot;&quot;&quot;
- kDS1AttrProtocolNumber
- Single-valued attribute that defines a protocol number.  Usually found
-  in protocol records (kDSStdRecordTypeProtocols)
-&quot;&quot;&quot;
-kDS1AttrProtocolNumber = &quot;dsAttrTypeStandard:ProtocolNumber&quot;
-
-&quot;&quot;&quot;
- kDS1AttrRPCNumber
- Single-valued attribute that defines an RPC number.  Usually found
-  in RPC records (kDSStdRecordTypeRPC)
-&quot;&quot;&quot;
-kDS1AttrRPCNumber = &quot;dsAttrTypeStandard:RPCNumber&quot;
-
-&quot;&quot;&quot;
- kDS1AttrNetworkNumber
- Single-valued attribute that defines a network number.  Usually found
-  in network records (kDSStdRecordTypeNetworks)
-&quot;&quot;&quot;
-kDS1AttrNetworkNumber = &quot;dsAttrTypeStandard:NetworkNumber&quot;
-
-
-# Multiple Valued Specific Attribute Type Constants
-
-
-&quot;&quot;&quot;
- DirectoryService Multiple Valued Specific Attribute Type Constants
-&quot;&quot;&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAccessControlEntry
- Attribute type which stores directory access control directives.
-&quot;&quot;&quot;
-kDSNAttrAccessControlEntry = &quot;dsAttrTypeStandard:AccessControlEntry&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAddressLine1
- Line one of multiple lines of address data for a user.
-&quot;&quot;&quot;
-kDSNAttrAddressLine1 = &quot;dsAttrTypeStandard:AddressLine1&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAddressLine2
- Line two of multiple lines of address data for a user.
-&quot;&quot;&quot;
-kDSNAttrAddressLine2 = &quot;dsAttrTypeStandard:AddressLine2&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAddressLine3
- Line three of multiple lines of address data for a user.
-&quot;&quot;&quot;
-kDSNAttrAddressLine3 = &quot;dsAttrTypeStandard:AddressLine3&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAltSecurityIdentities
- Alternative Security Identities such as Kerberos principals.
-&quot;&quot;&quot;
-kDSNAttrAltSecurityIdentities = &quot;dsAttrTypeStandard:AltSecurityIdentities&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAreaCode
- Area code of a user's phone number.
-&quot;&quot;&quot;
-kDSNAttrAreaCode = &quot;dsAttrTypeStandard:AreaCode&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAuthenticationAuthority
- Determines what mechanism is used to verify or set a user's password.
-     If multiple values are present, the first attributes returned take precedence.
-     Typically found in User records (kDSStdRecordTypeUsers).
-&quot;&quot;&quot;
-kDSNAttrAuthenticationAuthority = &quot;dsAttrTypeStandard:AuthenticationAuthority&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAutomountInformation
- Used to store automount information in kDSStdRecordTypeAutomount records.
-&quot;&quot;&quot;
-kDSNAttrAutomountInformation = &quot;dsAttrTypeStandard:AutomountInformation&quot;
-
-&quot;&quot;&quot;
- kDSNAttrBootParams
- Attribute type in host or machine records for storing boot params.
-&quot;&quot;&quot;
-kDSNAttrBootParams = &quot;dsAttrTypeStandard:BootParams&quot;
-
-&quot;&quot;&quot;
- kDSNAttrBuilding
- Represents the building name for a user or person record.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrBuilding = &quot;dsAttrTypeStandard:Building&quot;
-
-&quot;&quot;&quot;
- kDSNAttrCalendarPrincipalURI
- the URI for a record's calendar
-&quot;&quot;&quot;
-kDSNAttrCalendarPrincipalURI = &quot;dsAttrTypeStandard:CalendarPrincipalURI&quot;
-
-&quot;&quot;&quot;
- kDSNAttrCity
- Usually, city for a user or person record.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrCity = &quot;dsAttrTypeStandard:City&quot;
-
-&quot;&quot;&quot;
- kDSNAttrCompany
- attribute that defines the user's company.
- Example: Apple Computer, Inc
-&quot;&quot;&quot;
-kDSNAttrCompany = &quot;dsAttrTypeStandard:Company&quot;
-
-&quot;&quot;&quot;
- kDSNAttrComputerAlias
- Attribute type in Neighborhood records describing computer records pointed to by
- this neighborhood.
-&quot;&quot;&quot;
-kDSNAttrComputerAlias = &quot;dsAttrTypeStandard:ComputerAlias&quot;
-
-&quot;&quot;&quot;
- kDSNAttrComputers
- List of computers.
-&quot;&quot;&quot;
-kDSNAttrComputers = &quot;dsAttrTypeStandard:Computers&quot;
-
-&quot;&quot;&quot;
- kDSNAttrCountry
- Represents country of a record entry.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrCountry = &quot;dsAttrTypeStandard:Country&quot;
-
-&quot;&quot;&quot;
- kDSNAttrDepartment
- Represents the department name of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrDepartment = &quot;dsAttrTypeStandard:Department&quot;
-
-&quot;&quot;&quot;
- kDSNAttrDNSName
- Domain Name Service name.
-&quot;&quot;&quot;
-kDSNAttrDNSName = &quot;dsAttrTypeStandard:DNSName&quot;
-
-&quot;&quot;&quot;
- kDSNAttrEMailAddress
- Email address of usually a user record.
-&quot;&quot;&quot;
-kDSNAttrEMailAddress = &quot;dsAttrTypeStandard:EMailAddress&quot;
-
-&quot;&quot;&quot;
- kDSNAttrEMailContacts
- multi-valued attribute that defines a record's custom email addresses .
-     found in user records (kDSStdRecordTypeUsers). 
-    Example: home:johndoe@mymail.com
-&quot;&quot;&quot;
-kDSNAttrEMailContacts = &quot;dsAttrTypeStandard:EMailContacts&quot;
-
-&quot;&quot;&quot;
- kDSNAttrFaxNumber
- Represents the FAX numbers of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrFaxNumber = &quot;dsAttrTypeStandard:FAXNumber&quot;
-
-&quot;&quot;&quot;
- kDSNAttrGroup
- List of groups.
-&quot;&quot;&quot;
-kDSNAttrGroup = &quot;dsAttrTypeStandard:Group&quot;
-
-&quot;&quot;&quot;
- kDSNAttrGroupMembers
- Attribute type in group records containing lists of GUID values for members other than groups.
-&quot;&quot;&quot;
-kDSNAttrGroupMembers = &quot;dsAttrTypeStandard:GroupMembers&quot;
-
-&quot;&quot;&quot;
- kDSNAttrGroupMembership
- Usually a list of users that below to a given group record.
-&quot;&quot;&quot;
-kDSNAttrGroupMembership = &quot;dsAttrTypeStandard:GroupMembership&quot;
-
-&quot;&quot;&quot;
- kDSNAttrGroupServices
- xml-plist attribute that defines a group's services .
-     found in group records (kDSStdRecordTypeGroups). 
-&quot;&quot;&quot;
-kDSNAttrGroupServices = &quot;dsAttrTypeStandard:GroupServices&quot;
-
-&quot;&quot;&quot;
- kDSNAttrHomePhoneNumber
- Home telephone number of a user or person.
-&quot;&quot;&quot;
-kDSNAttrHomePhoneNumber = &quot;dsAttrTypeStandard:HomePhoneNumber&quot;
-
-&quot;&quot;&quot;
- kDSNAttrHTML
- HTML location.
-&quot;&quot;&quot;
-kDSNAttrHTML = &quot;dsAttrTypeStandard:HTML&quot;
-
-&quot;&quot;&quot;
- kDSNAttrHomeDirectory
- Network home directory URL.
-&quot;&quot;&quot;
-kDSNAttrHomeDirectory = &quot;dsAttrTypeStandard:HomeDirectory&quot;
-
-&quot;&quot;&quot;
- kDSNAttrIMHandle
- Represents the Instant Messaging handles of a user.
- Values should be prefixed with the appropriate IM type
- ie. AIM:, Jabber:, MSN:, Yahoo:, or ICQ:
- Usually found in user records (kDSStdRecordTypeUsers).
-&quot;&quot;&quot;
-kDSNAttrIMHandle = &quot;dsAttrTypeStandard:IMHandle&quot;
-
-&quot;&quot;&quot;
- kDSNAttrIPAddress
- IP address expressed either as domain or IP notation.
-&quot;&quot;&quot;
-kDSNAttrIPAddress = &quot;dsAttrTypeStandard:IPAddress&quot;
-
-&quot;&quot;&quot;
-    kDSNAttrIPAddressAndENetAddress
- A pairing of IPv4 or IPv6 addresses with Ethernet addresses 
- (e.g., &quot;10.1.1.1/00:16:cb:92:56:41&quot;).  Usually found on kDSStdRecordTypeComputers for use by 
- services that need specific pairing of the two values.  This should be in addition to 
- kDSNAttrIPAddress, kDSNAttrIPv6Address and kDS1AttrENetAddress. This is necessary because not
- all directories return attribute values in a guaranteed order.
-&quot;&quot;&quot;
-kDSNAttrIPAddressAndENetAddress = &quot;dsAttrTypeStandard:IPAddressAndENetAddress&quot;
-
-&quot;&quot;&quot;
- kDSNAttrIPv6Address
- IPv6 address expressed in the standard notation (e.g., &quot;fe80::236:caff:fcc2:5641&quot; )
- Usually found on kDSStdRecordTypeComputers, kDSStdRecordTypeHosts, and 
- kDSStdRecordTypeMachines.
-&quot;&quot;&quot;
-kDSNAttrIPv6Address = &quot;dsAttrTypeStandard:IPv6Address&quot;
-
-&quot;&quot;&quot;
- kDSNAttrJPEGPhoto
- Used to store binary picture data in JPEG format. 
- Usually found in user, people or group records (kDSStdRecordTypeUsers, 
- kDSStdRecordTypePeople, kDSStdRecordTypeGroups).
-&quot;&quot;&quot;
-kDSNAttrJPEGPhoto = &quot;dsAttrTypeStandard:JPEGPhoto&quot;
-
-&quot;&quot;&quot;
- kDSNAttrJobTitle
- Represents the job title of a user.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrJobTitle = &quot;dsAttrTypeStandard:JobTitle&quot;
-
-&quot;&quot;&quot;
- kDSNAttrKDCAuthKey
- KDC master key RSA encrypted with realm public key.
-&quot;&quot;&quot;
-kDSNAttrKDCAuthKey = &quot;dsAttrTypeStandard:KDCAuthKey&quot;
-
-&quot;&quot;&quot;
-    kDSNAttrKeywords
-    Keywords using for searching capability.
-&quot;&quot;&quot;
-kDSNAttrKeywords = &quot;dsAttrTypeStandard:Keywords&quot;
-
-&quot;&quot;&quot;
- kDSNAttrLDAPReadReplicas
- List of LDAP server URLs which can each be used to read directory data.
-&quot;&quot;&quot;
-kDSNAttrLDAPReadReplicas = &quot;dsAttrTypeStandard:LDAPReadReplicas&quot;
-
-&quot;&quot;&quot;
- kDSNAttrLDAPWriteReplicas
- List of LDAP server URLs which can each be used to write directory data.
-&quot;&quot;&quot;
-kDSNAttrLDAPWriteReplicas = &quot;dsAttrTypeStandard:LDAPWriteReplicas&quot;
-
-&quot;&quot;&quot;
- kDSNAttrMachineServes
- Attribute type in host or machine records for storing NetInfo 
-        domains served.
-&quot;&quot;&quot;
-kDSNAttrMachineServes = &quot;dsAttrTypeStandard:MachineServes&quot;
-
-&quot;&quot;&quot;
- kDSNAttrMapCoordinates
- attribute that defines coordinates for a user's location .
-*     found in user records (kDSStdRecordTypeUsers) and resource records (kDSStdRecordTypeResources).
-    Example: 7.7,10.6
-&quot;&quot;&quot;
-kDSNAttrMapCoordinates = &quot;dsAttrTypeStandard:MapCoordinates&quot;
-
-&quot;&quot;&quot;
- kDSNAttrMapURI
- attribute that defines the URI of a user's location.
-    Usually found in user records (kDSStdRecordTypeUsers). 
-    Example: http://example.com/bldg1
-&quot;&quot;&quot;
-kDSNAttrMapURI = &quot;dsAttrTypeStandard:MapURI&quot;
-
-&quot;&quot;&quot;
- kDSNAttrMCXSettings
- Used by MCX.
-&quot;&quot;&quot;
-kDSNAttrMCXSettings = &quot;dsAttrTypeStandard:MCXSettings&quot;
-
-&quot;&quot;&quot;
- kDSNAttrMIME
- Data contained in this attribute type is a fully qualified MIME Type. 
-&quot;&quot;&quot;
-kDSNAttrMIME = &quot;dsAttrTypeStandard:MIME&quot;
-
-&quot;&quot;&quot;
- kDSNAttrMember
- List of member records. 
-&quot;&quot;&quot;
-kDSNAttrMember = &quot;dsAttrTypeStandard:Member&quot;
-
-&quot;&quot;&quot;
- kDSNAttrMobileNumber
- Represents the mobile numbers of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrMobileNumber = &quot;dsAttrTypeStandard:MobileNumber&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNBPEntry
- Appletalk data.
-&quot;&quot;&quot;
-kDSNAttrNBPEntry = &quot;dsAttrTypeStandard:NBPEntry&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNestedGroups
- Attribute type in group records for the list of GUID values for nested groups.
-&quot;&quot;&quot;
-kDSNAttrNestedGroups = &quot;dsAttrTypeStandard:NestedGroups&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNetGroups
- Attribute type that indicates which netgroups its record is a member of.
-        Found in user, host, and netdomain records.
-&quot;&quot;&quot;
-kDSNAttrNetGroups = &quot;dsAttrTypeStandard:NetGroups&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNickName
- Represents the nickname of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrNickName = &quot;dsAttrTypeStandard:NickName&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNodePathXMLPlist
- Attribute type in Neighborhood records describing the DS Node to search while
- looking up aliases in this neighborhood.
-&quot;&quot;&quot;
-kDSNAttrNodePathXMLPlist = &quot;dsAttrTypeStandard:NodePathXMLPlist&quot;
-
-&quot;&quot;&quot;
- kDSNAttrOrganizationInfo
- Usually the organization info of a user.
-&quot;&quot;&quot;
-kDSNAttrOrganizationInfo = &quot;dsAttrTypeStandard:OrganizationInfo&quot;
-
-&quot;&quot;&quot;
- kDSNAttrOrganizationName
- Usually the organization of a user.
-&quot;&quot;&quot;
-kDSNAttrOrganizationName = &quot;dsAttrTypeStandard:OrganizationName&quot;
-
-&quot;&quot;&quot;
- kDSNAttrPagerNumber
- Represents the pager numbers of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrPagerNumber = &quot;dsAttrTypeStandard:PagerNumber&quot;
-
-&quot;&quot;&quot;
- kDSNAttrPhoneContacts
- multi-valued attribute that defines a record's custom phone numbers .
-     found in user records (kDSStdRecordTypeUsers). 
-    Example: home fax:408-555-4444
-&quot;&quot;&quot;
-kDSNAttrPhoneContacts = &quot;dsAttrTypeStandard:PhoneContacts&quot;
-
-
-&quot;&quot;&quot;
- kDSNAttrPhoneNumber
- Telephone number of a user.
-&quot;&quot;&quot;
-kDSNAttrPhoneNumber = &quot;dsAttrTypeStandard:PhoneNumber&quot;
-
-&quot;&quot;&quot;
- kDSNAttrPGPPublicKey
- Pretty Good Privacy public encryption key.
-&quot;&quot;&quot;
-kDSNAttrPGPPublicKey = &quot;dsAttrTypeStandard:PGPPublicKey&quot;
-
-&quot;&quot;&quot;
- kDSNAttrPostalAddress
- The postal address usually excluding postal code.
-&quot;&quot;&quot;
-kDSNAttrPostalAddress = &quot;dsAttrTypeStandard:PostalAddress&quot;
-
-&quot;&quot;&quot;
-* kDSNAttrPostalAddressContacts
-* multi-valued attribute that defines a record's alternate postal addresses .
-*     found in user records (kDSStdRecordTypeUsers) and resource records (kDSStdRecordTypeResources).
-&quot;&quot;&quot;
-kDSNAttrPostalAddressContacts = &quot;dsAttrTypeStandard:PostalAddressContacts&quot;
-
-&quot;&quot;&quot;
- kDSNAttrPostalCode
- The postal code such as zip code in the USA.
-&quot;&quot;&quot;
-kDSNAttrPostalCode = &quot;dsAttrTypeStandard:PostalCode&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNamePrefix
- Represents the title prefix of a user or person.
- ie. Mr., Ms., Mrs., Dr., etc.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrNamePrefix = &quot;dsAttrTypeStandard:NamePrefix&quot;
-
-&quot;&quot;&quot;
- kDSNAttrProtocols
- List of protocols.
-&quot;&quot;&quot;
-kDSNAttrProtocols = &quot;dsAttrTypeStandard:Protocols&quot;
-
-&quot;&quot;&quot;
- kDSNAttrRecordName
- List of names/keys for this record.
-&quot;&quot;&quot;
-kDSNAttrRecordName = &quot;dsAttrTypeStandard:RecordName&quot;
-
-&quot;&quot;&quot;
- kDSNAttrRelationships
- multi-valued attribute that defines the relationship to the record type .
-     found in user records (kDSStdRecordTypeUsers). 
-    Example: brother:John
-&quot;&quot;&quot;
-kDSNAttrRelationships = &quot;dsAttrTypeStandard:Relationships&quot;
-
-&quot;&quot;&quot;
-* kDSNAttrResourceInfo
-* multi-valued attribute that defines a resource record's info.
-&quot;&quot;&quot;
-kDSNAttrResourceInfo = &quot;dsAttrTypeStandard:ResourceInfo&quot;
-
-&quot;&quot;&quot;
- kDSNAttrResourceType
- Attribute type for the kind of resource. 
-     found in resource records (kDSStdRecordTypeResources). 
-    Example: ConferenceRoom
-&quot;&quot;&quot;
-kDSNAttrResourceType = &quot;dsAttrTypeStandard:ResourceType&quot;
-
-&quot;&quot;&quot;
- kDSNAttrServicesLocator
- Attribute describing the services hosted for the record.
-&quot;&quot;&quot;
-kDSNAttrServicesLocator = &quot;dsAttrTypeStandard:ServicesLocator&quot;
-
-&quot;&quot;&quot;
- kDSNAttrState
- The state or province of a country.
-&quot;&quot;&quot;
-kDSNAttrState = &quot;dsAttrTypeStandard:State&quot;
-
-&quot;&quot;&quot;
- kDSNAttrStreet
- Represents the street address of a user or person.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrStreet = &quot;dsAttrTypeStandard:Street&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNameSuffix
- Represents the name suffix of a user or person.
- ie. Jr., Sr., etc.
- Usually found in user or people records (kDSStdRecordTypeUsers or 
- kDSStdRecordTypePeople).
-&quot;&quot;&quot;
-kDSNAttrNameSuffix = &quot;dsAttrTypeStandard:NameSuffix&quot;
-
-&quot;&quot;&quot;
- kDSNAttrURL
- List of URLs.
-&quot;&quot;&quot;
-kDSNAttrURL = &quot;dsAttrTypeStandard:URL&quot;
-
-&quot;&quot;&quot;
- kDSNAttrURLForNSL
- List of URLs used by NSL.
-&quot;&quot;&quot;
-kDSNAttrURLForNSL = &quot;dsAttrTypeStandard:URLForNSL&quot;
-
-&quot;&quot;&quot;
- kDSNAttrVFSOpts
- Used in support of mount records.
-&quot;&quot;&quot;
-kDSNAttrVFSOpts = &quot;dsAttrTypeStandard:VFSOpts&quot;
-
-
-
-# Other Attribute Type Constants
-
-
-&quot;&quot;&quot;
- DirectoryService Other Attribute Type Constants Not Mapped by Directory Node Plugins
- Mainly used internally by the DirectoryService Daemon or made available via dsGetDirNodeInfo()
-&quot;&quot;&quot;
-
-&quot;&quot;&quot;
- kDS1AttrAdminStatus
- Retained only for backward compatibility.
-&quot;&quot;&quot;
-kDS1AttrAdminStatus = &quot;dsAttrTypeStandard:AdminStatus&quot;
-
-&quot;&quot;&quot;
- kDS1AttrAlias
- Alias attribute, contain pointer to another node/record/attribute.
-&quot;&quot;&quot;
-kDS1AttrAlias = &quot;dsAttrTypeStandard:Alias&quot;
-
-&quot;&quot;&quot;
- kDS1AttrAuthCredential
- An &quot;auth&quot; credential, to be used to authenticate to other Directory nodes.
-&quot;&quot;&quot;
-kDS1AttrAuthCredential = &quot;dsAttrTypeStandard:AuthCredential&quot;
-
-&quot;&quot;&quot;
- kDS1AttrCopyTimestamp
- Timestamp used in local account caching.
-&quot;&quot;&quot;
-kDS1AttrCopyTimestamp = &quot;dsAttrTypeStandard:CopyTimestamp&quot;
-
-&quot;&quot;&quot;
-    kDS1AttrDateRecordCreated
-    Date of record creation.
-&quot;&quot;&quot;
-kDS1AttrDateRecordCreated = &quot;dsAttrTypeStandard:DateRecordCreated&quot;
-
-&quot;&quot;&quot;
- kDS1AttrKerberosRealm
- Supports Kerberized SMB Server services.
-&quot;&quot;&quot;
-kDS1AttrKerberosRealm = &quot;dsAttrTypeStandard:KerberosRealm&quot;
-
-&quot;&quot;&quot;
- kDS1AttrNTDomainComputerAccount
- Supports Kerberized SMB Server services.
-&quot;&quot;&quot;
-kDS1AttrNTDomainComputerAccount = &quot;dsAttrTypeStandard:NTDomainComputerAccount&quot;
-
-&quot;&quot;&quot;
- kDSNAttrOriginalHomeDirectory
- Home directory URL used in local account caching.
-&quot;&quot;&quot;
-kDSNAttrOriginalHomeDirectory = &quot;dsAttrTypeStandard:OriginalHomeDirectory&quot;
-
-&quot;&quot;&quot;
- kDS1AttrOriginalNFSHomeDirectory
- NFS home directory used in local account caching.
-&quot;&quot;&quot;
-kDS1AttrOriginalNFSHomeDirectory = &quot;dsAttrTypeStandard:OriginalNFSHomeDirectory&quot;
-
-&quot;&quot;&quot;
- kDS1AttrOriginalNodeName
- Nodename used in local account caching.
-&quot;&quot;&quot;
-kDS1AttrOriginalNodeName = &quot;dsAttrTypeStandard:OriginalNodeName&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPrimaryNTDomain
- Supports Kerberized SMB Server services.
-&quot;&quot;&quot;
-kDS1AttrPrimaryNTDomain = &quot;dsAttrTypeStandard:PrimaryNTDomain&quot;
-
-&quot;&quot;&quot;
- kDS1AttrPwdAgingPolicy
- Contains the password aging policy data for an authentication capable record.
-&quot;&quot;&quot;
-kDS1AttrPwdAgingPolicy = &quot;dsAttrTypeStandard:PwdAgingPolicy&quot;
-
-&quot;&quot;&quot;
- kDS1AttrRARA
- Retained only for backward compatibility.
-&quot;&quot;&quot;
-kDS1AttrRARA = &quot;dsAttrTypeStandard:RARA&quot;
-
-&quot;&quot;&quot;
- kDS1AttrReadOnlyNode
- Can be found using dsGetDirNodeInfo and will return one of
- ReadOnly, ReadWrite, or WriteOnly strings.
- Note that ReadWrite does not imply fully readable or writable
-&quot;&quot;&quot;
-kDS1AttrReadOnlyNode = &quot;dsAttrTypeStandard:ReadOnlyNode&quot;
-
-&quot;&quot;&quot;
- kDS1AttrRecordImage
- A binary image of the record and all it's attributes.
- Has never been supported.
-&quot;&quot;&quot;
-kDS1AttrRecordImage = &quot;dsAttrTypeStandard:RecordImage&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSMBGroupRID
- Attributefor supporting PDC SMB interaction.
-&quot;&quot;&quot;
-kDS1AttrSMBGroupRID = &quot;dsAttrTypeStandard:SMBGroupRID&quot;
-
-&quot;&quot;&quot;
- kDS1AttrTimePackage
- Data of Create, Modify, Backup time in UTC.
-&quot;&quot;&quot;
-kDS1AttrTimePackage = &quot;dsAttrTypeStandard:TimePackage&quot;
-
-&quot;&quot;&quot;
- kDS1AttrTotalSize
- checksum/meta data.
-&quot;&quot;&quot;
-kDS1AttrTotalSize = &quot;dsAttrTypeStandard:TotalSize&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAllNames
- Backward compatibility only - all possible names for a record.
- Has never been supported.
-&quot;&quot;&quot;
-kDSNAttrAllNames = &quot;dsAttrTypeStandard:AllNames&quot;
-
-&quot;&quot;&quot;
- kDSNAttrAuthMethod
- Authentication method for an authentication capable record.
-&quot;&quot;&quot;
-kDSNAttrAuthMethod = &quot;dsAttrTypeStandard:AuthMethod&quot;
-
-&quot;&quot;&quot;
- kDSNAttrMetaNodeLocation
- Meta attribute returning registered node name by directory node plugin.
-&quot;&quot;&quot;
-kDSNAttrMetaNodeLocation = &quot;dsAttrTypeStandard:AppleMetaNodeLocation&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNodePath
- Sub strings of a Directory Service Node given in order.
-&quot;&quot;&quot;
-kDSNAttrNodePath = &quot;dsAttrTypeStandard:NodePath&quot;
-
-&quot;&quot;&quot;
- kDSNAttrPlugInInfo
- Information (version, signature, about, credits, etc.) about the plug-in
- that is actually servicing a particular directory node.
- Has never been supported.
-&quot;&quot;&quot;
-kDSNAttrPlugInInfo = &quot;dsAttrTypeStandard:PlugInInfo&quot;
-
-&quot;&quot;&quot;
- kDSNAttrRecordAlias
- No longer supported in Mac OS X 10.4 or later.
-&quot;&quot;&quot;
-kDSNAttrRecordAlias = &quot;dsAttrTypeStandard:RecordAlias&quot;
-
-&quot;&quot;&quot;
- kDSNAttrRecordType
- Single Valued for a Record, Multi-valued for a Directory Node.
-&quot;&quot;&quot;
-kDSNAttrRecordType = &quot;dsAttrTypeStandard:RecordType&quot;
-
-&quot;&quot;&quot;
- kDSNAttrSchema
- List of attribute types.
-&quot;&quot;&quot;
-kDSNAttrSchema = &quot;dsAttrTypeStandard:Scheama&quot;
-
-&quot;&quot;&quot;
- kDSNAttrSetPasswdMethod
- Retained only for backward compatibility.
-&quot;&quot;&quot;
-kDSNAttrSetPasswdMethod = &quot;dsAttrTypeStandard:SetPasswdMethod&quot;
-
-&quot;&quot;&quot;
- kDSNAttrSubNodes
- Attribute of a node which lists the available subnodes
-        of that node.
-&quot;&quot;&quot;
-kDSNAttrSubNodes = &quot;dsAttrTypeStandard:SubNodes&quot;
-
-&quot;&quot;&quot;
- kStandardSourceAlias
- No longer supported in Mac OS X 10.4 or later.
-&quot;&quot;&quot;
-kStandardSourceAlias = &quot;dsAttrTypeStandard:AppleMetaAliasSource&quot;
-
-&quot;&quot;&quot;
- kStandardTargetAlias
- No longer supported in Mac OS X 10.4 or later.
-&quot;&quot;&quot;
-kStandardTargetAlias = &quot;dsAttrTypeStandard:AppleMetaAliasTarget&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNetGroupTriplet
- Multivalued attribute that defines the host, user and domain triplet combinations
-  to support NetGroups.  Each attribute value is comma separated string to maintain the
-  triplet (e.g., host,user,domain).
-&quot;&quot;&quot;
-kDSNAttrNetGroupTriplet = &quot;dsAttrTypeStandard:NetGroupTriplet&quot;
-
-
-# Search Node attribute type Constants
-
-
-&quot;&quot;&quot;
- Search Node attribute type Constants
-&quot;&quot;&quot;

-&quot;&quot;&quot;
- kDS1AttrSearchPath
- Search path used by the search node.
-&quot;&quot;&quot;
-kDS1AttrSearchPath = &quot;dsAttrTypeStandard:SearchPath&quot;
-
-&quot;&quot;&quot;
- kDSNAttrSearchPath
- Retained only for backward compatibility.
-&quot;&quot;&quot;
-kDSNAttrSearchPath = &quot;dsAttrTypeStandard:SearchPath&quot;
-
-&quot;&quot;&quot;
- kDS1AttrSearchPolicy
- Search policy for the search node.
-&quot;&quot;&quot;
-kDS1AttrSearchPolicy = &quot;dsAttrTypeStandard:SearchPolicy&quot;
-
-&quot;&quot;&quot;
- kDS1AttrNSPSearchPath
- Automatic search path defined by the search node.
-&quot;&quot;&quot;
-kDS1AttrNSPSearchPath = &quot;dsAttrTypeStandard:NSPSearchPath&quot;
-
-&quot;&quot;&quot;
- kDSNAttrNSPSearchPath
- Retained only for backward compatibility.
-&quot;&quot;&quot;
-kDSNAttrNSPSearchPath = &quot;dsAttrTypeStandard:NSPSearchPath&quot;
-
-&quot;&quot;&quot;
- kDS1AttrLSPSearchPath
- Local only search path defined by the search node.
-&quot;&quot;&quot;
-kDS1AttrLSPSearchPath = &quot;dsAttrTypeStandard:LSPSearchPath&quot;
-
-&quot;&quot;&quot;
- kDSNAttrLSPSearchPath
- Retained only for backward compatibility.
-&quot;&quot;&quot;
-kDSNAttrLSPSearchPath = &quot;dsAttrTypeStandard:LSPSearchPath&quot;
-
-&quot;&quot;&quot;
- kDS1AttrCSPSearchPath
- Admin user configured custom search path defined by the search node.
-&quot;&quot;&quot;
-kDS1AttrCSPSearchPath = &quot;dsAttrTypeStandard:CSPSearchPath&quot;
-
-&quot;&quot;&quot;
- kDSNAttrCSPSearchPath
- Retained only for backward compatibility.
-&quot;&quot;&quot;
-kDSNAttrCSPSearchPath = &quot;dsAttrTypeStandard:CSPSearchPath&quot;
-
</del></span></pre></div>
<a id="twexttrunktwextwhoopendirectorydsquerypy"></a>
<div class="delfile"><h4>Deleted: twext/trunk/twext/who/opendirectory/dsquery.py (12126 => 12127)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/who/opendirectory/dsquery.py        2013-12-18 00:50:59 UTC (rev 12126)
+++ twext/trunk/twext/who/opendirectory/dsquery.py        2013-12-18 18:29:24 UTC (rev 12127)
</span><span class="lines">@@ -1,137 +0,0 @@
</span><del>-##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-##
-from __future__ import print_function
-
-&quot;&quot;&quot;
-Compound query builder. We do this in Python to avoid having to mess
-with pass a complex Python object hierarchy into C. These classes allow us to
-build the query in Python and generate the compound query string that the directory
-service C api requires.
-&quot;&quot;&quot;
-
-import dsattributes
-
-
-
-class match(object):
-    &quot;&quot;&quot;
-    Represents and attribute/value match operation.
-    &quot;&quot;&quot;
-
-    def __init__(self, attribute, value, matchType):
-        self.attribute = attribute
-        self.value = value
-        self.matchType = matchType
-
-    def generate(self):
-        return {
-            dsattributes.eDSExact :        &quot;(%s=%s)&quot;,
-            dsattributes.eDSStartsWith :   &quot;(%s=%s*)&quot;,
-            dsattributes.eDSEndsWith :     &quot;(%s=*%s)&quot;,
-            dsattributes.eDSContains :     &quot;(%s=*%s*)&quot;,
-            dsattributes.eDSLessThan :     &quot;(%s&lt;%s)&quot;,
-            dsattributes.eDSGreaterThan :  &quot;(%s&gt;%s)&quot;,
-        }.get(self.matchType, &quot;(%s=*%s*)&quot;) % (self.attribute, self.value,)
-
-class expression(object):
-    &quot;&quot;&quot;
-    Represents a query expression that includes a boolean operator, and a list
-    of sub-expressions operated on. The sub-expressions can either be another expression
-    object or a match object.
-    &quot;&quot;&quot;
-
-    AND = &quot;&amp;&quot;
-    OR  = &quot;|&quot;
-    NOT = &quot;!&quot;
-
-    def __init__(self, operator, subexpressions):
-        assert(operator == expression.AND or operator == expression.OR or operator == expression.NOT)
-        self.operator = operator
-        self.subexpressions = subexpressions
-
-    def generate(self):
-        result = &quot;&quot;
-        if self.operator == expression.NOT:
-            result += &quot;(&quot;
-            result += self.operator
-            result += self.subexpressions.generate()
-            result += &quot;)&quot;
-        else:
-            if len(self.subexpressions) &gt; 1:
-                result += &quot;(&quot;
-                result += self.operator
-            for sub in self.subexpressions:
-                result += sub.generate()
-            if len(self.subexpressions) &gt; 1:
-                result += &quot;)&quot;
-        return result
-
-
-# Do some tests
-if __name__=='__main__':
-    exprs = (
-        (expression(
-            expression.AND, (
-                expression(expression.OR, (match(&quot;ResourceType&quot;, &quot;xyz&quot;, dsattributes.eDSExact), match(&quot;ResourceType&quot;, &quot;abc&quot;, dsattributes.eDSExact))),
-                match(&quot;ServicesLocator&quot;, &quot;GUID:VGUID:calendar&quot;, dsattributes.eDSStartsWith),
-            )
-        ), &quot;(&amp;(|(ResourceType=xyz)(ResourceType=abc))(ServicesLocator=GUID:VGUID:calendar*))&quot;),
-        (expression(
-            expression.AND, (
-                expression(expression.OR, (match(&quot;ResourceType&quot;, &quot;xyz&quot;, dsattributes.eDSStartsWith), match(&quot;ResourceType&quot;, &quot;abc&quot;, dsattributes.eDSEndsWith))),
-                match(&quot;ServicesLocator&quot;, &quot;GUID:VGUID:calendar&quot;, dsattributes.eDSContains),
-            )
-        ), &quot;(&amp;(|(ResourceType=xyz*)(ResourceType=*abc))(ServicesLocator=*GUID:VGUID:calendar*))&quot;),
-        (expression(
-            expression.AND, (
-                expression(expression.AND, (match(&quot;ResourceType&quot;, &quot;xyz&quot;, dsattributes.eDSLessThan), match(&quot;ResourceType&quot;, &quot;abc&quot;, dsattributes.eDSGreaterThan))),
-                match(&quot;ServicesLocator&quot;, &quot;GUID:VGUID:calendar&quot;, 0xBAD),
-            )
-        ), &quot;(&amp;(&amp;(ResourceType&lt;xyz)(ResourceType&gt;abc))(ServicesLocator=*GUID:VGUID:calendar*))&quot;),
-        (expression(
-            expression.AND, (
-                match(&quot;ServicesLocator&quot;, &quot;GUID:VGUID:calendar&quot;, 0xBAD),
-            )
-        ), &quot;(ServicesLocator=*GUID:VGUID:calendar*)&quot;),
-        (expression(
-            expression.NOT, match(dsattributes.kDSNAttrNickName, &quot;&quot;, dsattributes.eDSStartsWith )
-        ), &quot;(!(&quot; + dsattributes.kDSNAttrNickName + &quot;=*))&quot;),
-        (expression(
-            expression.AND, (
-               expression(
-                    expression.NOT, match(dsattributes.kDSNAttrNickName, &quot;Billy&quot;, dsattributes.eDSContains )
-               ),
-               expression(
-                    expression.NOT, match(dsattributes.kDSNAttrEMailAddress, &quot;Billy&quot;, dsattributes.eDSContains )
-               ),
-            ),
-        ), &quot;(&amp;(!(&quot; + dsattributes.kDSNAttrNickName + &quot;=*Billy*))(!(&quot; + dsattributes.kDSNAttrEMailAddress + &quot;=*Billy*)))&quot;),
-        (expression(
-            expression.NOT, expression(
-                    expression.OR, (
-                        match(dsattributes.kDSNAttrNickName, &quot;&quot;, dsattributes.eDSStartsWith ),
-                        match(dsattributes.kDSNAttrEMailAddress, &quot;&quot;, dsattributes.eDSStartsWith ),
-                    ),
-            ),
-        ), &quot;(!(|(&quot;+dsattributes.kDSNAttrNickName+&quot;=*)(&quot;+dsattributes.kDSNAttrEMailAddress+&quot;=*)))&quot;),
-    )
-
-    for expr, result in exprs:
-        gen = expr.generate()
-        if gen != result:
-            print(&quot;Generate expression %s != %s&quot; % (gen, result,))
-    print(&quot;Done.&quot;)
</del></span></pre></div>
<a id="twexttrunktwextwhoopendirectoryopendirectorypy"></a>
<div class="delfile"><h4>Deleted: twext/trunk/twext/who/opendirectory/opendirectory.py (12126 => 12127)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/who/opendirectory/opendirectory.py        2013-12-18 00:50:59 UTC (rev 12126)
+++ twext/trunk/twext/who/opendirectory/opendirectory.py        2013-12-18 18:29:24 UTC (rev 12127)
</span><span class="lines">@@ -1,519 +0,0 @@
</span><del>-##
-# Copyright (c) 2006-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-&quot;&quot;&quot;
-OpenDirectory.framework access via PyObjC
-&quot;&quot;&quot;
-
-import odframework
-import objc
-import dsattributes
-import base64
-from twext.python.log import Logger
-import Foundation
-
-
-def autoPooled(f):
-    &quot;&quot;&quot;
-    A decorator which creates an autorelease pool and deletes it, causing it
-    to drain
-    &quot;&quot;&quot;
-    def autoPooledFunction(*args, **kwds):
-        pool = Foundation.NSAutoreleasePool.alloc().init()
-        try:
-            return f(*args, **kwds)
-        finally:
-            del pool
-    return autoPooledFunction
-
-
-log = Logger()
-
-NUM_TRIES = 3
-
-RETRY_CODES = (
-    5200, # Server unreachable
-    5201, # Server not found
-    5202, # Server error
-    5203, # Server timeout
-    5204, # Contact master
-    5205, # Server communication error
-)
-INCORRECT_CREDENTIALS = 5000
-
-# Single-value attributes (must be converted from lists):
-SINGLE_VALUE_ATTRIBUTES = [
-    dsattributes.kDS1AttrBirthday,
-    dsattributes.kDS1AttrComment,
-    dsattributes.kDS1AttrCreationTimestamp,
-    dsattributes.kDS1AttrDistinguishedName,
-    dsattributes.kDS1AttrFirstName,
-    dsattributes.kDS1AttrGeneratedUID,
-    dsattributes.kDS1AttrLastName,
-    dsattributes.kDS1AttrMiddleName,
-    dsattributes.kDS1AttrModificationTimestamp,
-    dsattributes.kDS1AttrNote,
-    dsattributes.kDS1AttrSearchPath,
-    dsattributes.kDS1AttrUserCertificate,
-    dsattributes.kDS1AttrUserPKCS12Data,
-    dsattributes.kDS1AttrUserSMIMECertificate,
-    dsattributes.kDS1AttrWeblogURI,
-]
-
-MATCHANY = 1
-DIGEST_MD5 = &quot;dsAuthMethodStandard:dsAuthNodeDIGEST-MD5&quot;
-
-class Directory(object):
-    &quot;&quot;&quot; Encapsulates OpenDirectory session and node &quot;&quot;&quot;
-
-    def __init__(self, session, node, nodeName):
-        self.session = session
-        self.node = node
-        self.nodeName = nodeName
-
-    def __str__(self):
-        return &quot;OpenDirectory node: %s&quot; % (self.nodeName)
-
-
-
-def adjustMatchType(matchType, caseInsensitive):
-    &quot;&quot;&quot; Return the case-insensitive equivalent matchType &quot;&quot;&quot;
-    return (matchType | 0x100) if caseInsensitive else matchType
-
-    # return caseInsensitiveEquivalents[matchType] if caseInsensitive else matchType
-
-
-def recordToResult(record, encodings):
-    &quot;&quot;&quot;
-    Takes an ODRecord and turns it into a (recordName, attributesDictionary)
-    tuple.  Unicode values are converted to utf-8 encoded strings. (Not sure
-    what to do with non-unicode values)
-
-    encodings is a attribute-name-to-encoding mapping, useful for specifying
-    how to decode values.
-    &quot;&quot;&quot;
-    details, error = record.recordDetailsForAttributes_error_(None, None)
-    if error:
-        log.error(&quot;Error: {err}&quot;, err=error)
-        raise ODNSError(error)
-    result = {}
-    for key, value in details.iteritems():
-        encoding = encodings.get(key, None)
-        if key in SINGLE_VALUE_ATTRIBUTES:
-            if encoding:
-                if encoding == &quot;base64&quot;:
-                    result[key] = base64.b64encode(value.bytes().tobytes())
-            else:
-                if len(value) == 0:
-                    result[key] = None
-                else:
-                    if isinstance(value[0], objc.pyobjc_unicode):
-                        result[key] = unicode(value[0]).encode(&quot;utf-8&quot;) # convert from pyobjc
-        else:
-            if encoding:
-                if encoding == &quot;base64&quot;:
-                    result[key] = [base64.b64encode(v.bytes().tobytes()) for v in value]
-            else:
-                result[key] = [unicode(v).encode(&quot;utf-8&quot;) for v in value if isinstance(v, objc.pyobjc_unicode)]
-
-    return (details.get(dsattributes.kDSNAttrRecordName, [None])[0], result)
-
-
-def attributeNamesFromList(attributes):
-    &quot;&quot;&quot;
-    The attributes list can contain string names or tuples of the form (name,
-    encoding).  Return just the names.
-    &quot;&quot;&quot;
-
-    if attributes is None:
-        attributes = []
-
-    names = []
-    encodings = {}
-    for attribute in attributes:
-        if isinstance(attribute, tuple):
-            names.append(attribute[0])
-            encodings[attribute[0]] = attribute[1]
-        else:
-            names.append(attribute)
-    return names, encodings
-
-
-@autoPooled
-def odInit(nodeName):
-    &quot;&quot;&quot;
-    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.
-    &quot;&quot;&quot;
-    session = odframework.ODSession.defaultSession()
-
-    tries = NUM_TRIES
-    while tries:
-        node, error = odframework.ODNode.nodeWithSession_name_error_(session,
-            nodeName, None)
-
-        if not error:
-            return Directory(session, node, nodeName)
-
-        code = error.code()
-        log.debug(&quot;Received code {code} from node call: {err}&quot;, code=code, err=error)
-
-        if code in RETRY_CODES:
-            tries -= 1
-        else:
-            break
-
-    log.error(&quot;Error: {err}&quot;, err=error)
-    raise ODNSError(error)
-
-
-
-@autoPooled
-def getNodeAttributes(directory, nodeName, attributes):
-    &quot;&quot;&quot;
-    Return key attributes for the specified directory node. 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 &quot;str&quot; or &quot;base64&quot;.
-
-    @param directory: C{Directory} the object obtained from an odInit call.
-    @param nodeName: C{str} containing the OD nodeName to query.
-    @param attributes: C{list} or C{tuple} containing the attributes to return for each record.
-    @return: C{dict} of attributes found.
-    &quot;&quot;&quot;
-
-    tries = NUM_TRIES
-    while tries:
-
-        details, error = directory.node.nodeDetailsForKeys_error_(attributes, None)
-        if not error:
-            return details
-
-        code = error.code()
-        log.debug(&quot;Received code {code} from node details call: {err}&quot;, code=code, err=error)
-
-        if code in RETRY_CODES:
-            tries -= 1
-        else:
-            break
-
-    log.error(&quot;Error: {err}&quot;, err=error)
-    raise ODNSError(error)
-
-
-@autoPooled
-def listAllRecordsWithAttributes_list(directory, recordType, attributes, count=0):
-    &quot;&quot;&quot;
-    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 &quot;str&quot; or &quot;base64&quot;.
-
-    @param directory: C{Directory} 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.
-    @param count: C{int} maximum number of records to return (zero returns all).
-    @return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
-        for each record found, or C{None} otherwise.
-    &quot;&quot;&quot;
-    results = []
-    attributeNames, encodings = attributeNamesFromList(attributes)
-
-    tries = NUM_TRIES
-    while tries:
-        query, error = odframework.ODQuery.queryWithNode_forRecordTypes_attribute_matchType_queryValues_returnAttributes_maximumResults_error_(
-            directory.node,
-            recordType,
-            None,
-            MATCHANY,
-            None,
-            attributeNames,
-            count,
-            None)
-
-        if not error:
-            records, error = query.resultsAllowingPartial_error_(False, None)
-
-        if not error:
-            for record in records:
-                results.append(recordToResult(record, encodings))
-            return results
-
-        code = error.code()
-        log.debug(&quot;Received code {code} from query call: {err}&quot;, code=code, err=error)
-
-        if code in RETRY_CODES:
-            tries -= 1
-        else:
-            break
-
-    log.error(&quot;Error: {err}&quot;, err=error)
-    raise ODNSError(error)
-
-
-@autoPooled
-def queryRecordsWithAttribute_list(directory, attr, value, matchType, casei, recordType, attributes, count=0):
-    &quot;&quot;&quot;
-    List records in Open Directory matching specified attribute/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 &quot;str&quot; or &quot;base64&quot;.
-
-    @param directory: C{Directory} the object obtained from an odInit call.
-    @param attr: C{str} containing the attribute to search.
-    @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-insensitive 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.
-    @param count: C{int} maximum number of records to return (zero returns all).
-    @return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
-        for each record found, or C{None} otherwise.
-    &quot;&quot;&quot;
-    results = []
-    attributeNames, encodings = attributeNamesFromList(attributes)
-
-    tries = NUM_TRIES
-    while tries:
-
-        query, error = odframework.ODQuery.queryWithNode_forRecordTypes_attribute_matchType_queryValues_returnAttributes_maximumResults_error_(
-            directory.node,
-            recordType,
-            attr,
-            adjustMatchType(matchType, casei),
-            value.decode(&quot;utf-8&quot;),
-            attributeNames,
-            count,
-            None)
-
-        if not error:
-            records, error = query.resultsAllowingPartial_error_(False, None)
-
-        if not error:
-            for record in records:
-                results.append(recordToResult(record, encodings))
-            return results
-
-        code = error.code()
-        log.debug(&quot;Received code {code} from query call: {err}&quot;, code=code, err=error)
-
-        if code in RETRY_CODES:
-            tries -= 1
-        else:
-            break
-
-    log.error(&quot;Error: {err}&quot;, err=error)
-    raise ODNSError(error)
-
-
-@autoPooled
-def queryRecordsWithAttributes_list(directory, compound, casei, recordType, attributes, count=0):
-    &quot;&quot;&quot;
-    List records in Open Directory matching specified criteria, 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 &quot;str&quot; or &quot;base64&quot;.
-
-    @param directory: C{Directory} 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-insensitive 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.
-    @param count: C{int} maximum number of records to return (zero returns all).
-    @return: C{list} containing a C{list} of C{str} (record name) and C{dict} attributes
-        for each record found, or C{None} otherwise.
-    &quot;&quot;&quot;
-    results = []
-
-    attributeNames, encodings = attributeNamesFromList(attributes)
-
-    tries = NUM_TRIES
-    while tries:
-
-        query, error = odframework.ODQuery.queryWithNode_forRecordTypes_attribute_matchType_queryValues_returnAttributes_maximumResults_error_(
-            directory.node,
-            recordType,
-            None,
-            0x210B, # adjustMatchType(matchType, casei),
-            compound.decode(&quot;utf-8&quot;),
-            attributeNames,
-            count,
-            None)
-
-        if not error:
-            records, error = query.resultsAllowingPartial_error_(False, None)
-
-        if not error:
-            for record in records:
-                results.append(recordToResult(record, encodings))
-            return results
-
-        code = error.code()
-        log.debug(&quot;Received code {code} from query call: {err}&quot;, code=code, err=error)
-
-        if code in RETRY_CODES:
-            tries -= 1
-        else:
-            break
-
-    log.error(&quot;Error: {err}&quot;, err=error)
-    raise ODNSError(error)
-
-
-def getUserRecord(directory, user):
-    &quot;&quot;&quot;
-    Look up the record for the given user within the directory's node
-
-    @param directory: C{Directory} the object obtained from an odInit call.
-    @param user: C{str} the user identifier/directory record name to fetch.
-    @return: OD record if the user was found, None otherwise.
-    &quot;&quot;&quot;
-    tries = NUM_TRIES
-    while tries:
-
-        record, error = directory.node.recordWithRecordType_name_attributes_error_(
-            dsattributes.kDSStdRecordTypeUsers,
-            user,
-            None,
-            None
-        )
-        if not error:
-            return record
-
-        code = error.code()
-        log.debug(&quot;Received code {code} from recordWithRecordType call: {err}&quot;, code=code, err=error)
-
-        if code in RETRY_CODES:
-            tries -= 1
-        else:
-            break
-
-    log.error(&quot;Error: {err}&quot;, err=error)
-    raise ODNSError(error)
-
-
-@autoPooled
-def authenticateUserBasic(directory, nodeName, user, password):
-    &quot;&quot;&quot;
-    Authenticate a user with a password to Open Directory.
-
-    @param directory: C{Directory} the object obtained from an odInit call.
-    @param nodeName: C{str} the directory nodeName for the record to check.
-    @param user: C{str} the user identifier/directory record name to check.
-    @param pswd: C{str} containing the password to check.
-    @return: C{True} if the user was found, C{False} otherwise.
-    &quot;&quot;&quot;
-    record = getUserRecord(directory, user)
-    if record is None:
-        raise ODError(&quot;Record not found&quot;, 0)
-
-    tries = NUM_TRIES
-    while tries:
-
-        log.debug(&quot;Checking basic auth for user '{user}' (tries remaining: {tries})&quot;, 
-            user=user, tries=tries)
-
-        result, error = record.verifyPassword_error_(password, None)
-        if not error:
-            log.debug(&quot;Basic auth for user '{user}' result: {result}&quot;, user=user, result=result)
-            return result
-
-        code = error.code()
-
-        if code == INCORRECT_CREDENTIALS:
-            log.debug(&quot;Basic auth for user '{user}' failed due to incorrect credentials&quot;, user=user)
-            return False
-
-        log.debug(&quot;Basic auth for user '{user}' failed with code {code} ({err})&quot;,
-            user=user, code=code, err=error)
-
-        if code in RETRY_CODES:
-            tries -= 1
-        else:
-            break
-
-    log.error(&quot;Basic auth error: {err}&quot;, err=error)
-    raise ODNSError(error)
-
-
-@autoPooled
-def authenticateUserDigest(directory, nodeName, user, challenge, response, method):
-    &quot;&quot;&quot;
-    Authenticate using HTTP Digest credentials to Open Directory.
-
-    @param directory: C{Directory} the object obtained from an odInit call.
-    @param nodeName: C{str} the directory nodeName for the record to check.
-    @param user: C{str} the user identifier/directory record name to check.
-    @param challenge: C{str} the HTTP challenge sent to the client.
-    @param response: C{str} the HTTP response sent from the client.
-    @param method: C{str} the HTTP method being used.
-    @return: C{True} if the user was found, C{False} otherwise.
-    &quot;&quot;&quot;
-    record = getUserRecord(directory, user)
-    if record is None:
-        raise ODError(&quot;Record not found&quot;, 0)
-
-    tries = NUM_TRIES
-    while tries:
-
-        log.debug(&quot;Checking digest auth for user '{user}' (tries remaining: {tries})&quot;,
-            user=user, tries=tries)
-
-        # TODO: what are these other return values?
-        result, mystery1, mystery2, error = record.verifyExtendedWithAuthenticationType_authenticationItems_continueItems_context_error_(
-            DIGEST_MD5,
-            [user, challenge, response, method],
-            None, None, None
-        )
-        if not error:
-            log.debug(&quot;Digest auth for user '{user}' result: {result}&quot;, user=user, result=result)
-            return result
-
-        code = error.code()
-
-        if code == INCORRECT_CREDENTIALS:
-            log.debug(&quot;Digest auth for user '{user}' failed due to incorrect credentials&quot;, user=user)
-            return False
-
-        log.debug(&quot;Digest auth for user '{user}' failed with code {code} ({err})&quot;,
-            user=user, code=code, err=error)
-
-        if code in RETRY_CODES:
-            tries -= 1
-        else:
-            break
-
-    log.error(&quot;Digest auth error: {err}&quot;, err=error)
-    raise ODNSError(error)
-
-
-class ODError(Exception):
-    &quot;&quot;&quot;
-    Exceptions from DirectoryServices errors.
-    &quot;&quot;&quot;
-    def __init__(self, msg, code):
-        self.message = (msg, code)
-
-    def __str__(self):
-        return &quot;&lt;OD Error %s %d&gt;&quot; % (self.message[0], self.message[1])
-
-
-class ODNSError(ODError):
-    &quot;&quot;&quot;
-    Converts an NSError.
-    &quot;&quot;&quot;
-    def __init__(self, error):
-        super(ODNSError, self).__init__(error.localizedDescription(),
-            error.code())
</del></span></pre></div>
<a id="twexttrunktwextwhoopendirectorysetup_directorypy"></a>
<div class="delfile"><h4>Deleted: twext/trunk/twext/who/opendirectory/setup_directory.py (12126 => 12127)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/who/opendirectory/setup_directory.py        2013-12-18 00:50:59 UTC (rev 12126)
+++ twext/trunk/twext/who/opendirectory/setup_directory.py        2013-12-18 18:29:24 UTC (rev 12127)
</span><span class="lines">@@ -1,381 +0,0 @@
</span><del>-##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-from __future__ import print_function
-
-import os
-import sys
-import odframework
-import dsattributes
-from getopt import getopt, GetoptError
-
-# TODO: Nested groups
-# TODO: GroupMembership
-
-masterNodeName = &quot;/LDAPv3/127.0.0.1&quot;
-localNodeName = &quot;/Local/Default&quot;
-
-saclGroupNodeName = &quot;/Local/Default&quot;
-saclGroupNames = (&quot;com.apple.access_calendar&quot;, &quot;com.apple.access_addressbook&quot;)
-
-masterUsers = [
-    (
-        &quot;odtestamanda&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;Amanda&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;Amanda Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;amanda@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33300&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestbetty&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;Betty&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;Betty Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;betty@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;9DC04A71-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33301&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestcarlene&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;Carlene&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;Carlene Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;carlene@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;9DC04A72-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33302&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestdenise&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;Denise&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;Denise Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;denise@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;9DC04A73-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33303&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestunicode&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;Unicode &quot; + unichr(208)],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;Unicode Test &quot; + unichr(208)],
-            dsattributes.kDSNAttrEMailAddress : [&quot;unicodetest@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;CA795296-D77A-4E09-A72F-869920A3D284&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33304&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestat@sign&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;AtSign&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;At Sign Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;attsign@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;71646A3A-1CEF-4744-AB1D-0AC855E25DC8&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33305&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestsatou&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;\xe4\xbd\x90\xe8\x97\xa4\xe4\xbd\x90\xe8\x97\xa4\xe4\xbd\x90\xe8\x97\xa4&quot;.decode(&quot;utf-8&quot;)],
-            dsattributes.kDS1AttrLastName  : [&quot;Test \xe4\xbd\x90\xe8\x97\xa4&quot;.decode(&quot;utf-8&quot;)],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;\xe4\xbd\x90\xe8\x97\xa4\xe4\xbd\x90\xe8\x97\xa4\xe4\xbd\x90\xe8\x97\xa4 Test \xe4\xbd\x90\xe8\x97\xa4&quot;.decode(&quot;utf-8&quot;)],
-            dsattributes.kDSNAttrEMailAddress : [&quot;satou@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;C662F833-75AD-4589-9879-5FF102943CEF&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33306&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-]
-
-masterGroups = [
-    (
-        &quot;odtestsubgroupb&quot;,
-        {
-            dsattributes.kDS1AttrGeneratedUID : [&quot;6C6CD282-E6E3-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;OD Test Subgroup B&quot;],
-            dsattributes.kDSNAttrGroupMembers : [&quot;9DC04A72-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;33401&quot;],
-        },
-    ),
-    (
-        &quot;odtestgrouptop&quot;,
-        {
-            dsattributes.kDS1AttrGeneratedUID : [&quot;6C6CD280-E6E3-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;OD Test Group Top&quot;],
-            dsattributes.kDSNAttrGroupMembers : [&quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;, &quot;9DC04A71-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDSNAttrNestedGroups : [&quot;6C6CD282-E6E3-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;33400&quot;],
-        },
-    ),
-]
-
-localUsers = [
-    (
-        &quot;odtestalbert&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;Albert&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;Albert Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;albert@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;9DC04A74-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33350&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestbill&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;Bill&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;Bill Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;bill@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;9DC04A75-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33351&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestcarl&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;Carl&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;Carl Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;carl@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;9DC04A76-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33352&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-    (
-        &quot;odtestdavid&quot;,
-        {
-            dsattributes.kDS1AttrFirstName : [&quot;David&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;Test&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;David Test&quot;],
-            dsattributes.kDSNAttrEMailAddress : [&quot;david@example.com&quot;],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;9DC04A77-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrUniqueID : [&quot;33353&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;20&quot;],
-        },
-    ),
-]
-
-localGroups = [
-    (
-        &quot;odtestsubgroupa&quot;,
-        {
-            dsattributes.kDS1AttrGeneratedUID : [&quot;6C6CD281-E6E3-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;OD Test Subgroup A&quot;],
-            dsattributes.kDSNAttrGroupMembers : [&quot;9DC04A74-E6DD-11DF-9492-0800200C9A66&quot;, &quot;9DC04A75-E6DD-11DF-9492-0800200C9A66&quot;],
-            dsattributes.kDS1AttrPrimaryGroupID : [&quot;33402&quot;],
-        },
-    ),
-]
-
-
-def usage(e=None):
-    name = os.path.basename(sys.argv[0])
-    print(&quot;usage: %s [options] local_user local_password odmaster_user odmaster_password&quot; % (name,))
-    print(&quot;&quot;)
-    print(&quot; Configures local and OD master directories for testing&quot;)
-    print(&quot;&quot;)
-    print(&quot;options:&quot;)
-    print(&quot; -h --help: print this help and exit&quot;)
-    if e:
-        sys.exit(1)
-    else:
-        sys.exit(0)
-
-
-def lookupRecordName(node, recordType, name):
-    query, error = odframework.ODQuery.queryWithNode_forRecordTypes_attribute_matchType_queryValues_returnAttributes_maximumResults_error_(
-        node,
-        recordType,
-        dsattributes.kDSNAttrRecordName,
-        dsattributes.eDSExact,
-        name,
-        None,
-        0,
-        None)
-    if error:
-        raise ODError(error)
-    records, error = query.resultsAllowingPartial_error_(False, None)
-    if error:
-        raise ODError(error)
-
-    if len(records) &lt; 1:
-        return None
-    if len(records) &gt; 1:
-        raise ODError(&quot;Multiple records for '%s' were found&quot; % (name,))
-
-    return records[0]
-
-def createRecord(node, recordType, recordName, attrs):
-    record, error = node.createRecordWithRecordType_name_attributes_error_(
-        recordType,
-        recordName,
-        attrs,
-        None)
-    if error:
-        print(error)
-        raise ODError(error)
-    return record
-
-def main():
-
-    try:
-        (optargs, args) = getopt(sys.argv[1:], &quot;h&quot;, [&quot;help&quot;])
-    except GetoptError, e:
-        usage(e)
-
-    for opt, arg in optargs:
-        if opt in (&quot;-h&quot;, &quot;--help&quot;):
-            usage()
-
-    if len(args) != 4:
-        usage()
-
-    localUser, localPassword, masterUser, masterPassword = args
-
-    userInfo = {
-        masterNodeName : {
-            &quot;user&quot; : masterUser,
-            &quot;password&quot; : masterPassword,
-            &quot;users&quot; : masterUsers,
-            &quot;groups&quot; : masterGroups,
-        },
-        localNodeName : {
-            &quot;user&quot; : localUser,
-            &quot;password&quot; : localPassword,
-            &quot;users&quot; : localUsers,
-            &quot;groups&quot; : localGroups,
-        },
-    }
-
-
-
-    session = odframework.ODSession.defaultSession()
-    userRecords = []
-
-    for nodeName, info in userInfo.iteritems():
-
-        userName = info[&quot;user&quot;]
-        password = info[&quot;password&quot;]
-        users = info[&quot;users&quot;]
-        groups = info[&quot;groups&quot;]
-
-        node, error = odframework.ODNode.nodeWithSession_name_error_(session, nodeName, None)
-        if error:
-            print(error)
-            raise ODError(error)
-
-        result, error = node.setCredentialsWithRecordType_recordName_password_error_(
-            dsattributes.kDSStdRecordTypeUsers,
-            userName,
-            password,
-            None
-        )
-        if error:
-            print(&quot;Unable to authenticate with directory %s: %s&quot; % (nodeName, error))
-            raise ODError(error)
-
-        print(&quot;Successfully authenticated with directory %s&quot; % (nodeName,))
-
-        print(&quot;Creating users within %s:&quot; % (nodeName,))
-        for recordName, attrs in users:
-            record = lookupRecordName(node, dsattributes.kDSStdRecordTypeUsers, recordName)
-            if record is None:
-                print(&quot;Creating user %s&quot; % (recordName,))
-                try:
-                    record = createRecord(node, dsattributes.kDSStdRecordTypeUsers, recordName, attrs)
-                    print(&quot;Successfully created user %s&quot; % (recordName,))
-                    result, error = record.changePassword_toPassword_error_(
-                        None, &quot;password&quot;, None)
-                    if error or not result:
-                        print(&quot;Failed to set password for %s: %s&quot; % (recordName, error))
-                    else:
-                        print(&quot;Successfully set password for %s&quot; % (recordName,))
-                except ODError, e:
-                    print(&quot;Failed to create user %s: %s&quot; % (recordName, e))
-            else:
-                print(&quot;User %s already exists&quot; % (recordName,))
-
-            if record is not None:
-                userRecords.append(record)
-
-        print(&quot;Creating groups within %s:&quot; % (nodeName,))
-        for recordName, attrs in groups:
-            record = lookupRecordName(node, dsattributes.kDSStdRecordTypeGroups, recordName)
-            if record is None:
-                print(&quot;Creating group %s&quot; % (recordName,))
-                try:
-                    record = createRecord(node, dsattributes.kDSStdRecordTypeGroups, recordName, attrs)
-                    print(&quot;Successfully created group %s&quot; % (recordName,))
-                except ODError, e:
-                    print(&quot;Failed to create group %s: %s&quot; % (recordName, e))
-            else:
-                print(&quot;Group %s already exists&quot; % (recordName,))
-
-        print
-
-    # Populate SACL groups
-    node, error = odframework.ODNode.nodeWithSession_name_error_(session, saclGroupNodeName, None)
-    result, error = node.setCredentialsWithRecordType_recordName_password_error_(
-        dsattributes.kDSStdRecordTypeUsers,
-        userInfo[saclGroupNodeName][&quot;user&quot;],
-        userInfo[saclGroupNodeName][&quot;password&quot;],
-        None
-    )
-    if not error:
-        for saclGroupName in saclGroupNames:
-            saclGroupRecord = lookupRecordName(node, dsattributes.kDSStdRecordTypeGroups, saclGroupName)
-            if saclGroupRecord:
-                print(&quot;Populating %s SACL group:&quot; % (saclGroupName,))
-                for userRecord in userRecords:
-                    details, error = userRecord.recordDetailsForAttributes_error_(None, None)
-                    recordName = details.get(dsattributes.kDSNAttrRecordName, [None])[0]
-                    result, error = saclGroupRecord.isMemberRecord_error_(userRecord, None)
-                    if result:
-                        print(&quot;%s is already in the %s SACL group&quot; % (recordName, saclGroupName))
-                    else:
-                        result, error = saclGroupRecord.addMemberRecord_error_(userRecord, None)
-                        print(&quot;Adding %s to the %s SACL group&quot; % (recordName, saclGroupName))
-
-            print(&quot;&quot;)
-
-class ODError(Exception):
-    def __init__(self, error):
-        self.message = (str(error), error.code())
-
-if __name__ == &quot;__main__&quot;:
-    main()
</del></span></pre></div>
<a id="twexttrunktwextwhoopendirectorysetup_testuserspy"></a>
<div class="delfile"><h4>Deleted: twext/trunk/twext/who/opendirectory/setup_testusers.py (12126 => 12127)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/who/opendirectory/setup_testusers.py        2013-12-18 00:50:59 UTC (rev 12126)
+++ twext/trunk/twext/who/opendirectory/setup_testusers.py        2013-12-18 18:29:24 UTC (rev 12127)
</span><span class="lines">@@ -1,145 +0,0 @@
</span><del>-##
-# Copyright (c) 2012-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-from __future__ import print_function
-
-import os
-import sys
-import odframework
-import dsattributes
-from getopt import getopt, GetoptError
-
-
-def usage(e=None):
-    name = os.path.basename(sys.argv[0])
-    print(&quot;usage: %s [options] local_user local_password&quot; % (name,))
-    print(&quot;&quot;)
-    print(&quot; Configures local directory for test users&quot;)
-    print(&quot;&quot;)
-    print(&quot;options:&quot;)
-    print(&quot; -h --help: print this help and exit&quot;)
-    if e:
-        sys.exit(1)
-    else:
-        sys.exit(0)
-
-
-def lookupRecordName(node, recordType, name):
-    query, error = odframework.ODQuery.queryWithNode_forRecordTypes_attribute_matchType_queryValues_returnAttributes_maximumResults_error_(
-        node,
-        recordType,
-        dsattributes.kDSNAttrRecordName,
-        dsattributes.eDSExact,
-        name,
-        None,
-        0,
-        None)
-    if error:
-        raise ODError(error)
-    records, error = query.resultsAllowingPartial_error_(False, None)
-    if error:
-        raise ODError(error)
-
-    if len(records) &lt; 1:
-        return None
-    if len(records) &gt; 1:
-        raise ODError(&quot;Multiple records for '%s' were found&quot; % (name,))
-
-    return records[0]
-
-def createRecord(node, recordType, recordName, attrs):
-    record, error = node.createRecordWithRecordType_name_attributes_error_(
-        recordType,
-        recordName,
-        attrs,
-        None)
-    if error:
-        print(error)
-        raise ODError(error)
-    return record
-
-def main():
-
-    try:
-        (optargs, args) = getopt(sys.argv[1:], &quot;h&quot;, [&quot;help&quot;])
-    except GetoptError, e:
-        usage(e)
-
-    for opt, arg in optargs:
-        if opt in (&quot;-h&quot;, &quot;--help&quot;):
-            usage()
-
-    if len(args) != 2:
-        usage()
-
-    localUser, localPassword = args
-
-    session = odframework.ODSession.defaultSession()
-
-    nodeName = &quot;/Local/Default&quot;
-    node, error = odframework.ODNode.nodeWithSession_name_error_(session, nodeName, None)
-    if error:
-        print(error)
-        raise ODError(error)
-
-    result, error = node.setCredentialsWithRecordType_recordName_password_error_(
-        dsattributes.kDSStdRecordTypeUsers,
-        localUser,
-        localPassword,
-        None
-    )
-    if error:
-        print(&quot;Unable to authenticate with directory %s: %s&quot; % (nodeName, error))
-        raise ODError(error)
-
-    print(&quot;Successfully authenticated with directory %s&quot; % (nodeName,))
-
-    print(&quot;Creating users within %s:&quot; % (nodeName,))
-    for i in xrange(99):
-        j = i+1
-        recordName = &quot;user%02d&quot; % (j,)
-        password = &quot;user%02d&quot; % (j,)
-        attrs = {
-            dsattributes.kDS1AttrFirstName : [&quot;User&quot;],
-            dsattributes.kDS1AttrLastName  : [&quot;%02d&quot; % (j,)],
-            dsattributes.kDS1AttrDistinguishedName : [&quot;User %02d&quot; % (j,)],
-            dsattributes.kDSNAttrEMailAddress : [&quot;user%02d@example.com&quot; % (j,)],
-            dsattributes.kDS1AttrGeneratedUID : [&quot;user%02d&quot; % (j,)],
-        }
-
-        record = lookupRecordName(node, dsattributes.kDSStdRecordTypeUsers, recordName)
-        if record is None:
-            print(&quot;Creating user %s&quot; % (recordName,))
-            try:
-                record = createRecord(node, dsattributes.kDSStdRecordTypeUsers, recordName, attrs)
-                print(&quot;Successfully created user %s&quot; % (recordName,))
-                result, error = record.changePassword_toPassword_error_(
-                    None, password, None)
-                if error or not result:
-                    print(&quot;Failed to set password for %s: %s&quot; % (recordName, error))
-                else:
-                    print(&quot;Successfully set password for %s&quot; % (recordName,))
-            except ODError, e:
-                print(&quot;Failed to create user %s: %s&quot; % (recordName, e))
-        else:
-            print(&quot;User %s already exists&quot; % (recordName,))
-
-
-class ODError(Exception):
-    def __init__(self, error):
-        self.message = (str(error), error.code())
-
-if __name__ == &quot;__main__&quot;:
-    main()
</del></span></pre></div>
<a id="twexttrunktwextwhoopendirectorytesttest_opendirectorypy"></a>
<div class="delfile"><h4>Deleted: twext/trunk/twext/who/opendirectory/test/test_opendirectory.py (12126 => 12127)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/who/opendirectory/test/test_opendirectory.py        2013-12-18 00:50:59 UTC (rev 12126)
+++ twext/trunk/twext/who/opendirectory/test/test_opendirectory.py        2013-12-18 18:29:24 UTC (rev 12127)
</span><span class="lines">@@ -1,940 +0,0 @@
</span><del>-##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-from __future__ import print_function
-
-from twistedcaldav.test.util import TestCase
-import hashlib
-import random
-import sys
-
-runTests = False
-
-try:
-    from calendarserver.platform.darwin.od import opendirectory, dsattributes, dsquery, setup_directory
-
-    directory = opendirectory.odInit(&quot;/Search&quot;)
-
-    results = opendirectory.queryRecordsWithAttribute_list(
-        directory,
-        dsattributes.kDS1AttrGeneratedUID,
-        &quot;9DC04A74-E6DD-11DF-9492-0800200C9A66&quot;,
-        dsattributes.eDSExact,
-        False,
-        dsattributes.kDSStdRecordTypeUsers,
-        None,
-        count=0
-    )
-    recordNames = [x[0] for x in results]
-    # Local user:
-    if &quot;odtestalbert&quot; in recordNames:
-        runTests = True
-    else:
-        print(&quot;Please run setup_directory.py to populate OD&quot;)
-
-except ImportError:
-    print(&quot;Unable to import OpenDirectory framework&quot;)
-
-
-def generateNonce():
-    c = tuple([random.randrange(sys.maxint) for _ in range(3)])
-    c = '%d%d%d' % c
-    return c
-
-def getChallengeResponse(user, password, node, uri, method):
-    nonce = generateNonce()
-
-    ha1 = hashlib.md5(&quot;%s:%s:%s&quot; % (user, node, password)).hexdigest()
-    ha2 = hashlib.md5(&quot;%s:%s&quot; % (method, uri)).hexdigest()
-    response = hashlib.md5(&quot;%s:%s:%s&quot;% (ha1, nonce, ha2)).hexdigest()
-
-    fields = {
-        'username': user,
-        'nonce': nonce,
-        'realm': node,
-        'algorithm': 'md5',
-        'uri': uri,
-        'response': response,
-    }
-
-    challenge = 'Digest realm=&quot;%(realm)s&quot;, nonce=&quot;%(nonce)s&quot;, algorithm=%(algorithm)s' % fields
-
-    response = (
-        'Digest username=&quot;%(username)s&quot;, '
-        'realm=&quot;%(realm)s&quot;, '
-        'nonce=&quot;%(nonce)s&quot;, '
-        'uri=&quot;%(uri)s&quot;, '
-        'response=&quot;%(response)s&quot;,'
-        'algorithm=%(algorithm)s'
-    ) % fields
-
-    return challenge, response
-
-if runTests:
-
-    USER_ATTRIBUTES = [
-        dsattributes.kDS1AttrGeneratedUID,
-        dsattributes.kDSNAttrRecordName,
-        dsattributes.kDSNAttrAltSecurityIdentities,
-        dsattributes.kDSNAttrRecordType,
-        dsattributes.kDS1AttrDistinguishedName,
-        dsattributes.kDS1AttrFirstName,
-        dsattributes.kDS1AttrLastName,
-        dsattributes.kDSNAttrEMailAddress,
-        dsattributes.kDSNAttrMetaNodeLocation,
-        (dsattributes.kDSNAttrJPEGPhoto, &quot;base64&quot;),
-    ]
-
-    class OpenDirectoryTests(TestCase):
-
-        def test_odInit(self):
-
-            # Bogus node name
-            self.assertRaises(opendirectory.ODError, opendirectory.odInit, &quot;/Foo&quot;)
-
-            # Valid node name
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-            self.assertTrue(isinstance(directory, opendirectory.Directory))
-
-        def test_adjustMatchType(self):
-            self.assertEquals(
-                opendirectory.adjustMatchType(dsattributes.eDSExact, False),
-                dsattributes.eDSExact
-            )
-            self.assertEquals(
-                opendirectory.adjustMatchType(dsattributes.eDSExact, True),
-                dsattributes.eDSExact | 0x100
-            )
-
-        def test_getNodeAttributes(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-            results = opendirectory.getNodeAttributes(directory, &quot;/Search&quot;, [dsattributes.kDS1AttrSearchPath])
-            self.assertTrue(&quot;/Local/Default&quot; in results[dsattributes.kDS1AttrSearchPath])
-            self.assertTrue(&quot;/LDAPv3/127.0.0.1&quot; in results[dsattributes.kDS1AttrSearchPath])
-
-        def test_listAllRecordsWithAttributes_list_master(self):
-
-            directory = opendirectory.odInit(&quot;/LDAPv3/127.0.0.1&quot;)
-            results = opendirectory.listAllRecordsWithAttributes_list(
-                directory,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            for recordName, info in setup_directory.masterUsers:
-                self.assertTrue(recordName in recordNames)
-
-        def test_listAllRecordsWithAttributes_list_local(self):
-
-            directory = opendirectory.odInit(&quot;/Local/Default&quot;)
-            results = opendirectory.listAllRecordsWithAttributes_list(
-                directory,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            for recordName, info in setup_directory.localUsers:
-                self.assertTrue(recordName in recordNames)
-
-
-        def test_queryRecordsWithAttribute_list_firstname_exact_insensitive_match(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrFirstName,
-                &quot;betty&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestbetty&quot; in recordNames)
-
-        def test_queryRecordsWithAttribute_list_firstname_exact_insensitive_match_multitype(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrFirstName,
-                &quot;betty&quot;,
-                dsattributes.eDSExact,
-                False,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestbetty&quot; in recordNames)
-
-        def test_queryRecordsWithAttribute_list_firstname_begins_insensitive_match(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrFirstName,
-                &quot;Amand&quot;,
-                dsattributes.eDSStartsWith,
-                True,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-        def test_queryRecordsWithAttribute_list_firstname_begins_insensitive_match_multitype(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrFirstName,
-                &quot;Amand&quot;,
-                dsattributes.eDSStartsWith,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-        def test_queryRecordsWithAttribute_list_firstname_contains_insensitive_match(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrFirstName,
-                &quot;mand&quot;,
-                dsattributes.eDSContains,
-                True,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-        def test_queryRecordsWithAttribute_list_firstname_contains_insensitive_match_multitype(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrFirstName,
-                &quot;mand&quot;,
-                dsattributes.eDSContains,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-        def test_queryRecordsWithAttribute_list_lastname_exact_insensitive_match(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrLastName,
-                &quot;test&quot;,
-                dsattributes.eDSExact,
-                True,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            for recordName, info in setup_directory.masterUsers:
-                if info[dsattributes.kDS1AttrLastName] == &quot;Test&quot;:
-                    self.assertTrue(recordName in recordNames)
-            for recordName, info in setup_directory.localUsers:
-                if info[dsattributes.kDS1AttrLastName] == &quot;Test&quot;:
-                    self.assertTrue(recordName in recordNames)
-
-        def test_queryRecordsWithAttribute_list_lastname_exact_insensitive_match_multitype(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrLastName,
-                &quot;test&quot;,
-                dsattributes.eDSExact,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            for recordName, info in setup_directory.masterUsers:
-                if info[dsattributes.kDS1AttrLastName] == &quot;Test&quot;:
-                    self.assertTrue(recordName in recordNames)
-            for recordName, info in setup_directory.localUsers:
-                if info[dsattributes.kDS1AttrLastName] == &quot;Test&quot;:
-                    self.assertTrue(recordName in recordNames)
-
-        def test_queryRecordsWithAttribute_list_lastname_begins_insensitive_match(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrLastName,
-                &quot;tes&quot;,
-                dsattributes.eDSStartsWith,
-                True,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            for recordName, info in setup_directory.masterUsers:
-                self.assertTrue(recordName in recordNames)
-            for recordName, info in setup_directory.localUsers:
-                self.assertTrue(recordName in recordNames)
-
-        def test_queryRecordsWithAttribute_list_lastname_begins_insensitive_match_multitype(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrLastName,
-                &quot;tes&quot;,
-                dsattributes.eDSStartsWith,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            for recordName, info in setup_directory.masterUsers:
-                self.assertTrue(recordName in recordNames)
-            for recordName, info in setup_directory.localUsers:
-                self.assertTrue(recordName in recordNames)
-
-        def test_queryRecordsWithAttribute_list_lastname_contains_insensitive_match(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrLastName,
-                &quot;es&quot;,
-                dsattributes.eDSContains,
-                True,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            for recordName, info in setup_directory.masterUsers:
-                self.assertTrue(recordName in recordNames)
-            for recordName, info in setup_directory.localUsers:
-                self.assertTrue(recordName in recordNames)
-
-        def test_queryRecordsWithAttribute_list_lastname_contains_insensitive_match_multitype(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrLastName,
-                &quot;es&quot;,
-                dsattributes.eDSContains,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            for recordName, info in setup_directory.masterUsers:
-                self.assertTrue(recordName in recordNames)
-            for recordName, info in setup_directory.localUsers:
-                self.assertTrue(recordName in recordNames)
-
-        def test_queryRecordsWithAttribute_list_email_begins_insensitive_match(self):
-            # This test won't pass until this is fixed: &lt;rdar://problem/8608148&gt;
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDSNAttrEMailAddress,
-                &quot;aman&quot;,
-                dsattributes.eDSStartsWith,
-                True,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-
-        def test_queryRecordsWithAttribute_list_email_begins_insensitive_match_multitype(self):
-            # This test won't pass until this is fixed: &lt;rdar://problem/8608148&gt;
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDSNAttrEMailAddress,
-                &quot;aman&quot;,
-                dsattributes.eDSStartsWith,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-
-
-        def test_queryRecordsWithAttribute_list_guid_exact_sensitive_match_master(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrGeneratedUID,
-                &quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            # OD Master user:
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-        def test_queryRecordsWithAttribute_list_guid_exact_sensitive_match_multitype_master(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrGeneratedUID,
-                &quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;,
-                dsattributes.eDSExact,
-                False,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            # OD Master user:
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-
-        def test_queryRecordsWithAttribute_list_guid_exact_sensitive_match_local(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrGeneratedUID,
-                &quot;9DC04A74-E6DD-11DF-9492-0800200C9A66&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            # Local user:
-            self.assertTrue(&quot;odtestalbert&quot; in recordNames)
-
-
-        def test_queryRecordsWithAttribute_list_guid_exact_sensitive_match_multitype_local(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrGeneratedUID,
-                &quot;9DC04A74-E6DD-11DF-9492-0800200C9A66&quot;,
-                dsattributes.eDSExact,
-                False,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            # Local user:
-            self.assertTrue(&quot;odtestalbert&quot; in recordNames)
-
-
-
-        def test_queryRecordsWithAttribute_list_groupMembers_recordName_master(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDSNAttrRecordName,
-                &quot;odtestgrouptop&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeGroups,
-                [
-                    dsattributes.kDSNAttrGroupMembers,
-                    dsattributes.kDSNAttrNestedGroups,
-                ],
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestgrouptop&quot; in recordNames)
-            groupMembers = results[0][1][dsattributes.kDSNAttrGroupMembers]
-            self.assertEquals(
-                set(groupMembers),
-                set(setup_directory.masterGroups[1][1][dsattributes.kDSNAttrGroupMembers])
-            )
-
-        def test_queryRecordsWithAttribute_list_groupMembers_recordName_local(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDSNAttrRecordName,
-                &quot;odtestsubgroupa&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeGroups,
-                [
-                    dsattributes.kDSNAttrGroupMembers,
-                    dsattributes.kDSNAttrNestedGroups,
-                ],
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestsubgroupa&quot; in recordNames)
-            groupMembers = results[0][1][dsattributes.kDSNAttrGroupMembers]
-            self.assertEquals(
-                set(groupMembers),
-                set(setup_directory.localGroups[0][1][dsattributes.kDSNAttrGroupMembers])
-            )
-
-
-        def test_queryRecordsWithAttribute_list_groupMembers_guid_master(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrGeneratedUID,
-                &quot;6C6CD280-E6E3-11DF-9492-0800200C9A66&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeGroups,
-                [
-                    dsattributes.kDSNAttrGroupMembers,
-                    dsattributes.kDSNAttrNestedGroups,
-                ],
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestgrouptop&quot; in recordNames)
-            groupMembers = results[0][1][dsattributes.kDSNAttrGroupMembers]
-            self.assertEquals(
-                set(groupMembers),
-                set(setup_directory.masterGroups[1][1][dsattributes.kDSNAttrGroupMembers])
-            )
-
-        def test_queryRecordsWithAttribute_list_groupMembers_guid_local(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrGeneratedUID,
-                &quot;6C6CD281-E6E3-11DF-9492-0800200C9A66&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeGroups,
-                [
-                    dsattributes.kDSNAttrGroupMembers,
-                    dsattributes.kDSNAttrNestedGroups,
-                ],
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestsubgroupa&quot; in recordNames)
-            groupMembers = results[0][1][dsattributes.kDSNAttrGroupMembers]
-            self.assertEquals(
-                groupMembers,
-                setup_directory.localGroups[0][1][dsattributes.kDSNAttrGroupMembers]
-            )
-
-
-        def test_queryRecordsWithAttribute_list_groupsForGUID(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDSNAttrGroupMembers,
-                &quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeGroups,
-                [
-                    dsattributes.kDS1AttrGeneratedUID,
-                ],
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertTrue(&quot;odtestgrouptop&quot; in recordNames)
-
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDSNAttrNestedGroups,
-                &quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeGroups,
-                [
-                    dsattributes.kDS1AttrGeneratedUID,
-                ],
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            self.assertEquals([], recordNames)
-
-        def test_queryRecordsWithAttributes_list_master(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            expressions = [
-                dsquery.match(dsattributes.kDS1AttrDistinguishedName, &quot;aman&quot;, &quot;starts-with&quot;),
-                dsquery.match(dsattributes.kDS1AttrFirstName, &quot;amanda&quot;, &quot;equals&quot;),
-                dsquery.match(dsattributes.kDS1AttrLastName, &quot;es&quot;, &quot;contains&quot;),
-                dsquery.match(dsattributes.kDSNAttrEMailAddress, &quot;amanda@&quot;, &quot;starts-with&quot;),
-            ]
-
-            compound = dsquery.expression(dsquery.expression.OR, expressions).generate()
-
-            results = opendirectory.queryRecordsWithAttributes_list(
-                directory,
-                compound,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            # Master user:
-            self.assertTrue(&quot;odtestamanda&quot; in recordNames)
-
-        def test_queryRecordsWithAttributes_list_nonascii(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            expressions = [
-                dsquery.match(dsattributes.kDS1AttrFirstName, &quot;\xe4\xbd\x90&quot;, &quot;contains&quot;),
-                dsquery.match(dsattributes.kDS1AttrLastName, &quot;Test&quot;, &quot;contains&quot;),
-            ]
-
-            compound = dsquery.expression(dsquery.expression.AND, expressions).generate()
-
-            results = opendirectory.queryRecordsWithAttributes_list(
-                directory,
-                compound,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            # Master user:
-            self.assertTrue(&quot;odtestsatou&quot; in recordNames)
-
-
-        def test_queryRecordsWithAttributes_list_local(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            expressions = [
-                dsquery.match(dsattributes.kDS1AttrDistinguishedName, &quot;bil&quot;, &quot;starts-with&quot;),
-                dsquery.match(dsattributes.kDS1AttrFirstName, &quot;Bill&quot;, &quot;equals&quot;),
-                dsquery.match(dsattributes.kDS1AttrLastName, &quot;es&quot;, &quot;contains&quot;),
-                dsquery.match(dsattributes.kDSNAttrEMailAddress, &quot;bill@&quot;, &quot;starts-with&quot;),
-            ]
-
-            compound = dsquery.expression(dsquery.expression.OR, expressions).generate()
-
-            results = opendirectory.queryRecordsWithAttributes_list(
-                directory,
-                compound,
-                True,
-                [
-                    dsattributes.kDSStdRecordTypeUsers,
-                    dsattributes.kDSStdRecordTypeGroups,
-                    dsattributes.kDSStdRecordTypeResources,
-                    dsattributes.kDSStdRecordTypePlaces,
-                ],
-                USER_ATTRIBUTES,
-                count=0
-            )
-            recordNames = [x[0] for x in results]
-            # Local user:
-            self.assertTrue(&quot;odtestbill&quot; in recordNames)
-
-
-        def test_getUserRecord_existing(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-            record = opendirectory.getUserRecord(directory, &quot;odtestbill&quot;)
-            self.assertNotEquals(record, None)
-
-        def test_getUserRecord_missing(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-            record = opendirectory.getUserRecord(directory, &quot;i_do_not_exist&quot;)
-            self.assertEquals(record, None)
-
-        def test_basicAuth_master(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-            result = opendirectory.authenticateUserBasic(directory,
-                &quot;/LDAPv3/127.0.0.1&quot;, &quot;odtestamanda&quot;, &quot;password&quot;)
-            self.assertTrue(result)
-
-        def test_basicAuth_local(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-            result = opendirectory.authenticateUserBasic(directory,
-                &quot;/Local/Default&quot;, &quot;odtestalbert&quot;, &quot;password&quot;)
-            self.assertTrue(result)
-
-        def test_digestAuth_master(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            user = &quot;odtestamanda&quot;
-            password = &quot;password&quot;
-            node = &quot;/LDAPv3/127.0.0.1&quot;
-            uri = &quot;principals/users/odtestamanda&quot;
-            method = &quot;PROPFIND&quot;
-
-            challenge, response = getChallengeResponse(user, password, node,
-                uri, method)
-
-            result = opendirectory.authenticateUserDigest(directory, node,
-                user, challenge, response, method)
-            self.assertTrue(result)
-
-        def test_digestAuth_master_wrong_password(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            user = &quot;odtestamanda&quot;
-            password = &quot;wrong&quot;
-            node = &quot;/LDAPv3/127.0.0.1&quot;
-            uri = &quot;principals/users/odtestamanda&quot;
-            method = &quot;PROPFIND&quot;
-
-            challenge, response = getChallengeResponse(user, password, node,
-                uri, method)
-
-            self.assertEquals(
-                False,
-                opendirectory.authenticateUserDigest(directory, node, user,
-                    challenge, response, method)
-            )
-
-        def test_digestAuth_master_missing_record(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            user = &quot;missingperson&quot;
-            password = &quot;wrong&quot;
-            node = &quot;/LDAPv3/127.0.0.1&quot;
-            uri = &quot;principals/users/odtestamanda&quot;
-            method = &quot;PROPFIND&quot;
-
-            challenge, response = getChallengeResponse(user, password, node,
-                uri, method)
-
-            self.assertRaises(opendirectory.ODError,
-                opendirectory.authenticateUserDigest,
-                directory, node, user, challenge, response, method)
-
-        def test_digestAuth_local(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            user = &quot;odtestalbert&quot;
-            password = &quot;password&quot;
-            node = &quot;/Local/Default&quot;
-            uri = &quot;principals/users/odtestalbert&quot;
-            method = &quot;PROPFIND&quot;
-
-            challenge, response = getChallengeResponse(user, password, node,
-                uri, method)
-
-            result = opendirectory.authenticateUserDigest(directory, node,
-                user, challenge, response, method)
-            self.assertTrue(result)
-
-        def test_result_types(self):
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-            record = opendirectory.getUserRecord(directory, &quot;odtestbill&quot;)
-            name, data = opendirectory.recordToResult(record, {})
-            for value in data.values():
-                if isinstance(value, list):
-                    for item in value:
-                        self.assertTrue(type(item) is str)
-                else:
-                    self.assertTrue(type(value) is str)
-
-        def test_nonascii_record_by_guid(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrGeneratedUID,
-                &quot;CA795296-D77A-4E09-A72F-869920A3D284&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            result = results[0][1]
-            self.assertEquals(
-                result[dsattributes.kDS1AttrDistinguishedName],
-                &quot;Unicode Test \xc3\x90&quot;
-            )
-
-        def test_nonascii_record_by_name(self):
-
-            directory = opendirectory.odInit(&quot;/Search&quot;)
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrDistinguishedName,
-                &quot;Unicode Test \xc3\x90&quot;,
-                dsattributes.eDSExact,
-                False,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            result = results[0][1]
-            self.assertEquals(
-                result[dsattributes.kDS1AttrGeneratedUID],
-                &quot;CA795296-D77A-4E09-A72F-869920A3D284&quot;
-            )
-
-            results = opendirectory.queryRecordsWithAttribute_list(
-                directory,
-                dsattributes.kDS1AttrFirstName,
-                &quot;\xe4\xbd\x90\xe8\x97\xa4&quot;,
-                dsattributes.eDSStartsWith,
-                False,
-                dsattributes.kDSStdRecordTypeUsers,
-                USER_ATTRIBUTES,
-                count=0
-            )
-            result = results[0][1]
-            self.assertEquals(
-                result[dsattributes.kDS1AttrGeneratedUID],
-                &quot;C662F833-75AD-4589-9879-5FF102943CEF&quot;
-            )
-
-        def test_attributeNamesFromList(self):
-            self.assertEquals(
-                ([], {}), opendirectory.attributeNamesFromList(None)
-            )
-            self.assertEquals(
-                ([&quot;a&quot;, &quot;b&quot;], {&quot;b&quot;:&quot;base64&quot;}),
-                opendirectory.attributeNamesFromList([&quot;a&quot;, (&quot;b&quot;, &quot;base64&quot;)])
-            )
-
-        def test_autoPooled(self):
-            &quot;&quot;&quot;
-            Make sure no exception is raised by an autoPooled method
-            &quot;&quot;&quot;
-            @opendirectory.autoPooled
-            def method(x):
-                return x + 1
-
-            self.assertEquals(2, method(1))
</del></span></pre></div>
<a id="twexttrunktwextwhoopendirectorytesttest_servicepy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/who/opendirectory/test/test_service.py (12126 => 12127)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/who/opendirectory/test/test_service.py        2013-12-18 00:50:59 UTC (rev 12126)
+++ twext/trunk/twext/who/opendirectory/test/test_service.py        2013-12-18 18:29:24 UTC (rev 12127)
</span><span class="lines">@@ -35,33 +35,79 @@
</span><span class="cx"> 
</span><span class="cx">     def test_queryStringFromExpression(self):
</span><span class="cx">         service = DirectoryService()
</span><del>-        expression = MatchExpression(
-            service.fieldName.shortNames, u&quot;xyzzy&quot;,
-            matchType=MatchType.equals
-        )
-        query = service._queryStringFromExpression(expression)
-        self.assertEquals(query, u&quot;(dsAttrTypeStandard:RecordName=xyzzy)&quot;)
</del><span class="cx"> 
</span><ins>+        # MatchExpressions
+
+        for matchType, expected in (
+            (MatchType.equals, u&quot;=xyzzy&quot;),
+            (MatchType.startsWith, u&quot;=xyzzy*&quot;),
+            (MatchType.endsWith, u&quot;=*xyzzy&quot;),
+            (MatchType.contains, u&quot;=*xyzzy*&quot;),
+        ):
+            expression = MatchExpression(
+                service.fieldName.shortNames, u&quot;xyzzy&quot;,
+                matchType=matchType
+            )
+            queryString = service._queryStringFromExpression(expression)
+            self.assertEquals(queryString,
+                u&quot;(dsAttrTypeStandard:RecordName{exp})&quot;.format(exp=expected))
+
+        # CompoundExpressions
+
</ins><span class="cx">         expression = CompoundExpression(
</span><span class="cx">             [
</span><span class="cx">                 MatchExpression(
</span><del>-                    service.fieldName.shortNames, u&quot;xyzzy&quot;,
</del><ins>+                    service.fieldName.uid, u&quot;a&quot;,
</ins><span class="cx">                     matchType=MatchType.contains
</span><span class="cx">                 ),
</span><span class="cx">                 MatchExpression(
</span><del>-                    service.fieldName.emailAddresses, u&quot;plugh&quot;,
</del><ins>+                    service.fieldName.guid, u&quot;b&quot;,
+                    matchType=MatchType.contains
+                ),
+                MatchExpression(
+                    service.fieldName.shortNames, u&quot;c&quot;,
+                    matchType=MatchType.contains
+                ),
+                MatchExpression(
+                    service.fieldName.emailAddresses, u&quot;d&quot;,
</ins><span class="cx">                     matchType=MatchType.startsWith
</span><span class="cx">                 ),
</span><span class="cx">                 MatchExpression(
</span><del>-                    service.fieldName.fullNames, u&quot;foo&quot;,
</del><ins>+                    service.fieldName.fullNames, u&quot;e&quot;,
</ins><span class="cx">                     matchType=MatchType.equals
</span><span class="cx">                 ),
</span><span class="cx">             ],
</span><span class="cx">             Operand.AND
</span><span class="cx">         ) 
</span><del>-        query = service._queryStringFromExpression(expression)
-        self.assertEquals(query,
-            u&quot;(&amp;(dsAttrTypeStandard:RecordName=*xyzzy*)&quot;
-             &quot;(dsAttrTypeStandard:EMailAddress=plugh*)&quot;
-             &quot;(dsAttrTypeStandard:RealName=foo))&quot;
</del><ins>+        queryString = service._queryStringFromExpression(expression)
+        self.assertEquals(queryString,
+            u&quot;(&amp;(dsAttrTypeStandard:GeneratedUID=*a*)&quot;
+             &quot;(dsAttrTypeStandard:GeneratedUID=*b*)&quot;
+             &quot;(dsAttrTypeStandard:RecordName=*c*)&quot;
+             &quot;(dsAttrTypeStandard:EMailAddress=d*)&quot;
+             &quot;(dsAttrTypeStandard:RealName=e))&quot;
</ins><span class="cx">         )
</span><ins>+
+        expression = CompoundExpression(
+            [
+                MatchExpression(
+                    service.fieldName.shortNames, u&quot;a&quot;,
+                    matchType=MatchType.contains
+                ),
+                MatchExpression(
+                    service.fieldName.emailAddresses, u&quot;b&quot;,
+                    matchType=MatchType.startsWith
+                ),
+                MatchExpression(
+                    service.fieldName.fullNames, u&quot;c&quot;,
+                    matchType=MatchType.equals
+                ),
+            ],
+            Operand.OR
+        ) 
+        queryString = service._queryStringFromExpression(expression)
+        self.assertEquals(queryString,
+            u&quot;(|(dsAttrTypeStandard:RecordName=*a*)&quot;
+             &quot;(dsAttrTypeStandard:EMailAddress=b*)&quot;
+             &quot;(dsAttrTypeStandard:RealName=c))&quot;
+        )
</ins></span></pre>
</div>
</div>

</body>
</html>