<!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>[12256] CalendarServer/trunk/twistedcaldav/directory</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/12256">12256</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2014-01-07 11:53:20 -0800 (Tue, 07 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>lint</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryldapdirectorypy">CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectorytesttest_ldapdirectorypy">CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunktwistedcaldavdirectoryldapdirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py (12255 => 12256)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py        2014-01-07 18:34:58 UTC (rev 12255)
+++ CalendarServer/trunk/twistedcaldav/directory/ldapdirectory.py        2014-01-07 19:53:20 UTC (rev 12256)
</span><span class="lines">@@ -40,7 +40,8 @@
</span><span class="cx">     &quot;LdapDirectoryService&quot;,
</span><span class="cx"> ]
</span><span class="cx"> 
</span><del>-import ldap, ldap.async
</del><ins>+import ldap
+import ldap.async
</ins><span class="cx"> from ldap.filter import escape_filter_chars as ldapEsc
</span><span class="cx"> 
</span><span class="cx"> try:
</span><span class="lines">@@ -52,8 +53,9 @@
</span><span class="cx"> 
</span><span class="cx"> import time
</span><span class="cx"> from twisted.cred.credentials import UsernamePassword
</span><del>-from twistedcaldav.directory.cachingdirectory import (CachingDirectoryService,
-    CachingDirectoryRecord)
</del><ins>+from twistedcaldav.directory.cachingdirectory import (
+    CachingDirectoryService, CachingDirectoryRecord
+)
</ins><span class="cx"> from twistedcaldav.directory.directory import DirectoryConfigurationError
</span><span class="cx"> from twistedcaldav.directory.augment import AugmentRecord
</span><span class="cx"> from twistedcaldav.directory.util import splitIntoBatches, normalizeUUID
</span><span class="lines">@@ -63,6 +65,8 @@
</span><span class="cx"> from txweb2.http import HTTPError, StatusResponse
</span><span class="cx"> from txweb2 import responsecode
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class LdapDirectoryService(CachingDirectoryService):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     LDAP based implementation of L{IDirectoryService}.
</span><span class="lines">@@ -72,8 +76,9 @@
</span><span class="cx">     baseGUID = &quot;5A871574-0C86-44EE-B11B-B9440C3DC4DD&quot;
</span><span class="cx"> 
</span><span class="cx">     def __repr__(self):
</span><del>-        return &quot;&lt;%s %r: %r&gt;&quot; % (self.__class__.__name__, self.realmName,
-            self.uri)
</del><ins>+        return &quot;&lt;%s %r: %r&gt;&quot; % (
+            self.__class__.__name__, self.realmName, self.uri
+        )
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def __init__(self, params):
</span><span class="lines">@@ -85,15 +90,15 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">         defaults = {
</span><del>-            &quot;augmentService&quot; : None,
-            &quot;groupMembershipCache&quot; : None,
-            &quot;cacheTimeout&quot;: 1, # Minutes
</del><ins>+            &quot;augmentService&quot;: None,
+            &quot;groupMembershipCache&quot;: None,
+            &quot;cacheTimeout&quot;: 1,  # Minutes
</ins><span class="cx">             &quot;negativeCaching&quot;: False,
</span><span class="cx">             &quot;warningThresholdSeconds&quot;: 3,
</span><del>-            &quot;batchSize&quot;: 500, # for splitting up large queries
-            &quot;requestTimeoutSeconds&quot; : 10,
-            &quot;requestResultsLimit&quot; : 200,
-            &quot;optimizeMultiName&quot; : False,
</del><ins>+            &quot;batchSize&quot;: 500,  # for splitting up large queries
+            &quot;requestTimeoutSeconds&quot;: 10,
+            &quot;requestResultsLimit&quot;: 200,
+            &quot;optimizeMultiName&quot;: False,
</ins><span class="cx">             &quot;queryLocationsImplicitly&quot;: True,
</span><span class="cx">             &quot;restrictEnabledRecords&quot;: False,
</span><span class="cx">             &quot;restrictToGroup&quot;: &quot;&quot;,
</span><span class="lines">@@ -102,7 +107,7 @@
</span><span class="cx">             &quot;tls&quot;: False,
</span><span class="cx">             &quot;tlsCACertFile&quot;: None,
</span><span class="cx">             &quot;tlsCACertDir&quot;: None,
</span><del>-            &quot;tlsRequireCert&quot;: None, # never, allow, try, demand, hard
</del><ins>+            &quot;tlsRequireCert&quot;: None,  # never, allow, try, demand, hard
</ins><span class="cx">             &quot;credentials&quot;: {
</span><span class="cx">                 &quot;dn&quot;: None,
</span><span class="cx">                 &quot;password&quot;: None,
</span><span class="lines">@@ -113,68 +118,68 @@
</span><span class="cx">                 &quot;guidAttr&quot;: &quot;entryUUID&quot;,
</span><span class="cx">                 &quot;users&quot;: {
</span><span class="cx">                     &quot;rdn&quot;: &quot;ou=People&quot;,
</span><del>-                    &quot;filter&quot;: None, # additional filter for this type
-                    &quot;loginEnabledAttr&quot; : &quot;&quot;, # attribute controlling login
-                    &quot;loginEnabledValue&quot; : &quot;yes&quot;, # &quot;True&quot; value of above attribute
-                    &quot;calendarEnabledAttr&quot; : &quot;&quot;, # attribute controlling enabledForCalendaring
-                    &quot;calendarEnabledValue&quot; : &quot;yes&quot;, # &quot;True&quot; value of above attribute
-                    &quot;mapping&quot; : { # maps internal record names to LDAP
</del><ins>+                    &quot;filter&quot;: None,  # additional filter for this type
+                    &quot;loginEnabledAttr&quot;: &quot;&quot;,  # attribute controlling login
+                    &quot;loginEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
+                    &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling enabledForCalendaring
+                    &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
+                    &quot;mapping&quot;: {  # maps internal record names to LDAP
</ins><span class="cx">                         &quot;recordName&quot;: &quot;uid&quot;,
</span><del>-                        &quot;fullName&quot; : &quot;cn&quot;,
-                        &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
-                        &quot;firstName&quot; : &quot;givenName&quot;,
-                        &quot;lastName&quot; : &quot;sn&quot;,
</del><ins>+                        &quot;fullName&quot;: &quot;cn&quot;,
+                        &quot;emailAddresses&quot;: [&quot;mail&quot;],  # multiple LDAP fields supported
+                        &quot;firstName&quot;: &quot;givenName&quot;,
+                        &quot;lastName&quot;: &quot;sn&quot;,
</ins><span class="cx">                     },
</span><span class="cx">                 },
</span><span class="cx">                 &quot;groups&quot;: {
</span><span class="cx">                     &quot;rdn&quot;: &quot;ou=Group&quot;,
</span><del>-                    &quot;filter&quot;: None, # additional filter for this type
-                    &quot;mapping&quot; : { # maps internal record names to LDAP
</del><ins>+                    &quot;filter&quot;: None,  # additional filter for this type
+                    &quot;mapping&quot;: {  # maps internal record names to LDAP
</ins><span class="cx">                         &quot;recordName&quot;: &quot;cn&quot;,
</span><del>-                        &quot;fullName&quot; : &quot;cn&quot;,
-                        &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
-                        &quot;firstName&quot; : &quot;givenName&quot;,
-                        &quot;lastName&quot; : &quot;sn&quot;,
</del><ins>+                        &quot;fullName&quot;: &quot;cn&quot;,
+                        &quot;emailAddresses&quot;: [&quot;mail&quot;],  # multiple LDAP fields supported
+                        &quot;firstName&quot;: &quot;givenName&quot;,
+                        &quot;lastName&quot;: &quot;sn&quot;,
</ins><span class="cx">                     },
</span><span class="cx">                 },
</span><span class="cx">                 &quot;locations&quot;: {
</span><span class="cx">                     &quot;rdn&quot;: &quot;ou=Places&quot;,
</span><del>-                    &quot;filter&quot;: None, # additional filter for this type
-                    &quot;calendarEnabledAttr&quot; : &quot;&quot;, # attribute controlling enabledForCalendaring
-                    &quot;calendarEnabledValue&quot; : &quot;yes&quot;, # &quot;True&quot; value of above attribute
-                    &quot;associatedAddressAttr&quot; : &quot;&quot;,
-                    &quot;mapping&quot; : { # maps internal record names to LDAP
</del><ins>+                    &quot;filter&quot;: None,  # additional filter for this type
+                    &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling enabledForCalendaring
+                    &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
+                    &quot;associatedAddressAttr&quot;: &quot;&quot;,
+                    &quot;mapping&quot;: {  # maps internal record names to LDAP
</ins><span class="cx">                         &quot;recordName&quot;: &quot;cn&quot;,
</span><del>-                        &quot;fullName&quot; : &quot;cn&quot;,
-                        &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
</del><ins>+                        &quot;fullName&quot;: &quot;cn&quot;,
+                        &quot;emailAddresses&quot;: [&quot;mail&quot;],  # multiple LDAP fields supported
</ins><span class="cx">                     },
</span><span class="cx">                 },
</span><span class="cx">                 &quot;resources&quot;: {
</span><span class="cx">                     &quot;rdn&quot;: &quot;ou=Resources&quot;,
</span><del>-                    &quot;filter&quot;: None, # additional filter for this type
-                    &quot;calendarEnabledAttr&quot; : &quot;&quot;, # attribute controlling enabledForCalendaring
-                    &quot;calendarEnabledValue&quot; : &quot;yes&quot;, # &quot;True&quot; value of above attribute
-                    &quot;mapping&quot; : { # maps internal record names to LDAP
</del><ins>+                    &quot;filter&quot;: None,  # additional filter for this type
+                    &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling enabledForCalendaring
+                    &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
+                    &quot;mapping&quot;: {  # maps internal record names to LDAP
</ins><span class="cx">                         &quot;recordName&quot;: &quot;cn&quot;,
</span><del>-                        &quot;fullName&quot; : &quot;cn&quot;,
-                        &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
</del><ins>+                        &quot;fullName&quot;: &quot;cn&quot;,
+                        &quot;emailAddresses&quot;: [&quot;mail&quot;],  # multiple LDAP fields supported
</ins><span class="cx">                     },
</span><span class="cx">                 },
</span><span class="cx">                 &quot;addresses&quot;: {
</span><span class="cx">                     &quot;rdn&quot;: &quot;ou=Buildings&quot;,
</span><del>-                    &quot;filter&quot;: None, # additional filter for this type
-                    &quot;streetAddressAttr&quot; : &quot;&quot;,
-                    &quot;geoAttr&quot; : &quot;&quot;,
-                    &quot;mapping&quot; : { # maps internal record names to LDAP
</del><ins>+                    &quot;filter&quot;: None,  # additional filter for this type
+                    &quot;streetAddressAttr&quot;: &quot;&quot;,
+                    &quot;geoAttr&quot;: &quot;&quot;,
+                    &quot;mapping&quot;: {  # maps internal record names to LDAP
</ins><span class="cx">                         &quot;recordName&quot;: &quot;cn&quot;,
</span><del>-                        &quot;fullName&quot; : &quot;cn&quot;,
</del><ins>+                        &quot;fullName&quot;: &quot;cn&quot;,
</ins><span class="cx">                     },
</span><span class="cx">                 },
</span><span class="cx">             },
</span><span class="cx">             &quot;groupSchema&quot;: {
</span><del>-                &quot;membersAttr&quot;: &quot;member&quot;, # how members are specified
-                &quot;nestedGroupsAttr&quot;: None, # how nested groups are specified
-                &quot;memberIdAttr&quot;: None, # which attribute the above refer to (None means use DN)
</del><ins>+                &quot;membersAttr&quot;: &quot;member&quot;,  # how members are specified
+                &quot;nestedGroupsAttr&quot;: None,  # how nested groups are specified
+                &quot;memberIdAttr&quot;: None,  # which attribute the above refer to (None means use DN)
</ins><span class="cx">             },
</span><span class="cx">             &quot;resourceSchema&quot;: {
</span><span class="cx">                 # Either set this attribute to retrieve the plist version
</span><span class="lines">@@ -184,12 +189,12 @@
</span><span class="cx">                 # individually:
</span><span class="cx">                 &quot;autoScheduleAttr&quot;: None,
</span><span class="cx">                 &quot;autoScheduleEnabledValue&quot;: &quot;yes&quot;,
</span><del>-                &quot;proxyAttr&quot;: None, # list of GUIDs
-                &quot;readOnlyProxyAttr&quot;: None, # list of GUIDs
-                &quot;autoAcceptGroupAttr&quot;: None, # single group GUID
</del><ins>+                &quot;proxyAttr&quot;: None,  # list of GUIDs
+                &quot;readOnlyProxyAttr&quot;: None,  # list of GUIDs
+                &quot;autoAcceptGroupAttr&quot;: None,  # single group GUID
</ins><span class="cx">             },
</span><span class="cx">             &quot;poddingSchema&quot;: {
</span><del>-                &quot;serverIdAttr&quot;: None, # maps to augments server-id
</del><ins>+                &quot;serverIdAttr&quot;: None,  # maps to augments server-id
</ins><span class="cx">             },
</span><span class="cx">         }
</span><span class="cx">         ignored = None
</span><span class="lines">@@ -238,7 +243,7 @@
</span><span class="cx">             if self.rdnSchema[recordType][&quot;attr&quot;]:
</span><span class="cx">                 attrSet.add(self.rdnSchema[recordType][&quot;attr&quot;])
</span><span class="cx">             for n in (&quot;calendarEnabledAttr&quot;, &quot;associatedAddressAttr&quot;,
</span><del>-                &quot;streetAddressAttr&quot;, &quot;geoAttr&quot;):
</del><ins>+                      &quot;streetAddressAttr&quot;, &quot;geoAttr&quot;):
</ins><span class="cx">                 if self.rdnSchema[recordType].get(n, False):
</span><span class="cx">                     attrSet.add(self.rdnSchema[recordType][n])
</span><span class="cx">             for attrList in self.rdnSchema[recordType][&quot;mapping&quot;].values():
</span><span class="lines">@@ -311,15 +316,16 @@
</span><span class="cx"> 
</span><span class="cx">         # Query the LDAP server
</span><span class="cx">         self.log.debug(&quot;Querying ldap for records matching base {base} and &quot;
</span><del>-            &quot;filter {filter} for attributes {attrs}.&quot;,
-            base=ldap.dn.dn2str(base), filter=filterstr, attrs=self.attrlist)
</del><ins>+                       &quot;filter {filter} for attributes {attrs}.&quot;,
+                       base=ldap.dn.dn2str(base), filter=filterstr,
+                       attrs=self.attrlist)
</ins><span class="cx"> 
</span><span class="cx">         # This takes a while, so if you don't want to have a &quot;long request&quot;
</span><span class="cx">         # warning logged, use this instead of timedSearch:
</span><span class="cx">         # results = self.ldap.search_s(ldap.dn.dn2str(base),
</span><span class="cx">         #     ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
</span><del>-        results = self.timedSearch(ldap.dn.dn2str(base),
-            ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
</del><ins>+        results = self.timedSearch(ldap.dn.dn2str(base), ldap.SCOPE_SUBTREE,
+                                   filterstr=filterstr, attrlist=self.attrlist)
</ins><span class="cx"> 
</span><span class="cx">         records = []
</span><span class="cx">         numMissingGuids = 0
</span><span class="lines">@@ -337,7 +343,8 @@
</span><span class="cx">                 continue
</span><span class="cx"> 
</span><span class="cx">             if not unrestricted:
</span><del>-                self.log.debug(&quot;{dn} is not enabled because it's not a member of group: {group}&quot;,
</del><ins>+                self.log.debug(
+                    &quot;{dn} is not enabled because it's not a member of group: {group}&quot;,
</ins><span class="cx">                     dn=dn, group=self.restrictToGroup)
</span><span class="cx">                 record.enabledForCalendaring = False
</span><span class="cx">                 record.enabledForAddressBooks = False
</span><span class="lines">@@ -346,7 +353,8 @@
</span><span class="cx"> 
</span><span class="cx">         if numMissingGuids:
</span><span class="cx">             self.log.info(&quot;{num} {recordType} records are missing {attr}&quot;,
</span><del>-                num=numMissingGuids, recordType=recordType, attr=guidAttr)
</del><ins>+                          num=numMissingGuids, recordType=recordType,
+                          attr=guidAttr)
</ins><span class="cx"> 
</span><span class="cx">         return records
</span><span class="cx"> 
</span><span class="lines">@@ -400,11 +408,13 @@
</span><span class="cx"> 
</span><span class="cx">         # Query the LDAP server
</span><span class="cx">         self.log.debug(&quot;Querying ldap for records matching base {base} and &quot;
</span><del>-            &quot;filter {filter} for attributes {attrs}.&quot;,
-            base=ldap.dn.dn2str(self.base), filter=filterstr, attrs=attrlist)
</del><ins>+                       &quot;filter {filter} for attributes {attrs}.&quot;,
+                       base=ldap.dn.dn2str(self.base), filter=filterstr,
+                       attrs=attrlist)
</ins><span class="cx"> 
</span><span class="cx">         results = self.timedSearch(ldap.dn.dn2str(self.base),
</span><del>-            ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=attrlist)
</del><ins>+                                   ldap.SCOPE_SUBTREE, filterstr=filterstr,
+                                   attrlist=attrlist)
</ins><span class="cx"> 
</span><span class="cx">         for dn, attrs in results:
</span><span class="cx">             dn = normalizeDNstr(dn)
</span><span class="lines">@@ -415,12 +425,12 @@
</span><span class="cx">                 if readDelegate:
</span><span class="cx">                     readDelegate = normalizeUUID(readDelegate)
</span><span class="cx">                     assignments.append((&quot;%s#calendar-proxy-read&quot; % (guid,),
</span><del>-                        [readDelegate]))
</del><ins>+                                       [readDelegate]))
</ins><span class="cx">                 writeDelegate = self._getUniqueLdapAttribute(attrs, writeAttr)
</span><span class="cx">                 if writeDelegate:
</span><span class="cx">                     writeDelegate = normalizeUUID(writeDelegate)
</span><span class="cx">                     assignments.append((&quot;%s#calendar-proxy-write&quot; % (guid,),
</span><del>-                        [writeDelegate]))
</del><ins>+                                       [writeDelegate]))
</ins><span class="cx"> 
</span><span class="cx">         return assignments
</span><span class="cx"> 
</span><span class="lines">@@ -433,11 +443,11 @@
</span><span class="cx">             if self.credentials.get(&quot;dn&quot;, &quot;&quot;):
</span><span class="cx">                 try:
</span><span class="cx">                     self.log.info(&quot;Binding to LDAP {dn}&quot;,
</span><del>-                        dn=repr(self.credentials.get(&quot;dn&quot;)))
</del><ins>+                                  dn=repr(self.credentials.get(&quot;dn&quot;)))
</ins><span class="cx">                     self.ldap.simple_bind_s(self.credentials.get(&quot;dn&quot;),
</span><del>-                        self.credentials.get(&quot;password&quot;))
</del><ins>+                                            self.credentials.get(&quot;password&quot;))
</ins><span class="cx">                     self.log.info(&quot;Successfully authenticated with LDAP as {dn}&quot;,
</span><del>-                        dn=repr(self.credentials.get(&quot;dn&quot;)))
</del><ins>+                                  dn=repr(self.credentials.get(&quot;dn&quot;)))
</ins><span class="cx">                 except ldap.INVALID_CREDENTIALS:
</span><span class="cx">                     self.log.error(&quot;Can't bind to LDAP {uri}: check credentials&quot;, uri=self.uri)
</span><span class="cx">                     raise DirectoryConfigurationError()
</span><span class="lines">@@ -498,7 +508,7 @@
</span><span class="cx"> 
</span><span class="cx">             except ldap.NO_SUCH_OBJECT:
</span><span class="cx">                 self.log.error(&quot;LDAP Authentication error for %s: NO_SUCH_OBJECT&quot;
</span><del>-                    % (dn,))
</del><ins>+                               % (dn,))
</ins><span class="cx">                 # fall through to try again; could be transient
</span><span class="cx"> 
</span><span class="cx">             except ldap.INVALID_CREDENTIALS:
</span><span class="lines">@@ -526,7 +536,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def timedSearch(self, base, scope, filterstr=&quot;(objectClass=*)&quot;,
</span><del>-        attrlist=None, timeoutSeconds=-1, resultLimit=0):
</del><ins>+                    attrlist=None, timeoutSeconds=-1, resultLimit=0):
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Execute an LDAP query, retrying up to 3 times in case the LDAP server has
</span><span class="cx">         gone down and we need to reconnect. If it takes longer than the configured
</span><span class="lines">@@ -541,8 +551,7 @@
</span><span class="cx">             try:
</span><span class="cx">                 s = ldap.async.List(self.getLDAPConnection())
</span><span class="cx">                 s.startSearch(base, scope, filterstr, attrList=attrlist,
</span><del>-                    timeout=timeoutSeconds,
-                    sizelimit=resultLimit)
</del><ins>+                              timeout=timeoutSeconds, sizelimit=resultLimit)
</ins><span class="cx">                 startTime = time.time()
</span><span class="cx">                 s.processResults()
</span><span class="cx">             except ldap.NO_SUCH_OBJECT:
</span><span class="lines">@@ -566,8 +575,10 @@
</span><span class="cx">             if totalTime &gt; self.warningThresholdSeconds:
</span><span class="cx">                 if filterstr and len(filterstr) &gt; 100:
</span><span class="cx">                     filterstr = &quot;%s...&quot; % (filterstr[:100],)
</span><del>-                self.log.error(&quot;LDAP query exceeded threshold: %.2f seconds for %s %s %s (#results=%d)&quot; %
-                    (totalTime, base, filterstr, attrlist, len(result)))
</del><ins>+                self.log.error(
+                    &quot;LDAP query exceeded threshold: %.2f seconds for %s %s %s (#results=%d)&quot; %
+                    (totalTime, base, filterstr, attrlist, len(result))
+                )
</ins><span class="cx">             return result
</span><span class="cx"> 
</span><span class="cx">         raise HTTPError(StatusResponse(responsecode.SERVICE_UNAVAILABLE, &quot;LDAP server unavailable&quot;))
</span><span class="lines">@@ -589,7 +600,7 @@
</span><span class="cx">             return True
</span><span class="cx">         if self.groupSchema[&quot;memberIdAttr&quot;]:
</span><span class="cx">             value = self._getUniqueLdapAttribute(attrs, self.groupSchema[&quot;memberIdAttr&quot;])
</span><del>-        else: # No memberIdAttr implies DN
</del><ins>+        else:  # No memberIdAttr implies DN
</ins><span class="cx">             value = dn
</span><span class="cx">         return value in self.restrictedPrincipals
</span><span class="cx"> 
</span><span class="lines">@@ -610,9 +621,11 @@
</span><span class="cx">                 # TODO: This shouldn't be hardcoded to cn
</span><span class="cx">                 filterstr = &quot;(cn=%s)&quot; % (self.restrictToGroup,)
</span><span class="cx">                 self.log.debug(&quot;Retrieving ldap record with base %s and filter %s.&quot; %
</span><del>-                    (ldap.dn.dn2str(base), filterstr))
</del><ins>+                               (ldap.dn.dn2str(base), filterstr))
</ins><span class="cx">                 result = self.timedSearch(ldap.dn.dn2str(base),
</span><del>-                    ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
</del><ins>+                                          ldap.SCOPE_SUBTREE,
+                                          filterstr=filterstr,
+                                          attrlist=self.attrlist)
</ins><span class="cx"> 
</span><span class="cx">                 members = []
</span><span class="cx">                 nestedGroups = []
</span><span class="lines">@@ -621,16 +634,20 @@
</span><span class="cx">                     dn, attrs = result[0]
</span><span class="cx">                     dn = normalizeDNstr(dn)
</span><span class="cx">                     if self.groupSchema[&quot;membersAttr&quot;]:
</span><del>-                        members = self._getMultipleLdapAttributes(attrs,
-                            self.groupSchema[&quot;membersAttr&quot;])
-                        if not self.groupSchema[&quot;memberIdAttr&quot;]: # these are DNs
</del><ins>+                        members = self._getMultipleLdapAttributes(
+                            attrs,
+                            self.groupSchema[&quot;membersAttr&quot;]
+                        )
+                        if not self.groupSchema[&quot;memberIdAttr&quot;]:  # these are DNs
</ins><span class="cx">                             members = [normalizeDNstr(m) for m in members]
</span><span class="cx">                         members = set(members)
</span><span class="cx"> 
</span><span class="cx">                     if self.groupSchema[&quot;nestedGroupsAttr&quot;]:
</span><del>-                        nestedGroups = self._getMultipleLdapAttributes(attrs,
-                            self.groupSchema[&quot;nestedGroupsAttr&quot;])
-                        if not self.groupSchema[&quot;memberIdAttr&quot;]: # these are DNs
</del><ins>+                        nestedGroups = self._getMultipleLdapAttributes(
+                            attrs,
+                            self.groupSchema[&quot;nestedGroupsAttr&quot;]
+                        )
+                        if not self.groupSchema[&quot;memberIdAttr&quot;]:  # these are DNs
</ins><span class="cx">                             nestedGroups = [normalizeDNstr(g) for g in nestedGroups]
</span><span class="cx">                         nestedGroups = set(nestedGroups)
</span><span class="cx">                     else:
</span><span class="lines">@@ -639,8 +656,9 @@
</span><span class="cx">                         nestedGroups = members
</span><span class="cx">                         members = set()
</span><span class="cx"> 
</span><del>-                self._cachedRestrictedPrincipals = set(self._expandGroupMembership(members,
-                    nestedGroups))
</del><ins>+                self._cachedRestrictedPrincipals = set(
+                    self._expandGroupMembership(members, nestedGroups)
+                )
</ins><span class="cx">                 self.log.info(&quot;Got %d restricted group members&quot; % (
</span><span class="cx">                     len(self._cachedRestrictedPrincipals),))
</span><span class="cx">                 self.restrictedTimestamp = time.time()
</span><span class="lines">@@ -695,15 +713,17 @@
</span><span class="cx">                 scope = ldap.SCOPE_SUBTREE
</span><span class="cx">                 base = self.typeDNs[recordType]
</span><span class="cx">                 filterstr = &quot;(%s=%s)&quot; % (self.groupSchema[&quot;memberIdAttr&quot;], group)
</span><del>-            else: # Use DN
</del><ins>+            else:  # Use DN
</ins><span class="cx">                 scope = ldap.SCOPE_BASE
</span><span class="cx">                 base = ldap.dn.str2dn(group)
</span><span class="cx">                 filterstr = &quot;(objectClass=*)&quot;
</span><span class="cx"> 
</span><span class="cx">             self.log.debug(&quot;Retrieving ldap record with base %s and filter %s.&quot; %
</span><del>-                (ldap.dn.dn2str(base), filterstr))
</del><ins>+                           (ldap.dn.dn2str(base), filterstr))
</ins><span class="cx">             result = self.timedSearch(ldap.dn.dn2str(base),
</span><del>-                scope, filterstr=filterstr, attrlist=self.attrlist)
</del><ins>+                                      scope,
+                                      filterstr=filterstr,
+                                      attrlist=self.attrlist)
</ins><span class="cx"> 
</span><span class="cx">             if len(result) == 0:
</span><span class="cx">                 continue
</span><span class="lines">@@ -714,24 +734,29 @@
</span><span class="cx">                 dn, attrs = result[0]
</span><span class="cx">                 dn = normalizeDNstr(dn)
</span><span class="cx">                 if self.groupSchema[&quot;membersAttr&quot;]:
</span><del>-                    subMembers = self._getMultipleLdapAttributes(attrs,
-                        self.groupSchema[&quot;membersAttr&quot;])
-                    if not self.groupSchema[&quot;memberIdAttr&quot;]: # these are DNs
</del><ins>+                    subMembers = self._getMultipleLdapAttributes(
+                        attrs,
+                        self.groupSchema[&quot;membersAttr&quot;]
+                    )
+                    if not self.groupSchema[&quot;memberIdAttr&quot;]:  # these are DNs
</ins><span class="cx">                         subMembers = [normalizeDNstr(m) for m in subMembers]
</span><span class="cx">                     subMembers = set(subMembers)
</span><span class="cx"> 
</span><span class="cx">                 if self.groupSchema[&quot;nestedGroupsAttr&quot;]:
</span><del>-                    subNestedGroups = self._getMultipleLdapAttributes(attrs,
-                        self.groupSchema[&quot;nestedGroupsAttr&quot;])
-                    if not self.groupSchema[&quot;memberIdAttr&quot;]: # these are DNs
</del><ins>+                    subNestedGroups = self._getMultipleLdapAttributes(
+                        attrs,
+                        self.groupSchema[&quot;nestedGroupsAttr&quot;]
+                    )
+                    if not self.groupSchema[&quot;memberIdAttr&quot;]:  # these are DNs
</ins><span class="cx">                         subNestedGroups = [normalizeDNstr(g) for g in subNestedGroups]
</span><span class="cx">                     subNestedGroups = set(subNestedGroups)
</span><span class="cx"> 
</span><span class="cx">             processedItems.add(group)
</span><span class="cx">             yield group
</span><span class="cx"> 
</span><del>-            for item in self._expandGroupMembership(subMembers, subNestedGroups,
-                processedItems):
</del><ins>+            for item in self._expandGroupMembership(subMembers,
+                                                    subNestedGroups,
+                                                    processedItems):
</ins><span class="cx">                 yield item
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -805,8 +830,10 @@
</span><span class="cx">         emailSuffix = self.rdnSchema[recordType].get(&quot;emailSuffix&quot;, None)
</span><span class="cx"> 
</span><span class="cx">         if len(emailAddresses) == 0 and emailSuffix:
</span><del>-            emailPrefix = self._getUniqueLdapAttribute(attrs,
-                self.rdnSchema[recordType].get(&quot;attr&quot;, &quot;cn&quot;))
</del><ins>+            emailPrefix = self._getUniqueLdapAttribute(
+                attrs,
+                self.rdnSchema[recordType].get(&quot;attr&quot;, &quot;cn&quot;)
+            )
</ins><span class="cx">             emailAddresses.add(emailPrefix + emailSuffix)
</span><span class="cx"> 
</span><span class="cx">         proxyGUIDs = ()
</span><span class="lines">@@ -837,7 +864,7 @@
</span><span class="cx">                 memberGUIDs.extend(members)
</span><span class="cx"> 
</span><span class="cx">             # Normalize members if they're in DN form
</span><del>-            if not self.groupSchema[&quot;memberIdAttr&quot;]: # empty = dn
</del><ins>+            if not self.groupSchema[&quot;memberIdAttr&quot;]:  # empty = dn
</ins><span class="cx">                 guids = list(memberGUIDs)
</span><span class="cx">                 memberGUIDs = []
</span><span class="cx">                 for dnStr in guids:
</span><span class="lines">@@ -849,14 +876,16 @@
</span><span class="cx">                         self.log.warn(&quot;Bad LDAP DN: %s&quot; % (dnStr,))
</span><span class="cx"> 
</span><span class="cx">         elif recordType in (self.recordType_resources,
</span><del>-            self.recordType_locations):
</del><ins>+                            self.recordType_locations):
</ins><span class="cx">             fullName = self._getUniqueLdapAttribute(attrs, self.rdnSchema[recordType][&quot;mapping&quot;][&quot;fullName&quot;])
</span><span class="cx">             enabledForCalendaring = True
</span><span class="cx">             enabledForAddressBooks = False
</span><span class="cx">             enabledForLogin = False
</span><span class="cx">             if self.resourceSchema[&quot;resourceInfoAttr&quot;]:
</span><del>-                resourceInfo = self._getUniqueLdapAttribute(attrs,
-                    self.resourceSchema[&quot;resourceInfoAttr&quot;])
</del><ins>+                resourceInfo = self._getUniqueLdapAttribute(
+                    attrs,
+                    self.resourceSchema[&quot;resourceInfoAttr&quot;]
+                )
</ins><span class="cx">                 if resourceInfo:
</span><span class="cx">                     try:
</span><span class="cx">                         (
</span><span class="lines">@@ -876,45 +905,66 @@
</span><span class="cx">                             readOnlyProxyGUIDs = (readOnlyProxy,)
</span><span class="cx">                     except ValueError, e:
</span><span class="cx">                         self.log.error(&quot;Unable to parse resource info (%s)&quot; % (e,))
</span><del>-            else: # the individual resource attributes might be specified
</del><ins>+            else:  # the individual resource attributes might be specified
</ins><span class="cx">                 if self.resourceSchema[&quot;autoScheduleAttr&quot;]:
</span><del>-                    autoScheduleValue = self._getUniqueLdapAttribute(attrs,
-                        self.resourceSchema[&quot;autoScheduleAttr&quot;])
-                    autoSchedule = (autoScheduleValue ==
-                        self.resourceSchema[&quot;autoScheduleEnabledValue&quot;])
</del><ins>+                    autoScheduleValue = self._getUniqueLdapAttribute(
+                        attrs,
+                        self.resourceSchema[&quot;autoScheduleAttr&quot;]
+                    )
+                    autoSchedule = (
+                        autoScheduleValue == self.resourceSchema[&quot;autoScheduleEnabledValue&quot;]
+                    )
</ins><span class="cx">                 if self.resourceSchema[&quot;proxyAttr&quot;]:
</span><del>-                    proxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
-                        self.resourceSchema[&quot;proxyAttr&quot;]))
</del><ins>+                    proxyGUIDs = set(
+                        self._getMultipleLdapAttributes(
+                            attrs,
+                            self.resourceSchema[&quot;proxyAttr&quot;]
+                        )
+                    )
</ins><span class="cx">                 if self.resourceSchema[&quot;readOnlyProxyAttr&quot;]:
</span><del>-                    readOnlyProxyGUIDs = set(self._getMultipleLdapAttributes(attrs,
-                        self.resourceSchema[&quot;readOnlyProxyAttr&quot;]))
</del><ins>+                    readOnlyProxyGUIDs = set(
+                        self._getMultipleLdapAttributes(
+                            attrs,
+                            self.resourceSchema[&quot;readOnlyProxyAttr&quot;]
+                        )
+                    )
</ins><span class="cx">                 if self.resourceSchema[&quot;autoAcceptGroupAttr&quot;]:
</span><del>-                    autoAcceptGroup = self._getUniqueLdapAttribute(attrs,
-                        self.resourceSchema[&quot;autoAcceptGroupAttr&quot;])
</del><ins>+                    autoAcceptGroup = self._getUniqueLdapAttribute(
+                        attrs,
+                        self.resourceSchema[&quot;autoAcceptGroupAttr&quot;]
+                    )
</ins><span class="cx"> 
</span><span class="cx">             if recordType == self.recordType_locations:
</span><span class="cx">                 if self.rdnSchema[recordType][&quot;associatedAddressAttr&quot;]:
</span><del>-                    associatedAddress = self._getUniqueLdapAttribute(attrs,
-                        self.rdnSchema[recordType][&quot;associatedAddressAttr&quot;])
</del><ins>+                    associatedAddress = self._getUniqueLdapAttribute(
+                        attrs,
+                        self.rdnSchema[recordType][&quot;associatedAddressAttr&quot;]
+                    )
</ins><span class="cx">                     if associatedAddress:
</span><span class="cx">                         extras[&quot;associatedAddress&quot;] = associatedAddress
</span><span class="cx"> 
</span><span class="cx">         elif recordType == self.recordType_addresses:
</span><span class="cx">             if self.rdnSchema[recordType].get(&quot;geoAttr&quot;, &quot;&quot;):
</span><del>-                geo = self._getUniqueLdapAttribute(attrs,
-                    self.rdnSchema[recordType][&quot;geoAttr&quot;])
</del><ins>+                geo = self._getUniqueLdapAttribute(
+                    attrs,
+                    self.rdnSchema[recordType][&quot;geoAttr&quot;]
+                )
</ins><span class="cx">                 if geo:
</span><span class="cx">                     extras[&quot;geo&quot;] = geo
</span><span class="cx">             if self.rdnSchema[recordType].get(&quot;streetAddressAttr&quot;, &quot;&quot;):
</span><del>-                street = self._getUniqueLdapAttribute(attrs,
-                    self.rdnSchema[recordType][&quot;streetAddressAttr&quot;])
</del><ins>+                street = self._getUniqueLdapAttribute(
+                    attrs,
+                    self.rdnSchema[recordType][&quot;streetAddressAttr&quot;]
+                )
</ins><span class="cx">                 if street:
</span><span class="cx">                     extras[&quot;streetAddress&quot;] = street
</span><span class="cx"> 
</span><span class="cx">         serverID = None
</span><span class="cx">         if self.poddingSchema[&quot;serverIdAttr&quot;]:
</span><del>-            serverID = self._getUniqueLdapAttribute(attrs,
-                self.poddingSchema[&quot;serverIdAttr&quot;])
</del><ins>+            serverID = self._getUniqueLdapAttribute(
+                attrs,
+                self.poddingSchema[&quot;serverIdAttr&quot;]
+            )
</ins><span class="cx"> 
</span><span class="cx">         record = LdapDirectoryRecord(
</span><span class="cx">             service=self,
</span><span class="lines">@@ -940,8 +990,7 @@
</span><span class="cx">             # TODO: this needs to be deferred but for now we hard code
</span><span class="cx">             # the deferred result because we know it is completing
</span><span class="cx">             # immediately.
</span><del>-            d = self.augmentService.getAugmentRecord(record.guid,
-                recordType)
</del><ins>+            d = self.augmentService.getAugmentRecord(record.guid, recordType)
</ins><span class="cx">             d.addCallback(lambda x: record.addAugmentInformation(x))
</span><span class="cx"> 
</span><span class="cx">         else:
</span><span class="lines">@@ -953,7 +1002,7 @@
</span><span class="cx">                 enabledForCalendaring=enabledForCalendaring,
</span><span class="cx">                 autoSchedule=autoSchedule,
</span><span class="cx">                 autoAcceptGroup=autoAcceptGroup,
</span><del>-                enabledForAddressBooks=enabledForAddressBooks, # TODO: add to LDAP?
</del><ins>+                enabledForAddressBooks=enabledForAddressBooks,  # TODO: add to LDAP?
</ins><span class="cx">                 enabledForLogin=enabledForLogin,
</span><span class="cx">             )
</span><span class="cx">             record.addAugmentInformation(augmentRecord)
</span><span class="lines">@@ -963,15 +1012,18 @@
</span><span class="cx">             loginEnabledAttr = self.rdnSchema[recordType][&quot;loginEnabledAttr&quot;]
</span><span class="cx">             if loginEnabledAttr:
</span><span class="cx">                 loginEnabledValue = self.rdnSchema[recordType][&quot;loginEnabledValue&quot;]
</span><del>-                record.enabledForLogin = self._getUniqueLdapAttribute(attrs,
-                    loginEnabledAttr) == loginEnabledValue
</del><ins>+                record.enabledForLogin = self._getUniqueLdapAttribute(
+                    attrs, loginEnabledAttr
+                ) == loginEnabledValue
</ins><span class="cx"> 
</span><span class="cx">         # Override with LDAP calendar-enabled control if attribute specified
</span><span class="cx">         calendarEnabledAttr = self.rdnSchema[recordType].get(&quot;calendarEnabledAttr&quot;, &quot;&quot;)
</span><span class="cx">         if calendarEnabledAttr:
</span><span class="cx">             calendarEnabledValue = self.rdnSchema[recordType][&quot;calendarEnabledValue&quot;]
</span><del>-            record.enabledForCalendaring = self._getUniqueLdapAttribute(attrs,
-                calendarEnabledAttr) == calendarEnabledValue
</del><ins>+            record.enabledForCalendaring = self._getUniqueLdapAttribute(
+                attrs,
+                calendarEnabledAttr
+            ) == calendarEnabledValue
</ins><span class="cx"> 
</span><span class="cx">         return record
</span><span class="cx"> 
</span><span class="lines">@@ -994,7 +1046,7 @@
</span><span class="cx">             queryMethod = self.timedSearch
</span><span class="cx"> 
</span><span class="cx">         self.log.debug(&quot;LDAP query for types %s, indexType %s and indexKey %s&quot;
</span><del>-            % (recordTypes, indexType, indexKey))
</del><ins>+                       % (recordTypes, indexType, indexKey))
</ins><span class="cx"> 
</span><span class="cx">         guidAttr = self.rdnSchema[&quot;guidAttr&quot;]
</span><span class="cx">         for recordType in recordTypes:
</span><span class="lines">@@ -1024,7 +1076,7 @@
</span><span class="cx"> 
</span><span class="cx">             elif indexType == self.INDEX_TYPE_CUA:
</span><span class="cx">                 # indexKey is of the form &quot;mailto:test@example.net&quot;
</span><del>-                email = indexKey[7:] # strip &quot;mailto:&quot;
</del><ins>+                email = indexKey[7:]  # strip &quot;mailto:&quot;
</ins><span class="cx">                 emailSuffix = self.rdnSchema[recordType].get(&quot;emailSuffix&quot;, None)
</span><span class="cx">                 if emailSuffix is not None and email.partition(&quot;@&quot;)[2] == emailSuffix:
</span><span class="cx">                     filterstr = &quot;(&amp;%s(|(&amp;(!(mail=*))(%s=%s))(mail=%s)))&quot; % (
</span><span class="lines">@@ -1040,7 +1092,7 @@
</span><span class="cx">                         if ldapFields:
</span><span class="cx">                             subfilter = &quot;(%s=%s)&quot; % (ldapFields, ldapEsc(email))
</span><span class="cx">                         else:
</span><del>-                            continue # No LDAP attribute assigned for emailAddresses
</del><ins>+                            continue  # No LDAP attribute assigned for emailAddresses
</ins><span class="cx"> 
</span><span class="cx">                     else:
</span><span class="cx">                         subfilter = []
</span><span class="lines">@@ -1048,7 +1100,7 @@
</span><span class="cx">                             if ldapField:
</span><span class="cx">                                 subfilter.append(&quot;(%s=%s)&quot; % (ldapField, ldapEsc(email)))
</span><span class="cx">                         if not subfilter:
</span><del>-                            continue # No LDAP attribute assigned for emailAddresses
</del><ins>+                            continue  # No LDAP attribute assigned for emailAddresses
</ins><span class="cx"> 
</span><span class="cx">                         subfilter = &quot;(|%s)&quot; % (&quot;&quot;.join(subfilter))
</span><span class="cx">                     filterstr = &quot;(&amp;%s%s)&quot; % (filterstr, subfilter)
</span><span class="lines">@@ -1058,9 +1110,11 @@
</span><span class="cx"> 
</span><span class="cx">             # Query the LDAP server
</span><span class="cx">             self.log.debug(&quot;Retrieving ldap record with base %s and filter %s.&quot; %
</span><del>-                (ldap.dn.dn2str(base), filterstr))
</del><ins>+                           (ldap.dn.dn2str(base), filterstr))
</ins><span class="cx">             result = queryMethod(ldap.dn.dn2str(base),
</span><del>-                ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.attrlist)
</del><ins>+                                 ldap.SCOPE_SUBTREE,
+                                 filterstr=filterstr,
+                                 attrlist=self.attrlist)
</ins><span class="cx"> 
</span><span class="cx">             if result:
</span><span class="cx">                 dn, attrs = result.pop()
</span><span class="lines">@@ -1079,20 +1133,26 @@
</span><span class="cx"> 
</span><span class="cx">                     record.applySACLs()
</span><span class="cx"> 
</span><del>-                    self.recordCacheForType(recordType).addRecord(record,
-                        indexType, indexKey
</del><ins>+                    self.recordCacheForType(recordType).addRecord(
+                        record, indexType, indexKey
</ins><span class="cx">                     )
</span><span class="cx"> 
</span><span class="cx">                     # We got a match, so don't bother checking other types
</span><span class="cx">                     break
</span><span class="cx"> 
</span><span class="cx">                 except MissingRecordNameException:
</span><del>-                    self.log.warn(&quot;Ignoring record missing record name attribute: recordType %s, indexType %s and indexKey %s&quot;
-                        % (recordTypes, indexType, indexKey))
</del><ins>+                    self.log.warn(
+                        &quot;Ignoring record missing record name &quot;
+                        &quot;attribute: recordType %s, indexType %s and indexKey %s&quot;
+                        % (recordTypes, indexType, indexKey)
+                    )
</ins><span class="cx"> 
</span><span class="cx">                 except MissingGuidException:
</span><del>-                    self.log.warn(&quot;Ignoring record missing guid attribute: recordType %s, indexType %s and indexKey %s&quot;
-                        % (recordTypes, indexType, indexKey))
</del><ins>+                    self.log.warn(
+                        &quot;Ignoring record missing guid attribute: &quot;
+                        &quot;recordType %s, indexType %s and indexKey %s&quot;
+                        % (recordTypes, indexType, indexKey)
+                    )
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def recordsMatchingTokens(self, tokens, context=None, limitResults=50, timeoutSeconds=10):
</span><span class="lines">@@ -1131,17 +1191,27 @@
</span><span class="cx">             base = self.typeDNs[recordType]
</span><span class="cx">             scope = ldap.SCOPE_SUBTREE
</span><span class="cx">             extraFilter = self.rdnSchema[recordType].get(&quot;filter&quot;, &quot;&quot;)
</span><del>-            filterstr = buildFilterFromTokens(recordType, self.rdnSchema[recordType][&quot;mapping&quot;],
-                tokens, extra=extraFilter)
</del><ins>+            filterstr = buildFilterFromTokens(
+                recordType,
+                self.rdnSchema[recordType][&quot;mapping&quot;],
+                tokens,
+                extra=extraFilter
+            )
</ins><span class="cx"> 
</span><span class="cx">             if filterstr is not None:
</span><span class="cx">                 # Query the LDAP server
</span><del>-                self.log.debug(&quot;LDAP search %s %s (limit=%d)&quot; %
-                    (ldap.dn.dn2str(base), filterstr, limitResults))
-                results = self.timedSearch(ldap.dn.dn2str(base), scope,
-                    filterstr=filterstr, attrlist=self.attrlist,
</del><ins>+                self.log.debug(
+                    &quot;LDAP search %s %s (limit=%d)&quot; %
+                    (ldap.dn.dn2str(base), filterstr, limitResults)
+                )
+                results = self.timedSearch(
+                    ldap.dn.dn2str(base),
+                    scope,
+                    filterstr=filterstr,
+                    attrlist=self.attrlist,
</ins><span class="cx">                     timeoutSeconds=timeoutSeconds,
</span><del>-                    resultLimit=limitResults)
</del><ins>+                    resultLimit=limitResults
+                )
</ins><span class="cx">                 numMissingGuids = 0
</span><span class="cx">                 numMissingRecordNames = 0
</span><span class="cx">                 numNotEnabled = 0
</span><span class="lines">@@ -1149,8 +1219,10 @@
</span><span class="cx">                     dn = normalizeDNstr(dn)
</span><span class="cx">                     # Skip if group restriction is in place and guid is not
</span><span class="cx">                     # a member
</span><del>-                    if (recordType != self.recordType_groups and
-                        not self.isAllowedByRestrictToGroup(dn, attrs)):
</del><ins>+                    if (
+                            recordType != self.recordType_groups and
+                            not self.isAllowedByRestrictToGroup(dn, attrs)
+                    ):
</ins><span class="cx">                         continue
</span><span class="cx"> 
</span><span class="cx">                     try:
</span><span class="lines">@@ -1219,19 +1291,27 @@
</span><span class="cx"> 
</span><span class="cx">             else:
</span><span class="cx">                 scope = ldap.SCOPE_SUBTREE
</span><del>-                filterstr = buildFilter(recordType,
</del><ins>+                filterstr = buildFilter(
+                    recordType,
</ins><span class="cx">                     self.rdnSchema[recordType][&quot;mapping&quot;],
</span><del>-                    fields, operand=operand,
-                    optimizeMultiName=self.optimizeMultiName)
</del><ins>+                    fields,
+                    operand=operand,
+                    optimizeMultiName=self.optimizeMultiName
+                )
</ins><span class="cx"> 
</span><span class="cx">             if filterstr is not None:
</span><span class="cx">                 # Query the LDAP server
</span><span class="cx">                 self.log.debug(&quot;LDAP search %s %s %s&quot; %
</span><del>-                    (ldap.dn.dn2str(base), scope, filterstr))
-                results = (yield deferToThread(self.timedSearch, ldap.dn.dn2str(base), scope,
-                    filterstr=filterstr, attrlist=self.attrlist,
</del><ins>+                               (ldap.dn.dn2str(base), scope, filterstr))
+                results = (yield deferToThread(
+                    self.timedSearch,
+                    ldap.dn.dn2str(base),
+                    scope,
+                    filterstr=filterstr,
+                    attrlist=self.attrlist,
</ins><span class="cx">                     timeoutSeconds=self.requestTimeoutSeconds,
</span><del>-                    resultLimit=self.requestResultsLimit))
</del><ins>+                    resultLimit=self.requestResultsLimit)
+                )
</ins><span class="cx">                 self.log.debug(&quot;LDAP search returned %d results&quot; % (len(results),))
</span><span class="cx">                 numMissingGuids = 0
</span><span class="cx">                 numMissingRecordNames = 0
</span><span class="lines">@@ -1239,8 +1319,10 @@
</span><span class="cx">                     dn = normalizeDNstr(dn)
</span><span class="cx">                     # Skip if group restriction is in place and guid is not
</span><span class="cx">                     # a member
</span><del>-                    if (recordType != self.recordType_groups and
-                        not self.isAllowedByRestrictToGroup(dn, attrs)):
</del><ins>+                    if (
+                        recordType != self.recordType_groups and
+                        not self.isAllowedByRestrictToGroup(dn, attrs)
+                    ):
</ins><span class="cx">                         continue
</span><span class="cx"> 
</span><span class="cx">                     try:
</span><span class="lines">@@ -1262,11 +1344,11 @@
</span><span class="cx"> 
</span><span class="cx">                 if numMissingGuids:
</span><span class="cx">                     self.log.warn(&quot;%d %s records are missing %s&quot; %
</span><del>-                        (numMissingGuids, recordType, guidAttr))
</del><ins>+                                  (numMissingGuids, recordType, guidAttr))
</ins><span class="cx"> 
</span><span class="cx">                 if numMissingRecordNames:
</span><span class="cx">                     self.log.warn(&quot;%d %s records are missing record name&quot; %
</span><del>-                        (numMissingRecordNames, recordType))
</del><ins>+                                  (numMissingRecordNames, recordType))
</ins><span class="cx"> 
</span><span class="cx">         self.log.debug(&quot;Principal property search matched %d records&quot; % (len(records),))
</span><span class="cx">         returnValue(records)
</span><span class="lines">@@ -1300,16 +1382,24 @@
</span><span class="cx">                 # recordsMatchingFields for *each* DN.
</span><span class="cx">                 for value in valuesToFetch:
</span><span class="cx">                     fields = [[&quot;dn&quot;, value, False, &quot;equals&quot;]]
</span><del>-                    result = (yield self.recordsMatchingFields(fields,
-                        recordType=self.recordType_groups))
</del><ins>+                    result = (
+                        yield self.recordsMatchingFields(
+                            fields,
+                            recordType=self.recordType_groups
+                        )
+                    )
</ins><span class="cx">                     results.extend(result)
</span><span class="cx">             else:
</span><span class="cx">                 for batch in splitIntoBatches(valuesToFetch, self.batchSize):
</span><span class="cx">                     fields = []
</span><span class="cx">                     for value in batch:
</span><span class="cx">                         fields.append([attributeToSearch, value, False, &quot;equals&quot;])
</span><del>-                    result = (yield self.recordsMatchingFields(fields,
-                        recordType=self.recordType_groups))
</del><ins>+                    result = (
+                        yield self.recordsMatchingFields(
+                            fields,
+                            recordType=self.recordType_groups
+                        )
+                    )
</ins><span class="cx">                     results.extend(result)
</span><span class="cx"> 
</span><span class="cx">             # Reset values for next iteration
</span><span class="lines">@@ -1329,7 +1419,7 @@
</span><span class="cx">                         # cut:  we know we only need to examine groups, and
</span><span class="cx">                         # those will be children of the groups DN
</span><span class="cx">                         if not dnContainedIn(ldap.dn.str2dn(memberAlias),
</span><del>-                            groupsDN):
</del><ins>+                                             groupsDN):
</ins><span class="cx">                             continue
</span><span class="cx">                     if memberAlias not in recordsByAlias:
</span><span class="cx">                         valuesToFetch.add(memberAlias)
</span><span class="lines">@@ -1351,7 +1441,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         dn = ldap.dn.str2dn(dnStr.lower())
</span><span class="cx">         for recordType in self.recordTypes():
</span><del>-            base = self.typeDNs[recordType] # already lowercase
</del><ins>+            base = self.typeDNs[recordType]  # already lowercase
</ins><span class="cx">             if dnContainedIn(dn, base):
</span><span class="cx">                 return recordType
</span><span class="cx">         return None
</span><span class="lines">@@ -1431,7 +1521,8 @@
</span><span class="cx">                             if firstName != lastName:
</span><span class="cx">                                 firstValue = _convertValue(firstName, firstMatchType)
</span><span class="cx">                                 lastValue = _convertValue(lastName, lastMatchType)
</span><del>-                                converted.append(&quot;(&amp;(%s=%s)(%s=%s))&quot; %
</del><ins>+                                converted.append(
+                                    &quot;(&amp;(%s=%s)(%s=%s))&quot; %
</ins><span class="cx">                                     (mapping[&quot;firstName&quot;], firstValue,
</span><span class="cx">                                      mapping[&quot;lastName&quot;], lastValue)
</span><span class="cx">                                 )
</span><span class="lines">@@ -1575,8 +1666,10 @@
</span><span class="cx">         # Identifier of this record as a group member
</span><span class="cx">         memberIdAttr = self.service.groupSchema[&quot;memberIdAttr&quot;]
</span><span class="cx">         if memberIdAttr:
</span><del>-            self._memberId = self.service._getUniqueLdapAttribute(attrs,
-                memberIdAttr)
</del><ins>+            self._memberId = self.service._getUniqueLdapAttribute(
+                attrs,
+                memberIdAttr
+            )
</ins><span class="cx">         else:
</span><span class="cx">             self._memberId = normalizeDNstr(self.dn)
</span><span class="cx"> 
</span><span class="lines">@@ -1604,18 +1697,23 @@
</span><span class="cx">                 base = self.service.base
</span><span class="cx">                 filterstr = &quot;(%s=%s)&quot; % (memberIdAttr, ldapEsc(memberId))
</span><span class="cx">                 self.log.debug(&quot;Retrieving subtree of %s with filter %s&quot; %
</span><del>-                    (ldap.dn.dn2str(base), filterstr),
-                    system=&quot;LdapDirectoryService&quot;)
-                result = self.service.timedSearch(ldap.dn.dn2str(base),
-                    ldap.SCOPE_SUBTREE, filterstr=filterstr,
-                    attrlist=self.service.attrlist)
</del><ins>+                               (ldap.dn.dn2str(base), filterstr),
+                               system=&quot;LdapDirectoryService&quot;)
+                result = self.service.timedSearch(
+                    ldap.dn.dn2str(base),
+                    ldap.SCOPE_SUBTREE,
+                    filterstr=filterstr,
+                    attrlist=self.service.attrlist
+                )
</ins><span class="cx"> 
</span><del>-            else: # using DN
</del><ins>+            else:  # using DN
</ins><span class="cx"> 
</span><span class="cx">                 self.log.debug(&quot;Retrieving %s.&quot; % memberId,
</span><del>-                    system=&quot;LdapDirectoryService&quot;)
-                result = self.service.timedSearch(memberId,
-                    ldap.SCOPE_BASE, attrlist=self.service.attrlist)
</del><ins>+                               system=&quot;LdapDirectoryService&quot;)
+                result = self.service.timedSearch(
+                    memberId,
+                    ldap.SCOPE_BASE, attrlist=self.service.attrlist
+                )
</ins><span class="cx"> 
</span><span class="cx">             if result:
</span><span class="cx"> 
</span><span class="lines">@@ -1627,12 +1725,16 @@
</span><span class="cx">                     self.log.error(&quot;Unable to map %s to a record type&quot; % (dn,))
</span><span class="cx">                     continue
</span><span class="cx"> 
</span><del>-                shortName = self.service._getUniqueLdapAttribute(attrs,
-                    self.service.rdnSchema[recordType][&quot;mapping&quot;][&quot;recordName&quot;])
</del><ins>+                shortName = self.service._getUniqueLdapAttribute(
+                    attrs,
+                    self.service.rdnSchema[recordType][&quot;mapping&quot;][&quot;recordName&quot;]
+                )
</ins><span class="cx"> 
</span><span class="cx">                 if shortName:
</span><del>-                    record = self.service.recordWithShortName(recordType,
-                        shortName)
</del><ins>+                    record = self.service.recordWithShortName(
+                        recordType,
+                        shortName
+                    )
</ins><span class="cx">                     if record:
</span><span class="cx">                         results.append(record)
</span><span class="cx"> 
</span><span class="lines">@@ -1663,7 +1765,8 @@
</span><span class="cx">         if len(membersAttrs) == 1:
</span><span class="cx">             filterstr = &quot;(%s=%s)&quot; % (membersAttrs[0], self._memberId)
</span><span class="cx">         else:
</span><del>-            filterstr = &quot;(|%s)&quot; % (&quot;&quot;.join(
</del><ins>+            filterstr = &quot;(|%s)&quot; % (
+                &quot;&quot;.join(
</ins><span class="cx">                     [&quot;(%s=%s)&quot; % (a, self._memberId) for a in membersAttrs]
</span><span class="cx">                 ),
</span><span class="cx">             )
</span><span class="lines">@@ -1671,8 +1774,12 @@
</span><span class="cx">         groups = []
</span><span class="cx"> 
</span><span class="cx">         try:
</span><del>-            results = self.service.timedSearch(ldap.dn.dn2str(base),
-                ldap.SCOPE_SUBTREE, filterstr=filterstr, attrlist=self.service.attrlist)
</del><ins>+            results = self.service.timedSearch(
+                ldap.dn.dn2str(base),
+                ldap.SCOPE_SUBTREE,
+                filterstr=filterstr,
+                attrlist=self.service.attrlist
+            )
</ins><span class="cx"> 
</span><span class="cx">             for dn, attrs in results:
</span><span class="cx">                 dn = normalizeDNstr(dn)
</span><span class="lines">@@ -1753,12 +1860,13 @@
</span><span class="cx"> 
</span><span class="cx">                 except ldap.INVALID_CREDENTIALS:
</span><span class="cx">                     self.log.info(&quot;Invalid credentials for {dn}&quot;,
</span><del>-                        dn=repr(self.dn), system=&quot;LdapDirectoryService&quot;)
</del><ins>+                                  dn=repr(self.dn),
+                                  system=&quot;LdapDirectoryService&quot;)
</ins><span class="cx">                     return False
</span><span class="cx"> 
</span><span class="cx">             else:
</span><span class="cx">                 self.log.error(&quot;Unknown Authentication Method '{method}'&quot;,
</span><del>-                    method=self.service.authMethod.upper())
</del><ins>+                               method=self.service.authMethod.upper())
</ins><span class="cx">                 raise DirectoryConfigurationError()
</span><span class="cx"> 
</span><span class="cx">         return super(LdapDirectoryRecord, self).verifyCredentials(credentials)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectorytesttest_ldapdirectorypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py (12255 => 12256)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py        2014-01-07 18:34:58 UTC (rev 12255)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_ldapdirectory.py        2014-01-07 19:53:20 UTC (rev 12256)
</span><span class="lines">@@ -1270,6 +1270,7 @@
</span><span class="cx">             }
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">         def setupService(self, scenario):
</span><span class="cx">             self.service = LdapDirectoryService(scenario[1])
</span><span class="cx">             self.service.ldap = LdapDirectoryTestWrapper(self.service.ldap, scenario[0])
</span></span></pre>
</div>
</div>

</body>
</html>