)]}'
{"keystone/common/ldap/core.py":[{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"14637744cc0c10d342ce06828f24ebc554f7238e","unresolved":false,"context_lines":[{"line_number":479,"context_line":"            raise self._not_found(object_id)"},{"line_number":480,"context_line":"        except ldap.NOT_ALLOWED_ON_NONLEAF:"},{"line_number":481,"context_line":"            # few ldap servers support the tree_delete_control"},{"line_number":482,"context_line":"            # so have to do a search then delete in reverse order"},{"line_number":483,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(objectclass\u003d*)\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAU3%2F%2F9FU%3D","line":482,"updated":"2014-02-23 16:00:04.000000000","message":"why would delete in reverse order give the right results? Does the LDAP specification say what order entries are returned in?","commit_id":"bfbe0120bf2002fe0cc70053ced3a6f9801d1fff"},{"author":{"_account_id":2218,"name":"Adam Young","email":"adam@younglogic.com","username":"ayoung"},"change_message_id":"726f3303259410c1067c6d4c6f26471893a6edeb","unresolved":false,"context_lines":[{"line_number":479,"context_line":"            raise self._not_found(object_id)"},{"line_number":480,"context_line":"        except ldap.NOT_ALLOWED_ON_NONLEAF:"},{"line_number":481,"context_line":"            # few ldap servers support the tree_delete_control"},{"line_number":482,"context_line":"            # so have to do a search then delete in reverse order"},{"line_number":483,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(objectclass\u003d*)\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAU3%2F%2F1CI%3D","line":482,"in_reply_to":"AAAAU3%2F%2F9FU%3D","updated":"2014-02-24 16:00:41.000000000","message":"Note that this code was run using live tests on such a server, so we know it works.  I suspect that it is ude to walking the tree in either inorder or postorder,  in which case reversing the flattened view is a valid tree operation.","commit_id":"bfbe0120bf2002fe0cc70053ced3a6f9801d1fff"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"14637744cc0c10d342ce06828f24ebc554f7238e","unresolved":false,"context_lines":[{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(objectclass\u003d*)\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            # entries should not be None here - if we did not hit"},{"line_number":488,"context_line":"            # ldap.NO_SUCH_OBJECT, that means there is an entry"},{"line_number":489,"context_line":"            # which should be returned in entries"},{"line_number":490,"context_line":"            entries.reverse()"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAU3%2F%2F9FM%3D","line":487,"updated":"2014-02-23 16:00:04.000000000","message":"this comment seems pretty obvious since it just describes how search_s works. Suggest remove it.","commit_id":"bfbe0120bf2002fe0cc70053ced3a6f9801d1fff"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"3f93e2fbaa0e9d7c5ea5465ed41c726a7fb026e2","unresolved":false,"context_lines":[{"line_number":482,"context_line":"            # so have to do a search then delete in reverse order"},{"line_number":483,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAU3%2F%2FuKI%3D","line":485,"updated":"2014-02-25 04:13:00.000000000","message":"filter seem redundant\n\nthe first part \u0027objectclass\u003d*\u0027 will match any objectclass so the second part \u0027objectclass\u003dldapsubentry\u0027 is redundant","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"8131eaefe5237d7e831c26cb2a7d64be79c50589","unresolved":false,"context_lines":[{"line_number":482,"context_line":"            # so have to do a search then delete in reverse order"},{"line_number":483,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAU3%2F%2Foyw%3D","line":485,"in_reply_to":"AAAAU3%2F%2FuKI%3D","updated":"2014-08-15 15:41:51.000000000","message":"In some directory servers, entries with objectclass: ldapsubentry are hidden from LDAP search operations.  In order to request these entries, you have to explicitly request them by having the (objectclass\u003dldapsubentry) as part of the search filter.\nIf they are present, and you do not request them, the delete will fail with NOT_ALLOWED_ON_NONLEAF.","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":9098,"name":"Nathan Kinder","email":"nkinder@redhat.com","username":"nkinder"},"change_message_id":"4d3b0cedd9fcbe3843e47962c3cf11bd62c8ca35","unresolved":false,"context_lines":[{"line_number":482,"context_line":"            # so have to do a search then delete in reverse order"},{"line_number":483,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAXX%2F%2F3hw%3D","line":485,"in_reply_to":"AAAAU3%2F%2FuKI%3D","updated":"2014-04-25 17:04:57.000000000","message":"The \u0027ldapsubentry\u0027 objectclass is used to flag entries as operational.  As with operational attributes, an \u0027ldapsubentry\u0027 will not be returned unless you specifically ask for it.  If we only use \u0027objectclass\u003d*\u0027 here, the subentries will be left behind, causing deletion of the non-leaf entry to fail since it will still have children.","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"3f93e2fbaa0e9d7c5ea5465ed41c726a7fb026e2","unresolved":false,"context_lines":[{"line_number":483,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"},{"line_number":489,"context_line":"                for dn, _ in entries:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAU3%2F%2FuCU%3D","line":486,"updated":"2014-02-25 04:13:00.000000000","message":"also, if I am looking at the right doc, (objectclass\u003d*) is already the default so no need to specify it. For efficiency, you don\u0027t want all the attributes back. In this case, all you care are the DNs. Maybe you can simplify this?\n\nentries \u003d conn.search_s(dn, scope, attrslist\u003d[\u0027dn\u0027], attrsonly\u003d1)","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"8131eaefe5237d7e831c26cb2a7d64be79c50589","unresolved":false,"context_lines":[{"line_number":483,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"},{"line_number":489,"context_line":"                for dn, _ in entries:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAU3%2F%2FoyI%3D","line":486,"in_reply_to":"AAAAU3%2F%2FuCU%3D","updated":"2014-08-15 15:41:51.000000000","message":"\u003e also, if I am looking at the right doc, (objectclass\u003d*) is already the default so no need to specify it.\n\nSee above.\n\n\u003e attrslist\u003d[\u0027dn\u0027]\n\n\u0027dn\u0027 isn\u0027t really an attribute.  The proper LDAP way to request that no attributes in the entry are returned is to specify the attribute \u00271.1\u0027 by OID.  This OID is guaranteed not to exist in any LDAP server.  It is a common idiom in the LDAP world.\n\n\u003e attrsonly\u003d1\n\nSince no attributes will be returned with \u00271.1\u0027, the attrsonly\u003d1 flag is a no-op and can be omitted.","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":9098,"name":"Nathan Kinder","email":"nkinder@redhat.com","username":"nkinder"},"change_message_id":"4d3b0cedd9fcbe3843e47962c3cf11bd62c8ca35","unresolved":false,"context_lines":[{"line_number":483,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":484,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"},{"line_number":489,"context_line":"                for dn, _ in entries:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAXX%2F%2F3kE%3D","line":486,"in_reply_to":"AAAAU3%2F%2FuCU%3D","updated":"2014-04-25 17:04:57.000000000","message":"Asking for the \u00271.1\u0027 attribute causes no attributes to be returned.  It\u0027s basically the opposite of \u0027*\u0027.  See section 4.5.1.8 of RFC 4511 for details:\n\n   noattrs \u003d %x31.2E.31 ; \"1.1\"","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"a2b80c08c27ef26fbc1869049cb4bf8145174845","unresolved":false,"context_lines":[{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"},{"line_number":489,"context_line":"                for dn, _ in entries:"},{"line_number":490,"context_line":"                    conn.delete_s(dn)"},{"line_number":491,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAVn%2F%2F%2B6U%3D","line":488,"updated":"2014-03-03 00:24:35.000000000","message":"The LDAP specification says that the results can come back in any order, see https://tools.ietf.org/html/rfc4511#section-4.5.2 .\n\n The SearchResultEntry and SearchResultReference messages\n   may come in any order.\n\nSo reversing the order of the entries returned doesn\u0027t make any difference.","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"205f09109a10ff8ca0909f255d164d8c4c71af2d","unresolved":false,"context_lines":[{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"},{"line_number":489,"context_line":"                for dn, _ in entries:"},{"line_number":490,"context_line":"                    conn.delete_s(dn)"},{"line_number":491,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAVn%2F%2Fbws%3D","line":488,"in_reply_to":"AAAAVn%2F%2F%2B6U%3D","updated":"2014-03-06 04:02:34.000000000","message":"Sorted the DNs by length, in decanding order should work fine. i.e. delete the ones with the longest DN first.","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"8131eaefe5237d7e831c26cb2a7d64be79c50589","unresolved":false,"context_lines":[{"line_number":485,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":486,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":487,"context_line":"            if entries:"},{"line_number":488,"context_line":"                entries.reverse()"},{"line_number":489,"context_line":"                for dn, _ in entries:"},{"line_number":490,"context_line":"                    conn.delete_s(dn)"},{"line_number":491,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAVn%2F%2F53g%3D","line":488,"in_reply_to":"AAAAVn%2F%2F%2B6U%3D","updated":"2014-08-15 15:41:51.000000000","message":"ok","commit_id":"18217417079e19dcd390ee1e55d2d772b121afdd"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"dd7577ebe8bb3b20e7405fc1c7fe597169a571d8","unresolved":false,"context_lines":[{"line_number":1029,"context_line":"        except ldap.NO_SUCH_OBJECT:"},{"line_number":1030,"context_line":"            raise self._not_found(object_id)"},{"line_number":1031,"context_line":"        except ldap.NOT_ALLOWED_ON_NONLEAF:"},{"line_number":1032,"context_line":"            # few ldap servers support the tree_delete_control"},{"line_number":1033,"context_line":"            # so have to do a search then delete in reverse order"},{"line_number":1034,"context_line":"            dn \u003d self._id_to_dn(object_id)"},{"line_number":1035,"context_line":"            scope \u003d ldap.SCOPE_SUBTREE"}],"source_content_type":"text/x-python","patch_set":4,"id":"7adec928_d7eedf8a","line":1032,"updated":"2014-05-23 15:57:41.000000000","message":"(nit) This makes it sounds like most LDAP servers don\u0027t support tree_delete_control, but the commit message makes me think the opposite. Should this be \u0027A few\u0027? or \u0027Most LDAP servers do not\u0027?\n\n(nit) Should this be LDAP instead of ldap?","commit_id":"b6be7cb2c8daf167e9bfb5a7cb892b2583c00c3d"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"dd7577ebe8bb3b20e7405fc1c7fe597169a571d8","unresolved":false,"context_lines":[{"line_number":1036,"context_line":"            filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":1037,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, [\u00271.1\u0027])"},{"line_number":1038,"context_line":"            if entries:"},{"line_number":1039,"context_line":"                entries.reverse()"},{"line_number":1040,"context_line":"                for dn, _ in entries:"},{"line_number":1041,"context_line":"                    conn.delete_s(dn)"},{"line_number":1042,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":4,"id":"7adec928_5a95963e","line":1039,"updated":"2014-05-23 15:57:41.000000000","message":"Does this work as intended? Brant had a comment and guang-yee has a solution in patchset 3, but I don\u0027t see a response to those. It may be as simple as:\n\n  for dn in reversed(sorted(e[0] for e in entries, key\u003dlen))","commit_id":"b6be7cb2c8daf167e9bfb5a7cb892b2583c00c3d"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"dd7577ebe8bb3b20e7405fc1c7fe597169a571d8","unresolved":false,"context_lines":[{"line_number":1040,"context_line":"                for dn, _ in entries:"},{"line_number":1041,"context_line":"                    conn.delete_s(dn)"},{"line_number":1042,"context_line":"            else:"},{"line_number":1043,"context_line":"                LOG.debug(_(\"No entries in LDAP subtree %s\") % dn)"},{"line_number":1044,"context_line":"        finally:"},{"line_number":1045,"context_line":"            conn.unbind_s()"},{"line_number":1046,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"7adec928_b7a5d348","line":1043,"updated":"2014-05-23 15:57:41.000000000","message":"Debug messages should not be translated.","commit_id":"b6be7cb2c8daf167e9bfb5a7cb892b2583c00c3d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"be7a5a8267c1caa129b8985c352a78e7fd094672","unresolved":false,"context_lines":[{"line_number":1200,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"},{"line_number":1201,"context_line":"                    conn.delete_s(dn)"},{"line_number":1202,"context_line":"            else:"},{"line_number":1203,"context_line":"                LOG.debug(\"No entries in LDAP subtree %s\" % dn)"},{"line_number":1204,"context_line":"        finally:"},{"line_number":1205,"context_line":"            conn.unbind_s()"},{"line_number":1206,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"1ae5cdf2_808a58bd","line":1203,"updated":"2014-06-02 18:26:35.000000000","message":"Please use \u0027,\u0027 instead of %, LOG is smart enough to handle that.\n\n    LOG.debug(\"No entries in LDAP subtree %s\", dn)","commit_id":"7e1a72c70b977ec1fbf859d3bccfb63f0e934ab4"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"caa1f044e6817fc491a50a50a45f100c628cff48","unresolved":false,"context_lines":[{"line_number":1200,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"},{"line_number":1201,"context_line":"                    conn.delete_s(dn)"},{"line_number":1202,"context_line":"            else:"},{"line_number":1203,"context_line":"                LOG.debug(\"No entries in LDAP subtree %s\", dn)"},{"line_number":1204,"context_line":"        finally:"},{"line_number":1205,"context_line":"            conn.unbind_s()"},{"line_number":1206,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"1ae5cdf2_285c4b25","line":1203,"updated":"2014-06-09 03:38:47.000000000","message":"can a test be added for this, stubbing out the conn.delete_ext_s() method and raising an ldap.NOT_ALLOWED_ON_NONLEAF error?","commit_id":"4d0c50c91ed8f64df733ea9f9f687a260dea178d"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"78d42afac72fd798288c42a50d86fced12294f2d","unresolved":false,"context_lines":[{"line_number":1534,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1535,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1536,"context_line":"            if entries:"},{"line_number":1537,"context_line":"                for dn in sorted([e[0] for e in entries],"},{"line_number":1538,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"},{"line_number":1539,"context_line":"                    conn.delete_s(dn)"},{"line_number":1540,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_40612d38","line":1537,"updated":"2014-08-20 16:05:39.000000000","message":"We can change this list comprehension into a generator expression and avoid creating the temporary list.","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"53d7cd5a894fc4c8e4c7a200b66fbab179da492d","unresolved":false,"context_lines":[{"line_number":1534,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1535,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1536,"context_line":"            if entries:"},{"line_number":1537,"context_line":"                for dn in sorted([e[0] for e in entries],"},{"line_number":1538,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"},{"line_number":1539,"context_line":"                    conn.delete_s(dn)"},{"line_number":1540,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_55a99b8e","line":1537,"in_reply_to":"1abeadc6_40612d38","updated":"2014-08-21 14:14:24.000000000","message":"Done","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"78d42afac72fd798288c42a50d86fced12294f2d","unresolved":false,"context_lines":[{"line_number":1538,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"},{"line_number":1539,"context_line":"                    conn.delete_s(dn)"},{"line_number":1540,"context_line":"            else:"},{"line_number":1541,"context_line":"                LOG.debug(\"No entries in LDAP subtree %s\", dn)"},{"line_number":1542,"context_line":"        finally:"},{"line_number":1543,"context_line":"            conn.unbind_s()"},{"line_number":1544,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_6099c91e","line":1541,"updated":"2014-08-20 16:05:39.000000000","message":"Should use single quotes here.","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"53d7cd5a894fc4c8e4c7a200b66fbab179da492d","unresolved":false,"context_lines":[{"line_number":1538,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"},{"line_number":1539,"context_line":"                    conn.delete_s(dn)"},{"line_number":1540,"context_line":"            else:"},{"line_number":1541,"context_line":"                LOG.debug(\"No entries in LDAP subtree %s\", dn)"},{"line_number":1542,"context_line":"        finally:"},{"line_number":1543,"context_line":"            conn.unbind_s()"},{"line_number":1544,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_b593cf59","line":1541,"in_reply_to":"1abeadc6_6099c91e","updated":"2014-08-21 14:14:24.000000000","message":"Done","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"5a7215d85bc76cb8f459c07ab9673817e6dcf991","unresolved":false,"context_lines":[{"line_number":1540,"context_line":"            # terms of both server and network resources to reduce the"},{"line_number":1541,"context_line":"            # amount of data returned to the minimum.  Since no attributes"},{"line_number":1542,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1543,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1544,"context_line":"            if entries:"},{"line_number":1545,"context_line":"                for dn in sorted((e[0] for e in entries),"},{"line_number":1546,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"}],"source_content_type":"text/x-python","patch_set":12,"id":"fa98f980_9a8b8367","line":1543,"updated":"2014-09-10 16:42:03.000000000","message":"just proposed https://review.openstack.org/#/c/120478/ to introduce a DN_ONLY constant so that you don\u0027t have to provide a verbose explanation, every time [1.1] is used.","commit_id":"28c805263e890e77affcc53ae073237840869e3d"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"08fb9dae3300725e05971f44a0d127a0036811fa","unresolved":false,"context_lines":[{"line_number":1540,"context_line":"            # terms of both server and network resources to reduce the"},{"line_number":1541,"context_line":"            # amount of data returned to the minimum.  Since no attributes"},{"line_number":1542,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1543,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1544,"context_line":"            if entries:"},{"line_number":1545,"context_line":"                for dn in sorted((e[0] for e in entries),"},{"line_number":1546,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"}],"source_content_type":"text/x-python","patch_set":12,"id":"fa98f980_9abf03aa","line":1543,"in_reply_to":"fa98f980_9a8b8367","updated":"2014-09-10 16:50:46.000000000","message":"Ok.  What should I do?\n1) Wait for 120478 to merge?\n2) Code my patch in such a way that if DN_ONLY is available, use it, otherwise, use [\u00271.1\u0027]?\n3) Change my code to use DN_ONLY, and specify that my commit has a dependency on 120478, and resubmit the patch for review?","commit_id":"28c805263e890e77affcc53ae073237840869e3d"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"685185b50323f4b3098565975854beed87de176f","unresolved":false,"context_lines":[{"line_number":1540,"context_line":"            # terms of both server and network resources to reduce the"},{"line_number":1541,"context_line":"            # amount of data returned to the minimum.  Since no attributes"},{"line_number":1542,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1543,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1544,"context_line":"            if entries:"},{"line_number":1545,"context_line":"                for dn in sorted((e[0] for e in entries),"},{"line_number":1546,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"}],"source_content_type":"text/x-python","patch_set":12,"id":"fa98f980_bd5e81e7","line":1543,"in_reply_to":"fa98f980_9abf03aa","updated":"2014-09-10 17:17:38.000000000","message":"You could rebase this patch on top of dolph\u0027s patch:\n\n  * Checkout that patch dolph made\n  * cherry-pick this patch on top\n  * submit to gerrit \n\nThose steps will make your patch depend on his and pass tests.","commit_id":"28c805263e890e77affcc53ae073237840869e3d"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"7e42c4b403070e6d61467d2c6531d40b49e4f71d","unresolved":false,"context_lines":[{"line_number":1540,"context_line":"            # terms of both server and network resources to reduce the"},{"line_number":1541,"context_line":"            # amount of data returned to the minimum.  Since no attributes"},{"line_number":1542,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1543,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1544,"context_line":"            if entries:"},{"line_number":1545,"context_line":"                for dn in sorted((e[0] for e in entries),"},{"line_number":1546,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"}],"source_content_type":"text/x-python","patch_set":12,"id":"fa98f980_2396ee94","line":1543,"in_reply_to":"fa98f980_bd5e81e7","updated":"2014-09-10 18:17:07.000000000","message":"Done","commit_id":"28c805263e890e77affcc53ae073237840869e3d"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"0213a70be61228998fc02c5e4b4aa7a2b61308ca","unresolved":false,"context_lines":[{"line_number":1540,"context_line":"            # terms of both server and network resources to reduce the"},{"line_number":1541,"context_line":"            # amount of data returned to the minimum.  Since no attributes"},{"line_number":1542,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1543,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1544,"context_line":"            if entries:"},{"line_number":1545,"context_line":"                for dn in sorted((e[0] for e in entries),"},{"line_number":1546,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"}],"source_content_type":"text/x-python","patch_set":12,"id":"fa98f980_e844c575","line":1543,"in_reply_to":"fa98f980_bd5e81e7","updated":"2014-09-10 18:11:33.000000000","message":"submit to gerrit using:\n\n  git-review --no-rebase\n\nto avoid rebasing the patch that is gating!","commit_id":"28c805263e890e77affcc53ae073237840869e3d"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"cb72b14acf960f972a9efb884b5866933d245792","unresolved":false,"context_lines":[{"line_number":1544,"context_line":"            # terms of both server and network resources to reduce the"},{"line_number":1545,"context_line":"            # amount of data returned to the minimum.  Since no attributes"},{"line_number":1546,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1547,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1548,"context_line":"            if entries:"},{"line_number":1549,"context_line":"                for dn in sorted((e[0] for e in entries),"},{"line_number":1550,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa98f980_846a16eb","line":1547,"updated":"2014-09-11 22:17:11.000000000","message":"the intent behind rebasing onto https://review.openstack.org/#/c/120478/ was to replace this attrlist with DN_ONLY and drop the redundant explanation","commit_id":"0ac8b35891a0514354d8f23c4249be6ab7e772b4"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"c0253b465c8bd6842581d36240352dab82923ead","unresolved":false,"context_lines":[{"line_number":1544,"context_line":"            # terms of both server and network resources to reduce the"},{"line_number":1545,"context_line":"            # amount of data returned to the minimum.  Since no attributes"},{"line_number":1546,"context_line":"            # will be returned, we do not have to specify attrsonly\u003d1."},{"line_number":1547,"context_line":"            entries \u003d conn.search_s(dn, scope, filt, attrlist\u003d[\u00271.1\u0027])"},{"line_number":1548,"context_line":"            if entries:"},{"line_number":1549,"context_line":"                for dn in sorted((e[0] for e in entries),"},{"line_number":1550,"context_line":"                                 key\u003dlen, reverse\u003dTrue):"}],"source_content_type":"text/x-python","patch_set":13,"id":"fa98f980_6750d432","line":1547,"in_reply_to":"fa98f980_846a16eb","updated":"2014-09-11 22:43:00.000000000","message":"Done","commit_id":"0ac8b35891a0514354d8f23c4249be6ab7e772b4"}],"keystone/tests/fakeldap.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"78d42afac72fd798288c42a50d86fced12294f2d","unresolved":false,"context_lines":[{"line_number":537,"context_line":""},{"line_number":538,"context_line":""},{"line_number":539,"context_line":"class FakeLdapNoSubtreeDelete(FakeLdap):"},{"line_number":540,"context_line":"    \u0027\u0027\u0027Same as FakeLdap except delete will throw the LDAP error"},{"line_number":541,"context_line":"    ldap.NOT_ALLOWED_ON_NONLEAF if there is an attempt to delete"},{"line_number":542,"context_line":"    an entry that has children."},{"line_number":543,"context_line":"    \u0027\u0027\u0027"}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_40192d87","line":540,"updated":"2014-08-20 16:05:39.000000000","message":"http://docs.openstack.org/developer/hacking/#docstrings\n\nAlso my convention \"\"\" is typically used instead of \u0027\u0027\u0027.","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5f59f0b3f91a4a79e6f99956d499de2bdc905cfd","unresolved":false,"context_lines":[{"line_number":537,"context_line":""},{"line_number":538,"context_line":""},{"line_number":539,"context_line":"class FakeLdapNoSubtreeDelete(FakeLdap):"},{"line_number":540,"context_line":"    \u0027\u0027\u0027Same as FakeLdap except delete will throw the LDAP error"},{"line_number":541,"context_line":"    ldap.NOT_ALLOWED_ON_NONLEAF if there is an attempt to delete"},{"line_number":542,"context_line":"    an entry that has children."},{"line_number":543,"context_line":"    \u0027\u0027\u0027"}],"source_content_type":"text/x-python","patch_set":11,"id":"1abeadc6_55fc3b72","line":540,"updated":"2014-08-21 14:16:03.000000000","message":"http://docs.openstack.org/developer/hacking/#docstrings\nAlso by convention \"\"\" is typically used instead of \u0027\u0027\u0027.","commit_id":"9eabf6a030c1cf65c6ce25f928d31999af631755"},{"author":{"_account_id":4,"name":"Dolph Mathews","email":"dolph.mathews@gmail.com","username":"dolph"},"change_message_id":"c829bf8d654fb8c6ec76f0a92ac6d4f4becb56b7","unresolved":false,"context_lines":[{"line_number":425,"context_line":"                raise ldap.NO_SUCH_OBJECT"},{"line_number":426,"context_line":"            results \u003d [(base, item_dict)]"},{"line_number":427,"context_line":"        elif scope \u003d\u003d ldap.SCOPE_SUBTREE:"},{"line_number":428,"context_line":"            # BAD - tests expect that the base entry does not exist!!!!"},{"line_number":429,"context_line":"            results \u003d []"},{"line_number":430,"context_line":"            try:"},{"line_number":431,"context_line":"                item_dict \u003d self.db[self.key(base)]"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa98f980_f37486d0","line":428,"updated":"2014-09-12 02:09:15.000000000","message":"i meant to mention in the previous review that this should be a formal FIXME (preferably in the tests rather than here?). it should also explain the cause of the expectation and the consequence(s).\n\nalternatively, correct the issue before this lands so we don\u0027t have to merge something so # BAD","commit_id":"2d06594377bedff92c5caff7db35f914cd7a8970"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"2f787666f07e31f47cfe74ca82846fa14be9946a","unresolved":false,"context_lines":[{"line_number":425,"context_line":"                raise ldap.NO_SUCH_OBJECT"},{"line_number":426,"context_line":"            results \u003d [(base, item_dict)]"},{"line_number":427,"context_line":"        elif scope \u003d\u003d ldap.SCOPE_SUBTREE:"},{"line_number":428,"context_line":"            # BAD - tests expect that the base entry does not exist!!!!"},{"line_number":429,"context_line":"            results \u003d []"},{"line_number":430,"context_line":"            try:"},{"line_number":431,"context_line":"                item_dict \u003d self.db[self.key(base)]"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa98f980_e6df5438","line":428,"in_reply_to":"fa98f980_f37486d0","updated":"2014-09-12 13:38:04.000000000","message":"Done","commit_id":"2d06594377bedff92c5caff7db35f914cd7a8970"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"1e51e60f160732fe4e145d18ac8b8d3c026219c1","unresolved":false,"context_lines":[{"line_number":425,"context_line":"                raise ldap.NO_SUCH_OBJECT"},{"line_number":426,"context_line":"            results \u003d [(base, item_dict)]"},{"line_number":427,"context_line":"        elif scope \u003d\u003d ldap.SCOPE_SUBTREE:"},{"line_number":428,"context_line":"            # FIXME - LDAP search with SUBTREE scope must return the base"},{"line_number":429,"context_line":"            # entry, but the code below does _not_.  Unfortunately, there are"},{"line_number":430,"context_line":"            # several tests that depend on this broken behavior, and fail"},{"line_number":431,"context_line":"            # when the base entry is returned in the search results.  The"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_8e921355","line":428,"updated":"2014-09-12 22:46:36.000000000","message":"reference the bug # 1368772 in the comment so we can find the code.","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"b617e1f3565d6a299c836ec82cc065360c34dad5","unresolved":false,"context_lines":[{"line_number":425,"context_line":"                raise ldap.NO_SUCH_OBJECT"},{"line_number":426,"context_line":"            results \u003d [(base, item_dict)]"},{"line_number":427,"context_line":"        elif scope \u003d\u003d ldap.SCOPE_SUBTREE:"},{"line_number":428,"context_line":"            # FIXME - LDAP search with SUBTREE scope must return the base"},{"line_number":429,"context_line":"            # entry, but the code below does _not_.  Unfortunately, there are"},{"line_number":430,"context_line":"            # several tests that depend on this broken behavior, and fail"},{"line_number":431,"context_line":"            # when the base entry is returned in the search results.  The"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_c9eb35a2","line":428,"in_reply_to":"fa98f980_8e921355","updated":"2014-09-12 23:20:15.000000000","message":"Done","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"1e51e60f160732fe4e145d18ac8b8d3c026219c1","unresolved":false,"context_lines":[{"line_number":436,"context_line":"                item_dict \u003d self.db[self.key(base)]"},{"line_number":437,"context_line":"                results.extend([(base, item_dict)])"},{"line_number":438,"context_line":"            except KeyError:"},{"line_number":439,"context_line":"                LOG.debug(\u0027search fail: dn not found for SCOPE_BASE\u0027)"},{"line_number":440,"context_line":"            extraresults \u003d [(k[len(self.__prefix):], v)"},{"line_number":441,"context_line":"                            for k, v in six.iteritems(self.db)"},{"line_number":442,"context_line":"                            if re.match(\u0027%s.*,%s\u0027 %"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_ce989b77","line":439,"updated":"2014-09-12 22:46:36.000000000","message":"this is subtree scope, not SCOPE_BASE.","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"b617e1f3565d6a299c836ec82cc065360c34dad5","unresolved":false,"context_lines":[{"line_number":436,"context_line":"                item_dict \u003d self.db[self.key(base)]"},{"line_number":437,"context_line":"                results.extend([(base, item_dict)])"},{"line_number":438,"context_line":"            except KeyError:"},{"line_number":439,"context_line":"                LOG.debug(\u0027search fail: dn not found for SCOPE_BASE\u0027)"},{"line_number":440,"context_line":"            extraresults \u003d [(k[len(self.__prefix):], v)"},{"line_number":441,"context_line":"                            for k, v in six.iteritems(self.db)"},{"line_number":442,"context_line":"                            if re.match(\u0027%s.*,%s\u0027 %"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_e92d59ff","line":439,"in_reply_to":"fa98f980_ce989b77","updated":"2014-09-12 23:20:15.000000000","message":"Done","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"}],"keystone/tests/test_backend_ldap.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"78d42afac72fd798288c42a50d86fced12294f2d","unresolved":false,"context_lines":[{"line_number":40,"context_line":""},{"line_number":41,"context_line":"CONF \u003d config.CONF"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"# test_deleteTree should only be run once, not run"},{"line_number":44,"context_line":"# by every subclass of BaseLDAPIdentity."},{"line_number":45,"context_line":"firsttime_test_deleteTree \u003d True"},{"line_number":46,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_fbf108ce","line":43,"updated":"2014-08-20 16:05:39.000000000","message":"Is there any reason it can\u0027t run more than once or that we can\u0027t put it in it\u0027s own test class so it only runs once?","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"53d7cd5a894fc4c8e4c7a200b66fbab179da492d","unresolved":false,"context_lines":[{"line_number":40,"context_line":""},{"line_number":41,"context_line":"CONF \u003d config.CONF"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"# test_deleteTree should only be run once, not run"},{"line_number":44,"context_line":"# by every subclass of BaseLDAPIdentity."},{"line_number":45,"context_line":"firsttime_test_deleteTree \u003d True"},{"line_number":46,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_75293736","line":43,"in_reply_to":"1abeadc6_8f8ee8ce","updated":"2014-08-21 14:14:24.000000000","message":"Since deleteTree wasn\u0027t about testing the LDAP backend and was really about testing specific LDAP functionality I moved the test to the unit tests.","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"76c282b95a3a40aa5d35433db4fa35beebe07e07","unresolved":false,"context_lines":[{"line_number":40,"context_line":""},{"line_number":41,"context_line":"CONF \u003d config.CONF"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"# test_deleteTree should only be run once, not run"},{"line_number":44,"context_line":"# by every subclass of BaseLDAPIdentity."},{"line_number":45,"context_line":"firsttime_test_deleteTree \u003d True"},{"line_number":46,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_8f8ee8ce","line":43,"in_reply_to":"1abeadc6_fbf108ce","updated":"2014-08-20 16:47:35.000000000","message":"It can be run more than once, however, it\u0027s a waste of time to do so.  Ideally, we could just add a simple unit test for the BaseLdap.deleteTree function, but I don\u0027t know how to do that.","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"78d42afac72fd798288c42a50d86fced12294f2d","unresolved":false,"context_lines":[{"line_number":799,"context_line":"        self.assertEqual(u\u0027100\u0027, result_unicode)"},{"line_number":800,"context_line":""},{"line_number":801,"context_line":"    def test_deleteTree(self):"},{"line_number":802,"context_line":"        \u0027\u0027\u0027Few LDAP servers support CONTROL_DELETETREE.  This test"},{"line_number":803,"context_line":"        exercises the alternate code paths in BaseLdap.deleteTree."},{"line_number":804,"context_line":"        \u0027\u0027\u0027"},{"line_number":805,"context_line":"        global firsttime_test_deleteTree"}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_7b589832","line":802,"updated":"2014-08-20 16:05:39.000000000","message":"Same things about this docstring.\n\nhttp://docs.openstack.org/developer/hacking/#docstrings","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"53d7cd5a894fc4c8e4c7a200b66fbab179da492d","unresolved":false,"context_lines":[{"line_number":799,"context_line":"        self.assertEqual(u\u0027100\u0027, result_unicode)"},{"line_number":800,"context_line":""},{"line_number":801,"context_line":"    def test_deleteTree(self):"},{"line_number":802,"context_line":"        \u0027\u0027\u0027Few LDAP servers support CONTROL_DELETETREE.  This test"},{"line_number":803,"context_line":"        exercises the alternate code paths in BaseLdap.deleteTree."},{"line_number":804,"context_line":"        \u0027\u0027\u0027"},{"line_number":805,"context_line":"        global firsttime_test_deleteTree"}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_d5176bec","line":802,"in_reply_to":"1abeadc6_7b589832","updated":"2014-08-21 14:14:24.000000000","message":"I fixed this in my version.","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"53d7cd5a894fc4c8e4c7a200b66fbab179da492d","unresolved":false,"context_lines":[{"line_number":822,"context_line":"            conn.add_s(dn, attrs)"},{"line_number":823,"context_line":"            return dn"},{"line_number":824,"context_line":""},{"line_number":825,"context_line":"        # create 3 entries like this:"},{"line_number":826,"context_line":"        # cn\u003dbase"},{"line_number":827,"context_line":"        # cn\u003dchild,cn\u003dbase"},{"line_number":828,"context_line":"        # cn\u003dgrandchild,cn\u003dchild,cn\u003dbase"}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_95a413a7","line":825,"updated":"2014-08-21 14:14:24.000000000","message":"I broke up the rest of this test into sections to identify what each part is doing.","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"53d7cd5a894fc4c8e4c7a200b66fbab179da492d","unresolved":false,"context_lines":[{"line_number":837,"context_line":"        self.assertEqual(len(entries), 3)"},{"line_number":838,"context_line":"        sort_ents \u003d sorted([e[0] for e in entries],"},{"line_number":839,"context_line":"                           key\u003dlen, reverse\u003dTrue)"},{"line_number":840,"context_line":"        self.assertEqual(sort_ents[0], grandchild_dn)"},{"line_number":841,"context_line":"        self.assertEqual(sort_ents[1], child_dn)"},{"line_number":842,"context_line":"        self.assertEqual(sort_ents[2], base_dn)"},{"line_number":843,"context_line":"        self.assertRaises(ldap.NOT_ALLOWED_ON_NONLEAF,"}],"source_content_type":"text/x-python","patch_set":9,"id":"1abeadc6_d5c12b30","line":840,"updated":"2014-08-21 14:14:24.000000000","message":"I had to reverse the order of the assertEqual args because the order should be (expected, observed).","commit_id":"9650093813157535be5f93f806e8f87a69d7268f"}],"keystone/tests/unit/common/test_ldap.py":[{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"1e51e60f160732fe4e145d18ac8b8d3c026219c1","unresolved":false,"context_lines":[{"line_number":220,"context_line":"        def create_entry(name, parent_dn\u003dNone):"},{"line_number":221,"context_line":"            if not parent_dn:"},{"line_number":222,"context_line":"                parent_dn \u003d tree_dn"},{"line_number":223,"context_line":"            dn \u003d \"%s\u003d%s,%s\" % (id_attr, name, parent_dn)"},{"line_number":224,"context_line":"            attrs \u003d [(\u0027objectclass\u0027, [objclass, \u0027ldapsubentry\u0027]),"},{"line_number":225,"context_line":"                     (id_attr, [name])]"},{"line_number":226,"context_line":"            conn.add_s(dn, attrs)"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_8965ade2","line":223,"updated":"2014-09-12 22:46:36.000000000","message":"use \u0027 for strings consistently.","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"b617e1f3565d6a299c836ec82cc065360c34dad5","unresolved":false,"context_lines":[{"line_number":220,"context_line":"        def create_entry(name, parent_dn\u003dNone):"},{"line_number":221,"context_line":"            if not parent_dn:"},{"line_number":222,"context_line":"                parent_dn \u003d tree_dn"},{"line_number":223,"context_line":"            dn \u003d \"%s\u003d%s,%s\" % (id_attr, name, parent_dn)"},{"line_number":224,"context_line":"            attrs \u003d [(\u0027objectclass\u0027, [objclass, \u0027ldapsubentry\u0027]),"},{"line_number":225,"context_line":"                     (id_attr, [name])]"},{"line_number":226,"context_line":"            conn.add_s(dn, attrs)"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_2934c148","line":223,"in_reply_to":"fa98f980_8965ade2","updated":"2014-09-12 23:20:15.000000000","message":"Done","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"1e51e60f160732fe4e145d18ac8b8d3c026219c1","unresolved":false,"context_lines":[{"line_number":231,"context_line":"        # cn\u003dchild,cn\u003dbase"},{"line_number":232,"context_line":"        # cn\u003dgrandchild,cn\u003dchild,cn\u003dbase"},{"line_number":233,"context_line":"        # then attempt to deleteTree(cn\u003dbase)"},{"line_number":234,"context_line":"        base_id \u003d \"base\""},{"line_number":235,"context_line":"        base_dn \u003d create_entry(base_id)"},{"line_number":236,"context_line":"        child_dn \u003d create_entry(\"child\", base_dn)"},{"line_number":237,"context_line":"        grandchild_dn \u003d create_entry(\"grandchild\", child_dn)"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_a960b1cf","line":234,"updated":"2014-09-12 22:46:36.000000000","message":"use \u0027 for strings consistently (applies throughout these changes)","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"b617e1f3565d6a299c836ec82cc065360c34dad5","unresolved":false,"context_lines":[{"line_number":231,"context_line":"        # cn\u003dchild,cn\u003dbase"},{"line_number":232,"context_line":"        # cn\u003dgrandchild,cn\u003dchild,cn\u003dbase"},{"line_number":233,"context_line":"        # then attempt to deleteTree(cn\u003dbase)"},{"line_number":234,"context_line":"        base_id \u003d \"base\""},{"line_number":235,"context_line":"        base_dn \u003d create_entry(base_id)"},{"line_number":236,"context_line":"        child_dn \u003d create_entry(\"child\", base_dn)"},{"line_number":237,"context_line":"        grandchild_dn \u003d create_entry(\"grandchild\", child_dn)"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_4937454d","line":234,"in_reply_to":"fa98f980_a960b1cf","updated":"2014-09-12 23:20:15.000000000","message":"Done","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"1e51e60f160732fe4e145d18ac8b8d3c026219c1","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        child_dn \u003d create_entry(\"child\", base_dn)"},{"line_number":237,"context_line":"        grandchild_dn \u003d create_entry(\"grandchild\", child_dn)"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        # verify that the three entries were created"},{"line_number":240,"context_line":"        scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":241,"context_line":"        filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":242,"context_line":"        entries \u003d conn.search_s(base_dn, scope, filt,"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_69b16946","line":239,"updated":"2014-09-12 22:46:36.000000000","message":"why wouldn\u0027t they be created?","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"b617e1f3565d6a299c836ec82cc065360c34dad5","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        child_dn \u003d create_entry(\"child\", base_dn)"},{"line_number":237,"context_line":"        grandchild_dn \u003d create_entry(\"grandchild\", child_dn)"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        # verify that the three entries were created"},{"line_number":240,"context_line":"        scope \u003d ldap.SCOPE_SUBTREE"},{"line_number":241,"context_line":"        filt \u003d \u0027(|(objectclass\u003d*)(objectclass\u003dldapsubentry))\u0027"},{"line_number":242,"context_line":"        entries \u003d conn.search_s(base_dn, scope, filt,"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_e91479a1","line":239,"in_reply_to":"fa98f980_69b16946","updated":"2014-09-12 23:20:15.000000000","message":"I don\u0027t know - perhaps some regression in FakeLdap?  As a developer, I would rather have the test blow up after adding the entries, then I know immediately that the problem was that the entries could not be created, rather than having the test blow up attempting to delete the entries because they are not there, and getting a different unexpected exception.","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"1e51e60f160732fe4e145d18ac8b8d3c026219c1","unresolved":false,"context_lines":[{"line_number":245,"context_line":"        sort_ents \u003d sorted([e[0] for e in entries], key\u003dlen, reverse\u003dTrue)"},{"line_number":246,"context_line":"        self.assertEqual(grandchild_dn, sort_ents[0])"},{"line_number":247,"context_line":"        self.assertEqual(child_dn, sort_ents[1])"},{"line_number":248,"context_line":"        self.assertEqual(base_dn, sort_ents[2])"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        # verify that a non-leaf node can\u0027t be deleted directly by the"},{"line_number":251,"context_line":"        # LDAP server"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_497e656b","line":248,"updated":"2014-09-12 22:46:36.000000000","message":"replace 244-248 with self.assertEqual([grandchild_dn, child_dn, base_dn], sort_ents)","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"},{"author":{"_account_id":9983,"name":"Richard Megginson","email":"rmeggins@redhat.com","username":"rmeggins"},"change_message_id":"b617e1f3565d6a299c836ec82cc065360c34dad5","unresolved":false,"context_lines":[{"line_number":245,"context_line":"        sort_ents \u003d sorted([e[0] for e in entries], key\u003dlen, reverse\u003dTrue)"},{"line_number":246,"context_line":"        self.assertEqual(grandchild_dn, sort_ents[0])"},{"line_number":247,"context_line":"        self.assertEqual(child_dn, sort_ents[1])"},{"line_number":248,"context_line":"        self.assertEqual(base_dn, sort_ents[2])"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"        # verify that a non-leaf node can\u0027t be deleted directly by the"},{"line_number":251,"context_line":"        # LDAP server"}],"source_content_type":"text/x-python","patch_set":15,"id":"fa98f980_0918ddd1","line":248,"in_reply_to":"fa98f980_497e656b","updated":"2014-09-12 23:20:15.000000000","message":"Done","commit_id":"bc29ea184f7f2aabce21619175fd4a2246002854"}]}
