)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"8eb6dfafc56f84d04cfb0a2fa0979996aaca4a4c","unresolved":false,"context_lines":[{"line_number":11,"context_line":"and DNs and escaping them. This process is rather error-prone so I"},{"line_number":12,"context_line":"decided to aggregate all necessary pieces in a separate module with"},{"line_number":13,"context_line":"clean interface."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"Change-Id: Iffdba2d650561d8ec3581a286be18b04b38a9028"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":12,"id":"5a890539_18d6cd27","line":14,"updated":"2014-12-01 19:55:25.000000000","message":"Can this be tied to a feature of blueprint?","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Peter Razumovsky \u003cprazumovsky@mirantis.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2014-12-25 18:14:03 +0300"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add a simple module to work with filters and DNs to LDAP backend"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"As I started to write new feature for LDAP backend I found out that I"},{"line_number":10,"context_line":"have to keep track of all little nasty things like formatting filters"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":13,"id":"3a961159_2a47f6bd","line":7,"updated":"2014-12-28 17:50:09.000000000","message":"The commit title should be shorter -- remove \"simple\" and \"to LDAP backend\"","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Peter Razumovsky \u003cprazumovsky@mirantis.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2014-12-25 18:14:03 +0300"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add a simple module to work with filters and DNs to LDAP backend"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"As I started to write new feature for LDAP backend I found out that I"},{"line_number":10,"context_line":"have to keep track of all little nasty things like formatting filters"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":13,"id":"3a961159_47f8f449","line":7,"in_reply_to":"3a961159_2a47f6bd","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"}],"keystone/assignment/backends/ldap.py":[{"author":{"_account_id":6282,"name":"Wu Wenxiang","email":"wu.wenxiang@algoblu.com","username":"wu-wenxiang"},"change_message_id":"c9b119d59d78c2d902d56d813c488b5f0f485315","unresolved":false,"context_lines":[{"line_number":606,"context_line":"    def list_project_roles_for_group(self, group_dn, project_subtree):"},{"line_number":607,"context_line":"        conn \u003d self.get_connection()"},{"line_number":608,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":609,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d group_dn))"},{"line_number":610,"context_line":"        try:"},{"line_number":611,"context_line":"            roles \u003d conn.search_s(project_subtree,"},{"line_number":612,"context_line":"                                  ldap.SCOPE_SUBTREE,"}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_30c275e9","line":609,"updated":"2014-08-28 15:24:05.000000000","message":"`\u0026` should be `And` here ?","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":13009,"name":"Peter Razumovsky","email":"prazumovsky@mirantis.com","username":"prazumovsky"},"change_message_id":"ff6e531b57017059f8fd9fa4592c991a6512f162","unresolved":false,"context_lines":[{"line_number":606,"context_line":"    def list_project_roles_for_group(self, group_dn, project_subtree):"},{"line_number":607,"context_line":"        conn \u003d self.get_connection()"},{"line_number":608,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":609,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d group_dn))"},{"line_number":610,"context_line":"        try:"},{"line_number":611,"context_line":"            roles \u003d conn.search_s(project_subtree,"},{"line_number":612,"context_line":"                                  ldap.SCOPE_SUBTREE,"}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_fe7b48f2","line":609,"in_reply_to":"1abeadc6_30c275e9","updated":"2014-08-29 10:12:51.000000000","message":"There is no mistake. \u0027And\u0027 is not overloaded operator. So I use \u0027\u0026\u0027 because of need to overload it.","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":617,"context_line":"        return res"},{"line_number":618,"context_line":""},{"line_number":619,"context_line":"    def list_global_roles_for_user(self, user_dn):"},{"line_number":620,"context_line":"        roles \u003d self.get_all(expr.Attr(self.member_attribute) \u003d\u003d user_dn)"},{"line_number":621,"context_line":"        return [UserRoleAssociation("},{"line_number":622,"context_line":"                role_dn\u003drole.dn,"},{"line_number":623,"context_line":"                user_dn\u003duser_dn) for role in roles]"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_8a7c6aed","line":620,"updated":"2014-12-28 17:50:09.000000000","message":"The name of this should be changed to FilterAttr, otherwise I find it confusing since LDAP uses attributes in other places too where it doesn\u0027t need to be escaped.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":617,"context_line":"        return res"},{"line_number":618,"context_line":""},{"line_number":619,"context_line":"    def list_global_roles_for_user(self, user_dn):"},{"line_number":620,"context_line":"        roles \u003d self.get_all(expr.Attr(self.member_attribute) \u003d\u003d user_dn)"},{"line_number":621,"context_line":"        return [UserRoleAssociation("},{"line_number":622,"context_line":"                role_dn\u003drole.dn,"},{"line_number":623,"context_line":"                user_dn\u003duser_dn) for role in roles]"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_674090a2","line":620,"in_reply_to":"3a961159_8a7c6aed","updated":"2015-01-16 20:40:24.000000000","message":"We use expr module only when we need proper escaping, and that\u0027s mostly only filters and DNs. If someone uses Attr where one doesn\u0027t need it, str(attr) would be just attr\u0027s name, no extra escaping. Besides, FilterAttr seems too long...","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":647,"context_line":"        return res"},{"line_number":648,"context_line":""},{"line_number":649,"context_line":"    def list_project_roles_for_group(self, group_dn, project_subtree):"},{"line_number":650,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":651,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d group_dn))"},{"line_number":652,"context_line":"        with self.get_connection() as conn:"},{"line_number":653,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_ea6a4e1a","line":650,"updated":"2014-12-28 17:50:09.000000000","message":"objectClass should be in the expr.Attr (or FilterAttr as I suggested) namespace so readers know what it is. So this should be expr.FilterAttr.objectClass.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":647,"context_line":"        return res"},{"line_number":648,"context_line":""},{"line_number":649,"context_line":"    def list_project_roles_for_group(self, group_dn, project_subtree):"},{"line_number":650,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":651,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d group_dn))"},{"line_number":652,"context_line":"        with self.get_connection() as conn:"},{"line_number":653,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_272128fc","line":650,"in_reply_to":"3a961159_ea6a4e1a","updated":"2015-01-16 20:40:24.000000000","message":"It\u0027s there to provide ANY and a shortcut for expr.Attr(\u0027objectClass\u0027). If we hide it in Attr (or FilterAttr), it looses purpose.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":227,"context_line":"            return self.role._id_to_dn(role_id)"},{"line_number":228,"context_line":"        else:"},{"line_number":229,"context_line":"            return six.text_type((self.role.id_attr, role_id) +"},{"line_number":230,"context_line":"                                 expr.DN(self.project._id_to_dn(tenant_id)))"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"    def add_role_to_user_and_project(self, user_id, tenant_id, role_id):"},{"line_number":233,"context_line":"        self.get_project(tenant_id)"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_58517561","line":230,"updated":"2015-01-21 16:56:12.000000000","message":"this this is a private method it should be able to be changed to always return an expr.DN rather than a string. I\u0027m also fine with it as is.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"253a03965c0005e4bd6b18ec6dc4b697432997f6","unresolved":false,"context_lines":[{"line_number":227,"context_line":"            return self.role._id_to_dn(role_id)"},{"line_number":228,"context_line":"        else:"},{"line_number":229,"context_line":"            return six.text_type((self.role.id_attr, role_id) +"},{"line_number":230,"context_line":"                                 expr.DN(self.project._id_to_dn(tenant_id)))"},{"line_number":231,"context_line":""},{"line_number":232,"context_line":"    def add_role_to_user_and_project(self, user_id, tenant_id, role_id):"},{"line_number":233,"context_line":"        self.get_project(tenant_id)"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_96c1dc82","line":230,"in_reply_to":"1a930d6b_58517561","updated":"2015-01-22 05:55:57.000000000","message":"If we change this to DN instance, we\u0027ll have to take special care of  them on driver level. I think this deserves separate discussion in separate CR.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"}],"keystone/common/ldap/core.py":[{"author":{"_account_id":6282,"name":"Wu Wenxiang","email":"wu.wenxiang@algoblu.com","username":"wu-wenxiang"},"change_message_id":"c9b119d59d78c2d902d56d813c488b5f0f485315","unresolved":false,"context_lines":[{"line_number":26,"context_line":"import six"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"from keystone.common.ldap import expr"},{"line_number":29,"context_line":"from keystone import exception"},{"line_number":30,"context_line":"from keystone.i18n import _"},{"line_number":31,"context_line":"from keystone.openstack.common import log"},{"line_number":32,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_b074c5cf","line":29,"updated":"2014-08-28 15:24:05.000000000","message":"from keystone.common.ldap import expr\nshould after:\nfrom keystone import exception","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":13009,"name":"Peter Razumovsky","email":"prazumovsky@mirantis.com","username":"prazumovsky"},"change_message_id":"173ce3857f710628ed76fe994626885c06d6730c","unresolved":false,"context_lines":[{"line_number":26,"context_line":"import six"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"from keystone.common.ldap import expr"},{"line_number":29,"context_line":"from keystone import exception"},{"line_number":30,"context_line":"from keystone.i18n import _"},{"line_number":31,"context_line":"from keystone.openstack.common import log"},{"line_number":32,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"fa98f980_0a25dac1","line":29,"in_reply_to":"1abeadc6_592296a3","updated":"2014-09-01 07:39:29.000000000","message":"Imports in alphabetical order.","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":13009,"name":"Peter Razumovsky","email":"prazumovsky@mirantis.com","username":"prazumovsky"},"change_message_id":"ff6e531b57017059f8fd9fa4592c991a6512f162","unresolved":false,"context_lines":[{"line_number":26,"context_line":"import six"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"from keystone.common.ldap import expr"},{"line_number":29,"context_line":"from keystone import exception"},{"line_number":30,"context_line":"from keystone.i18n import _"},{"line_number":31,"context_line":"from keystone.openstack.common import log"},{"line_number":32,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_592296a3","line":29,"in_reply_to":"1abeadc6_b074c5cf","updated":"2014-08-29 10:12:51.000000000","message":"Done","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":6282,"name":"Wu Wenxiang","email":"wu.wenxiang@algoblu.com","username":"wu-wenxiang"},"change_message_id":"c9b119d59d78c2d902d56d813c488b5f0f485315","unresolved":false,"context_lines":[{"line_number":1367,"context_line":"        conn \u003d self.get_connection()"},{"line_number":1368,"context_line":"        query \u003d ((expr.Attr(self.id_attr) \u003d\u003d object_id) \u0026"},{"line_number":1369,"context_line":"                 (ldap_filter or self.ldap_filter or \u0027\u0027) \u0026"},{"line_number":1370,"context_line":"                 (expr.objectClass \u003d\u003d self.object_class))"},{"line_number":1371,"context_line":"        try:"},{"line_number":1372,"context_line":"            attrs \u003d list(set((self.attribute_mapping.values() +"},{"line_number":1373,"context_line":"                              self.extra_attr_mapping.keys())))"}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_703dcddc","line":1370,"updated":"2014-08-28 15:24:05.000000000","message":"\u0026 -\u003e And","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":6282,"name":"Wu Wenxiang","email":"wu.wenxiang@algoblu.com","username":"wu-wenxiang"},"change_message_id":"c9b119d59d78c2d902d56d813c488b5f0f485315","unresolved":false,"context_lines":[{"line_number":1384,"context_line":"    def _ldap_get_all(self, ldap_filter\u003dNone):"},{"line_number":1385,"context_line":"        conn \u003d self.get_connection()"},{"line_number":1386,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":1387,"context_line":"                 (ldap_filter or self.ldap_filter or \u0027\u0027))"},{"line_number":1388,"context_line":"        try:"},{"line_number":1389,"context_line":"            attrs \u003d list(set((self.attribute_mapping.values() +"},{"line_number":1390,"context_line":"                              self.extra_attr_mapping.keys())))"}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_900c2944","line":1387,"updated":"2014-08-28 15:24:05.000000000","message":"Also here","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":6282,"name":"Wu Wenxiang","email":"wu.wenxiang@algoblu.com","username":"wu-wenxiang"},"change_message_id":"c9b119d59d78c2d902d56d813c488b5f0f485315","unresolved":false,"context_lines":[{"line_number":1403,"context_line":"        query \u003d expr.objectClass \u003d\u003d self.object_class"},{"line_number":1404,"context_line":"        if query_params:"},{"line_number":1405,"context_line":"            for k, v in six.iteritems(query_params):"},{"line_number":1406,"context_line":"                query \u0026\u003d expr.Attr(k) \u003d\u003d v"},{"line_number":1407,"context_line":"        try:"},{"line_number":1408,"context_line":"            return conn.search_s(search_base, scope, query, attrlist)"},{"line_number":1409,"context_line":"        finally:"}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_9313535b","line":1406,"updated":"2014-08-28 15:24:05.000000000","message":"use all() instead of \u0026\u003d","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":13009,"name":"Peter Razumovsky","email":"prazumovsky@mirantis.com","username":"prazumovsky"},"change_message_id":"ff6e531b57017059f8fd9fa4592c991a6512f162","unresolved":false,"context_lines":[{"line_number":1403,"context_line":"        query \u003d expr.objectClass \u003d\u003d self.object_class"},{"line_number":1404,"context_line":"        if query_params:"},{"line_number":1405,"context_line":"            for k, v in six.iteritems(query_params):"},{"line_number":1406,"context_line":"                query \u0026\u003d expr.Attr(k) \u003d\u003d v"},{"line_number":1407,"context_line":"        try:"},{"line_number":1408,"context_line":"            return conn.search_s(search_base, scope, query, attrlist)"},{"line_number":1409,"context_line":"        finally:"}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_590b7623","line":1406,"in_reply_to":"1abeadc6_9313535b","updated":"2014-08-29 10:12:51.000000000","message":"There is no need to use all() instead of \u0026\u003d. \u0027\u0026\u0027 is overloaded.","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":6282,"name":"Wu Wenxiang","email":"wu.wenxiang@algoblu.com","username":"wu-wenxiang"},"change_message_id":"c9b119d59d78c2d902d56d813c488b5f0f485315","unresolved":false,"context_lines":[{"line_number":1542,"context_line":"        query \u003d expr.objectClass \u003d\u003d self.object_class"},{"line_number":1543,"context_line":"        if query_params:"},{"line_number":1544,"context_line":"            for k, v in six.iteritems(query_params):"},{"line_number":1545,"context_line":"                query \u0026\u003d expr.Attr(k) \u003d\u003d v"},{"line_number":1546,"context_line":"        not_deleted_nodes \u003d []"},{"line_number":1547,"context_line":"        try:"},{"line_number":1548,"context_line":"            # RFC 4511 (The LDAP Protocol) defines a list containing only the"}],"source_content_type":"text/x-python","patch_set":1,"id":"1abeadc6_f3164748","line":1545,"updated":"2014-08-28 15:24:05.000000000","message":"Same here","commit_id":"0e7dffed7552c5bb6171675b6e52c831b88768b6"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fddcbcb08fb1dfb5ec9cf0ab0a13dd4ad335bcd9","unresolved":false,"context_lines":[{"line_number":1424,"context_line":""},{"line_number":1425,"context_line":"    def _ldap_get_all(self, ldap_filter\u003dNone):"},{"line_number":1426,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":1427,"context_line":"                 (ldap_filter or self.ldap_filter or \u0027\u0027))"},{"line_number":1428,"context_line":"        with self.get_connection() as conn:"},{"line_number":1429,"context_line":"            try:"},{"line_number":1430,"context_line":"                attrs \u003d list(set(([self.id_attr] +"}],"source_content_type":"text/x-python","patch_set":12,"id":"baa201ad_b9e49c0d","line":1427,"updated":"2014-10-16 00:40:01.000000000","message":"The \u0026 \u0027\u0027 possibility is confusing and should be unnecessary. It would make more sense to split it this up and only if ldap_filter or self.ldap_filter.\n\n query \u003d (expr.objectClass \u003d\u003d self.object_class)\n if ldap_filter or self.ldap_filter:\n    query \u0026\u003d ldap_filter or self.ldap_filter","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fddcbcb08fb1dfb5ec9cf0ab0a13dd4ad335bcd9","unresolved":false,"context_lines":[{"line_number":1595,"context_line":"        query \u003d expr.objectClass \u003d\u003d self.object_class"},{"line_number":1596,"context_line":"        if query_params:"},{"line_number":1597,"context_line":"            for k, v in six.iteritems(query_params):"},{"line_number":1598,"context_line":"                query \u0026\u003d expr.Attr(k) \u003d\u003d v"},{"line_number":1599,"context_line":"        not_deleted_nodes \u003d []"},{"line_number":1600,"context_line":"        with self.get_connection() as conn:"},{"line_number":1601,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":12,"id":"baa201ad_d99b2071","line":1598,"updated":"2014-10-16 00:40:01.000000000","message":"this happens a few times so seems like it could be a function.","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":932,"context_line":"        # attrlist is expected to be an iterable of strings."},{"line_number":933,"context_line":"        if attrlist is not None:"},{"line_number":934,"context_line":"            attrlist \u003d [attr for attr in attrlist if attr is not None]"},{"line_number":935,"context_line":"        filterstr \u003d six.text_type(filterstr)"},{"line_number":936,"context_line":"        LOG.debug(\u0027LDAP search: base\u003d%s scope\u003d%s filterstr\u003d%s \u0027"},{"line_number":937,"context_line":"                  \u0027attrs\u003d%s attrsonly\u003d%s\u0027,"},{"line_number":938,"context_line":"                  base, scope, filterstr, attrlist, attrsonly)"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_0a687a20","line":935,"updated":"2014-12-28 17:50:09.000000000","message":"this shouldn\u0027t be necessary, since the class should be convertable by itself.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":932,"context_line":"        # attrlist is expected to be an iterable of strings."},{"line_number":933,"context_line":"        if attrlist is not None:"},{"line_number":934,"context_line":"            attrlist \u003d [attr for attr in attrlist if attr is not None]"},{"line_number":935,"context_line":"        filterstr \u003d six.text_type(filterstr)"},{"line_number":936,"context_line":"        LOG.debug(\u0027LDAP search: base\u003d%s scope\u003d%s filterstr\u003d%s \u0027"},{"line_number":937,"context_line":"                  \u0027attrs\u003d%s attrsonly\u003d%s\u0027,"},{"line_number":938,"context_line":"                  base, scope, filterstr, attrlist, attrsonly)"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_cc532b14","line":935,"in_reply_to":"3a961159_0a687a20","updated":"2015-01-16 20:40:24.000000000","message":"utf8_encode method won\u0027t work otherwise. search_* methods are considered to be a border between object and string representations for filters.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":960,"context_line":"                   timeout\u003d-1, sizelimit\u003d0):"},{"line_number":961,"context_line":"        if attrlist is not None:"},{"line_number":962,"context_line":"            attrlist \u003d [attr for attr in attrlist if attr is not None]"},{"line_number":963,"context_line":"        filterstr \u003d six.text_type(filterstr)"},{"line_number":964,"context_line":"        LOG.debug(\u0027LDAP search_ext: base\u003d%s scope\u003d%s filterstr\u003d%s \u0027"},{"line_number":965,"context_line":"                  \u0027attrs\u003d%s attrsonly\u003d%s\u0027"},{"line_number":966,"context_line":"                  \u0027serverctrls\u003d%s clientctrls\u003d%s timeout\u003d%s sizelimit\u003d%s\u0027,"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_4a728212","line":963,"updated":"2014-12-28 17:50:09.000000000","message":"same here.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":1432,"context_line":"        return values"},{"line_number":1433,"context_line":""},{"line_number":1434,"context_line":"    def _ldap_get(self, object_id, ldap_filter\u003dNone):"},{"line_number":1435,"context_line":"        query \u003d ((expr.Attr(self.id_attr) \u003d\u003d object_id) \u0026"},{"line_number":1436,"context_line":"                 (ldap_filter or self.ldap_filter) \u0026"},{"line_number":1437,"context_line":"                 (expr.objectClass \u003d\u003d self.object_class))"},{"line_number":1438,"context_line":"        with self.get_connection() as conn:"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_ca5d927b","line":1435,"updated":"2014-12-28 17:50:09.000000000","message":"why isn\u0027t self.id_attr an expr.Attr already?","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":1432,"context_line":"        return values"},{"line_number":1433,"context_line":""},{"line_number":1434,"context_line":"    def _ldap_get(self, object_id, ldap_filter\u003dNone):"},{"line_number":1435,"context_line":"        query \u003d ((expr.Attr(self.id_attr) \u003d\u003d object_id) \u0026"},{"line_number":1436,"context_line":"                 (ldap_filter or self.ldap_filter) \u0026"},{"line_number":1437,"context_line":"                 (expr.objectClass \u003d\u003d self.object_class))"},{"line_number":1438,"context_line":"        with self.get_connection() as conn:"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_8c884323","line":1435,"in_reply_to":"3a961159_ca5d927b","updated":"2015-01-16 20:40:24.000000000","message":"There are exactly 50% places (7 out of 14) where id_attr is used as string and would require adding \".name\" or \"six.text_type(..)\" around it to make it work as Attr.\nAnd there are only 2 places where \"expr.Attr(self.id_attr)\" is needed. I think, that makes this choice obvious.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":1470,"context_line":"    def _build_query(self, query_params\u003dNone):"},{"line_number":1471,"context_line":"        query \u003d expr.objectClass \u003d\u003d self.object_class"},{"line_number":1472,"context_line":"        if query_params:"},{"line_number":1473,"context_line":"            for k, v in six.iteritems(query_params):"},{"line_number":1474,"context_line":"                query \u0026\u003d expr.Attr(k) \u003d\u003d v"},{"line_number":1475,"context_line":"        return query"},{"line_number":1476,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_cad4b2bf","line":1473,"updated":"2014-12-28 17:50:09.000000000","message":"query_params could be query_params or [] then could avoid the if statement.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":1470,"context_line":"    def _build_query(self, query_params\u003dNone):"},{"line_number":1471,"context_line":"        query \u003d expr.objectClass \u003d\u003d self.object_class"},{"line_number":1472,"context_line":"        if query_params:"},{"line_number":1473,"context_line":"            for k, v in six.iteritems(query_params):"},{"line_number":1474,"context_line":"                query \u0026\u003d expr.Attr(k) \u003d\u003d v"},{"line_number":1475,"context_line":"        return query"},{"line_number":1476,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_c795c432","line":1473,"in_reply_to":"3a961159_cad4b2bf","updated":"2015-01-16 20:40:24.000000000","message":"Made Junction handle query_params and FilterExpr ignore None\u0027s. That should do it.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":1488,"context_line":"            return self._ldap_res_to_model(res)"},{"line_number":1489,"context_line":""},{"line_number":1490,"context_line":"    def get_by_name(self, name, ldap_filter\u003dNone):"},{"line_number":1491,"context_line":"        query \u003d expr.Attr(self.attribute_mapping[\u0027name\u0027]) \u003d\u003d name"},{"line_number":1492,"context_line":"        res \u003d self.get_all(query)"},{"line_number":1493,"context_line":"        try:"},{"line_number":1494,"context_line":"            return res[0]"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_aae686ae","line":1491,"updated":"2014-12-28 17:50:09.000000000","message":"the expr module doesn\u0027t do six.text_type like the original code did, so I think name needs to be six.text_type(name).","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":1488,"context_line":"            return self._ldap_res_to_model(res)"},{"line_number":1489,"context_line":""},{"line_number":1490,"context_line":"    def get_by_name(self, name, ldap_filter\u003dNone):"},{"line_number":1491,"context_line":"        query \u003d expr.Attr(self.attribute_mapping[\u0027name\u0027]) \u003d\u003d name"},{"line_number":1492,"context_line":"        res \u003d self.get_all(query)"},{"line_number":1493,"context_line":"        try:"},{"line_number":1494,"context_line":"            return res[0]"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_87881c23","line":1491,"in_reply_to":"3a961159_aae686ae","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":1174,"context_line":"            self.id_attr \u003d getattr(conf.ldap, idatt) or self.DEFAULT_ID_ATTR"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"            objclass \u003d \u0027%s_objectclass\u0027 % self.options_name"},{"line_number":1177,"context_line":"            self.object_class \u003d (getattr(conf.ldap, objclass)"},{"line_number":1178,"context_line":"                                 or self.DEFAULT_OBJECTCLASS)"},{"line_number":1179,"context_line":"            self.object_class_expr \u003d expr.objectClass \u003d\u003d self.object_class"},{"line_number":1180,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_52231605","line":1177,"updated":"2015-01-21 16:56:12.000000000","message":"does object_class still need to be a member?","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"253a03965c0005e4bd6b18ec6dc4b697432997f6","unresolved":false,"context_lines":[{"line_number":1174,"context_line":"            self.id_attr \u003d getattr(conf.ldap, idatt) or self.DEFAULT_ID_ATTR"},{"line_number":1175,"context_line":""},{"line_number":1176,"context_line":"            objclass \u003d \u0027%s_objectclass\u0027 % self.options_name"},{"line_number":1177,"context_line":"            self.object_class \u003d (getattr(conf.ldap, objclass)"},{"line_number":1178,"context_line":"                                 or self.DEFAULT_OBJECTCLASS)"},{"line_number":1179,"context_line":"            self.object_class_expr \u003d expr.objectClass \u003d\u003d self.object_class"},{"line_number":1180,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_9b5bc553","line":1177,"in_reply_to":"1a930d6b_52231605","updated":"2015-01-22 05:55:57.000000000","message":"It\u0027s still used as is in several places, just like id_attr. We shouldn\u0027t make things more complex by making other things simpler.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":1435,"context_line":"    def _ldap_get(self, object_id, ldap_filter\u003dNone):"},{"line_number":1436,"context_line":"        query \u003d ((expr.Attr(self.id_attr) \u003d\u003d object_id) \u0026"},{"line_number":1437,"context_line":"                 (ldap_filter or self.ldap_filter) \u0026"},{"line_number":1438,"context_line":"                 self.object_class_expr)"},{"line_number":1439,"context_line":"        with self.get_connection() as conn:"},{"line_number":1440,"context_line":"            try:"},{"line_number":1441,"context_line":"                attrs \u003d list(set(([self.id_attr] +"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_92a73e4f","line":1438,"updated":"2015-01-21 16:56:12.000000000","message":"I think it\u0027s less confusing if we\u0027re explicit about adding the ldap_filter or self.ldap_filter only if they\u0027re set...\n\n ldap_filter \u003d ldap_filter or self.ldap_filter\n query \u003d ((expr.Attr(self.id_attr) \u003d\u003d object_id) \u0026\n                self.object_class_expr)\n if ldap_filter:\n     query \u0026\u003d ldap_filter\n\nOtherwise readers are left wondering what happens when you \u0026 a query with None... there\u0027s two ways it could work and they both make sense, either nothing matches or it\u0027s ignored.\n\nI\u0027m also fine with this as is... other reviewers might want it changed.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"253a03965c0005e4bd6b18ec6dc4b697432997f6","unresolved":false,"context_lines":[{"line_number":1435,"context_line":"    def _ldap_get(self, object_id, ldap_filter\u003dNone):"},{"line_number":1436,"context_line":"        query \u003d ((expr.Attr(self.id_attr) \u003d\u003d object_id) \u0026"},{"line_number":1437,"context_line":"                 (ldap_filter or self.ldap_filter) \u0026"},{"line_number":1438,"context_line":"                 self.object_class_expr)"},{"line_number":1439,"context_line":"        with self.get_connection() as conn:"},{"line_number":1440,"context_line":"            try:"},{"line_number":1441,"context_line":"                attrs \u003d list(set(([self.id_attr] +"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_f6ff80ff","line":1438,"in_reply_to":"1a930d6b_92a73e4f","updated":"2015-01-22 05:55:57.000000000","message":"In our context None as well as an empty string is a noop. We might want to document it.\n\nOn the other hand making this more explicit is good, I agree.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"35515f441ff31daa4c4765cbdddeaeda90b2443b","unresolved":false,"context_lines":[{"line_number":1435,"context_line":"    def _ldap_get(self, object_id, ldap_filter\u003dNone):"},{"line_number":1436,"context_line":"        query \u003d ((expr.Attr(self.id_attr) \u003d\u003d object_id) \u0026"},{"line_number":1437,"context_line":"                 (ldap_filter or self.ldap_filter) \u0026"},{"line_number":1438,"context_line":"                 self.object_class_expr)"},{"line_number":1439,"context_line":"        with self.get_connection() as conn:"},{"line_number":1440,"context_line":"            try:"},{"line_number":1441,"context_line":"                attrs \u003d list(set(([self.id_attr] +"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_d327c3b4","line":1438,"in_reply_to":"1a930d6b_f6ff80ff","updated":"2015-01-23 11:45:35.000000000","message":"Done","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":1453,"context_line":"            return None"},{"line_number":1454,"context_line":""},{"line_number":1455,"context_line":"    def _ldap_get_all(self, ldap_filter\u003dNone):"},{"line_number":1456,"context_line":"        query \u003d (self.object_class_expr \u0026 (ldap_filter or self.ldap_filter))"},{"line_number":1457,"context_line":"        with self.get_connection() as conn:"},{"line_number":1458,"context_line":"            try:"},{"line_number":1459,"context_line":"                attrs \u003d list(set(([self.id_attr] +"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_f2440276","line":1456,"updated":"2015-01-21 16:56:12.000000000","message":"same here:\n\n ldap_filter \u003d ldap_filter or self.ldap_filter\n query \u003d self.object_class_expr\n if ldap_filter:\n     query \u0026\u003d ldap_filter","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"35515f441ff31daa4c4765cbdddeaeda90b2443b","unresolved":false,"context_lines":[{"line_number":1453,"context_line":"            return None"},{"line_number":1454,"context_line":""},{"line_number":1455,"context_line":"    def _ldap_get_all(self, ldap_filter\u003dNone):"},{"line_number":1456,"context_line":"        query \u003d (self.object_class_expr \u0026 (ldap_filter or self.ldap_filter))"},{"line_number":1457,"context_line":"        with self.get_connection() as conn:"},{"line_number":1458,"context_line":"            try:"},{"line_number":1459,"context_line":"                attrs \u003d list(set(([self.id_attr] +"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_f32aff7c","line":1456,"in_reply_to":"1a930d6b_f2440276","updated":"2015-01-23 11:45:35.000000000","message":"Done","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":1468,"context_line":""},{"line_number":1469,"context_line":"    def _ldap_get_list(self, search_base, scope, query_params\u003dNone,"},{"line_number":1470,"context_line":"                       attrlist\u003dNone):"},{"line_number":1471,"context_line":"        query \u003d self.object_class_expr \u0026 query_params"},{"line_number":1472,"context_line":"        with self.get_connection() as conn:"},{"line_number":1473,"context_line":"            return conn.search_s(search_base, scope, query, attrlist)"},{"line_number":1474,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_951ac86c","line":1471,"updated":"2015-01-21 16:56:12.000000000","message":"same here:\n\n query \u003d self.object_class_expr\n if query_params:\n     query \u0026\u003d query_params","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"35515f441ff31daa4c4765cbdddeaeda90b2443b","unresolved":false,"context_lines":[{"line_number":1468,"context_line":""},{"line_number":1469,"context_line":"    def _ldap_get_list(self, search_base, scope, query_params\u003dNone,"},{"line_number":1470,"context_line":"                       attrlist\u003dNone):"},{"line_number":1471,"context_line":"        query \u003d self.object_class_expr \u0026 query_params"},{"line_number":1472,"context_line":"        with self.get_connection() as conn:"},{"line_number":1473,"context_line":"            return conn.search_s(search_base, scope, query, attrlist)"},{"line_number":1474,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_332567ab","line":1471,"in_reply_to":"1a930d6b_951ac86c","updated":"2015-01-23 11:45:35.000000000","message":"Done","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"}],"keystone/common/ldap/expr.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"92ba30fe73af8d7343f8bff1a6b96fa30bd27551","unresolved":false,"context_lines":[{"line_number":51,"context_line":"                                  \"for DN. Please, use \u0027attrs + DN\u0027.\")"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"class FilterExpr(object):"},{"line_number":55,"context_line":"    def __and__(self, other):"},{"line_number":56,"context_line":"        return Conjunction(self, other)"},{"line_number":57,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"fa98f980_c679bbfd","line":54,"updated":"2014-09-10 13:47:09.000000000","message":"Is there any reason why subclasses of this don\u0027t call the parent\u0027s __init__?","commit_id":"5772e8b2676ae9a1cdb57bcd4b78e5259a53b91d"},{"author":{"_account_id":13009,"name":"Peter Razumovsky","email":"prazumovsky@mirantis.com","username":"prazumovsky"},"change_message_id":"56581556c299772affb436a75d57ae902a7fc0f9","unresolved":false,"context_lines":[{"line_number":51,"context_line":"                                  \"for DN. Please, use \u0027attrs + DN\u0027.\")"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"class FilterExpr(object):"},{"line_number":55,"context_line":"    def __and__(self, other):"},{"line_number":56,"context_line":"        return Conjunction(self, other)"},{"line_number":57,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"fa98f980_225b33f7","line":54,"in_reply_to":"fa98f980_c679bbfd","updated":"2014-09-11 10:05:02.000000000","message":"Done","commit_id":"5772e8b2676ae9a1cdb57bcd4b78e5259a53b91d"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"92ba30fe73af8d7343f8bff1a6b96fa30bd27551","unresolved":false,"context_lines":[{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def __str__(self):"},{"line_number":107,"context_line":"        return u\u0027(\u0026%s)\u0027 % (u\u0027\u0027.join(map(six.text_type, self.parts)),)"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"objectClass \u003d Attr(\u0027objectClass\u0027)"},{"line_number":110,"context_line":"ALL \u003d objectClass \u003d\u003d \u0027*\u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"fa98f980_a644b7b7","line":108,"updated":"2014-09-10 13:47:09.000000000","message":"Missing a newline","commit_id":"5772e8b2676ae9a1cdb57bcd4b78e5259a53b91d"},{"author":{"_account_id":13009,"name":"Peter Razumovsky","email":"prazumovsky@mirantis.com","username":"prazumovsky"},"change_message_id":"56581556c299772affb436a75d57ae902a7fc0f9","unresolved":false,"context_lines":[{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def __str__(self):"},{"line_number":107,"context_line":"        return u\u0027(\u0026%s)\u0027 % (u\u0027\u0027.join(map(six.text_type, self.parts)),)"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"objectClass \u003d Attr(\u0027objectClass\u0027)"},{"line_number":110,"context_line":"ALL \u003d objectClass \u003d\u003d \u0027*\u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"fa98f980_573f3725","line":108,"in_reply_to":"fa98f980_a644b7b7","updated":"2014-09-11 10:05:02.000000000","message":"Done","commit_id":"5772e8b2676ae9a1cdb57bcd4b78e5259a53b91d"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fddcbcb08fb1dfb5ec9cf0ab0a13dd4ad335bcd9","unresolved":false,"context_lines":[{"line_number":13,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":14,"context_line":"# under the License."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"from ldap import dn as ldap_dn"},{"line_number":17,"context_line":"from ldap import filter as ldap_filter"},{"line_number":18,"context_line":"import six"},{"line_number":19,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"baa201ad_19892826","line":16,"updated":"2014-10-16 00:40:01.000000000","message":"import ldap.dn and use ldap.dn rather than have to rename to ldap_dn.","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fddcbcb08fb1dfb5ec9cf0ab0a13dd4ad335bcd9","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"class Conjunction(FilterExpr):"},{"line_number":59,"context_line":"    def __init__(self, *parts):"},{"line_number":60,"context_line":"        super(Conjunction, self).__init__()"},{"line_number":61,"context_line":"        self.parts \u003d []"},{"line_number":62,"context_line":"        for part in parts:"},{"line_number":63,"context_line":"            if isinstance(part, Conjunction):"}],"source_content_type":"text/x-python","patch_set":12,"id":"baa201ad_39bc2cbb","line":60,"updated":"2014-10-16 00:40:01.000000000","message":"super is called here but not for Equality.","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fddcbcb08fb1dfb5ec9cf0ab0a13dd4ad335bcd9","unresolved":false,"context_lines":[{"line_number":66,"context_line":"                self.parts.append(part)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def __str__(self):"},{"line_number":69,"context_line":"        return u\u0027(\u0026%s)\u0027 % (u\u0027\u0027.join(map(six.text_type, self.parts)),)"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"class DN(object):"}],"source_content_type":"text/x-python","patch_set":12,"id":"baa201ad_f9bd44b2","line":69,"updated":"2014-10-16 00:40:01.000000000","message":"this library is going to support \u0026 but not | ?","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fddcbcb08fb1dfb5ec9cf0ab0a13dd4ad335bcd9","unresolved":false,"context_lines":[{"line_number":100,"context_line":""},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"objectClass \u003d Attr(\u0027objectClass\u0027)"},{"line_number":103,"context_line":"ALL \u003d objectClass \u003d\u003d \u0027*\u0027"}],"source_content_type":"text/x-python","patch_set":12,"id":"baa201ad_f9d464ea","line":103,"updated":"2014-10-16 00:40:01.000000000","message":"This isn\u0027t going to work because \u0027*\u0027 is going to be escaped: \n \u003e\u003e\u003e str(expr.ALL)\n \u0027(objectClass\u003d\\\\2a)\u0027\n\nIt needs to be (objectClass\u003d*).\n\nAdd a test.","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd10c69f8ea305a884df07b0deaeaeafd443324e","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import ldap.dn as ldap_dn"},{"line_number":16,"context_line":"import ldap.filter as ldap_filter"},{"line_number":17,"context_line":"import six"},{"line_number":18,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_ca15924a","line":15,"updated":"2014-12-28 17:55:49.000000000","message":"use ldap.dn rather than have to rename to ldap_dn.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import ldap.dn as ldap_dn"},{"line_number":16,"context_line":"import ldap.filter as ldap_filter"},{"line_number":17,"context_line":"import six"},{"line_number":18,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_61dec06b","line":15,"in_reply_to":"3a961159_ca15924a","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd10c69f8ea305a884df07b0deaeaeafd443324e","unresolved":false,"context_lines":[{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import ldap.dn as ldap_dn"},{"line_number":16,"context_line":"import ldap.filter as ldap_filter"},{"line_number":17,"context_line":"import six"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_ea096e33","line":16,"updated":"2014-12-28 17:55:49.000000000","message":"use ldap.filter rather than have to rename to ldap_filter.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"import ldap.dn as ldap_dn"},{"line_number":16,"context_line":"import ldap.filter as ldap_filter"},{"line_number":17,"context_line":"import six"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_81d00c54","line":16,"in_reply_to":"3a961159_ea096e33","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":22,"context_line":"        self.name \u003d name"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    def __and__(self, other):"},{"line_number":25,"context_line":"        raise NotImplementedError(\"\u0027\u0026\u0027 is not supported for attrs. \""},{"line_number":26,"context_line":"                                  \"Forgot braces?\")"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    def __eq__(self, value):"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_4aa52246","line":25,"updated":"2014-12-28 17:50:09.000000000","message":"strings should be marked for translation with _()","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":22,"context_line":"        self.name \u003d name"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    def __and__(self, other):"},{"line_number":25,"context_line":"        raise NotImplementedError(\"\u0027\u0026\u0027 is not supported for attrs. \""},{"line_number":26,"context_line":"                                  \"Forgot braces?\")"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    def __eq__(self, value):"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_61fa40bb","line":25,"in_reply_to":"3a961159_4aa52246","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        return u\u0027(%s\u003d%s)\u0027 % (self.attr, value)"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"class Junction(Equality):"},{"line_number":61,"context_line":"    def __init__(self, *parts):"},{"line_number":62,"context_line":"        super(Junction, self).__init__(*parts)"},{"line_number":63,"context_line":"        self.parts \u003d []"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_0a84faaf","line":60,"updated":"2014-12-28 17:50:09.000000000","message":"Junction should be a subclass of FilterExpr not Equality.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":57,"context_line":"        return u\u0027(%s\u003d%s)\u0027 % (self.attr, value)"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"class Junction(Equality):"},{"line_number":61,"context_line":"    def __init__(self, *parts):"},{"line_number":62,"context_line":"        super(Junction, self).__init__(*parts)"},{"line_number":63,"context_line":"        self.parts \u003d []"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_81372caf","line":60,"in_reply_to":"3a961159_0a84faaf","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":91,"context_line":"                parts.append(u\u0027%s\u003d%s,\u0027 % (attr, val))"},{"line_number":92,"context_line":"            else:"},{"line_number":93,"context_line":"                parts.append(six.text_type(part))"},{"line_number":94,"context_line":"        return u\u0027%s\u0027 % (u\u0027\u0027.join(parts),)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def __radd__(self, other):"},{"line_number":97,"context_line":"        if not isinstance(other, tuple):"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_6a61fe10","line":94,"updated":"2014-12-28 17:50:09.000000000","message":"isn\u0027t this the same as u\u0027\u0027.join(parts) ?","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":91,"context_line":"                parts.append(u\u0027%s\u003d%s,\u0027 % (attr, val))"},{"line_number":92,"context_line":"            else:"},{"line_number":93,"context_line":"                parts.append(six.text_type(part))"},{"line_number":94,"context_line":"        return u\u0027%s\u0027 % (u\u0027\u0027.join(parts),)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def __radd__(self, other):"},{"line_number":97,"context_line":"        if not isinstance(other, tuple):"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_e140f007","line":94,"in_reply_to":"3a961159_6a61fe10","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd10c69f8ea305a884df07b0deaeaeafd443324e","unresolved":false,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"objectClass \u003d Attr(\u0027objectClass\u0027)"},{"line_number":112,"context_line":"ALL \u003d \u0027objectClass\u003d*\u0027"},{"line_number":113,"context_line":"EMPTY_ADDEND \u003d \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_4a01a205","line":112,"updated":"2014-12-28 17:55:49.000000000","message":"This change from patch set 12 shows that this library is flawed. You can\u0027t do \"objectClass \u003d\u003d \u0027*\u0027\" and get the expected result.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"objectClass \u003d Attr(\u0027objectClass\u0027)"},{"line_number":112,"context_line":"ALL \u003d \u0027objectClass\u003d*\u0027"},{"line_number":113,"context_line":"EMPTY_ADDEND \u003d \u0027\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_4151c4d7","line":112,"in_reply_to":"3a961159_4a01a205","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2012 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_75555cc5","line":1,"updated":"2015-01-21 16:56:12.000000000","message":"It\u0027s not 2012.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"35515f441ff31daa4c4765cbdddeaeda90b2443b","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2012 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_0c307300","line":1,"in_reply_to":"1a930d6b_75555cc5","updated":"2015-01-23 11:45:35.000000000","message":"Done","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"253a03965c0005e4bd6b18ec6dc4b697432997f6","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2012 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_f626a0b9","line":1,"in_reply_to":"1a930d6b_75555cc5","updated":"2015-01-22 05:55:57.000000000","message":"Oh... I thought I\u0027ve fixed that.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        self.attr \u003d attr"},{"line_number":67,"context_line":"        # NOTE(yorik-sar): We don\u0027t just special-case \u0027*\u0027 here to avoid"},{"line_number":68,"context_line":"        # possible injections. Only programmer can use STAR constant."},{"line_number":69,"context_line":"        if value \u003d\u003d \u0027*\u0027:"},{"line_number":70,"context_line":"            raise NotImplementedError("},{"line_number":71,"context_line":"                _(\"\u0027*\u0027 cannot be used in equaliry checks. Use STAR constant.\")"},{"line_number":72,"context_line":"            )"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_95bba80d","line":69,"updated":"2015-01-21 16:56:12.000000000","message":"The value is properly escaped, so I don\u0027t see why * needs to be rejected. This check is inadequate anyways, since * can appear anywhere in the value and it will need to be escaped. If \"*\" is rejected then \"a*\" should also be rejected.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"253a03965c0005e4bd6b18ec6dc4b697432997f6","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        self.attr \u003d attr"},{"line_number":67,"context_line":"        # NOTE(yorik-sar): We don\u0027t just special-case \u0027*\u0027 here to avoid"},{"line_number":68,"context_line":"        # possible injections. Only programmer can use STAR constant."},{"line_number":69,"context_line":"        if value \u003d\u003d \u0027*\u0027:"},{"line_number":70,"context_line":"            raise NotImplementedError("},{"line_number":71,"context_line":"                _(\"\u0027*\u0027 cannot be used in equaliry checks. Use STAR constant.\")"},{"line_number":72,"context_line":"            )"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_d648c45d","line":69,"in_reply_to":"1a930d6b_95bba80d","updated":"2015-01-22 05:55:57.000000000","message":"I guess I should expand this comment. The problem is that we should escape everything. Because any value can contain user-provided data. So if we allow (Attr(\u0027cn\u0027) \u003d\u003d \u0027*\u0027), we\u0027ll allow user to specify \u0027*\u0027 as a name in authentication and hack this planet.\n\nAnd we just won\u0027t support having \u0027*\u0027 in the middle of value as it\u0027s not currently needed. But we _do_ support users with \u0027*\u0027 in their names.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"35515f441ff31daa4c4765cbdddeaeda90b2443b","unresolved":false,"context_lines":[{"line_number":66,"context_line":"        self.attr \u003d attr"},{"line_number":67,"context_line":"        # NOTE(yorik-sar): We don\u0027t just special-case \u0027*\u0027 here to avoid"},{"line_number":68,"context_line":"        # possible injections. Only programmer can use STAR constant."},{"line_number":69,"context_line":"        if value \u003d\u003d \u0027*\u0027:"},{"line_number":70,"context_line":"            raise NotImplementedError("},{"line_number":71,"context_line":"                _(\"\u0027*\u0027 cannot be used in equaliry checks. Use STAR constant.\")"},{"line_number":72,"context_line":"            )"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_7d9fdfb4","line":69,"in_reply_to":"1a930d6b_d648c45d","updated":"2015-01-23 11:45:35.000000000","message":"Done","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":139,"context_line":"        )"},{"line_number":140,"context_line":""},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"objectClass \u003d Attr(\u0027objectClass\u0027)"},{"line_number":143,"context_line":"ALL \u003d objectClass \u003d\u003d STAR"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_b57984fe","line":142,"updated":"2015-01-21 16:56:12.000000000","message":"this should be moved into a static member of class Attr so that it\u0027s obvious what the type is.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"35515f441ff31daa4c4765cbdddeaeda90b2443b","unresolved":false,"context_lines":[{"line_number":139,"context_line":"        )"},{"line_number":140,"context_line":""},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"objectClass \u003d Attr(\u0027objectClass\u0027)"},{"line_number":143,"context_line":"ALL \u003d objectClass \u003d\u003d STAR"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_9d7d6b71","line":142,"in_reply_to":"1a930d6b_76963096","updated":"2015-01-23 11:45:35.000000000","message":"Since objectClass is used in only one place, I\u0027ll remove it altogether and move ALL to FilterExpr.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"253a03965c0005e4bd6b18ec6dc4b697432997f6","unresolved":false,"context_lines":[{"line_number":139,"context_line":"        )"},{"line_number":140,"context_line":""},{"line_number":141,"context_line":""},{"line_number":142,"context_line":"objectClass \u003d Attr(\u0027objectClass\u0027)"},{"line_number":143,"context_line":"ALL \u003d objectClass \u003d\u003d STAR"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_76963096","line":142,"in_reply_to":"1a930d6b_b57984fe","updated":"2015-01-22 05:55:57.000000000","message":"I\u0027ve answered that in the previous patchset. These are here to shortcut common expressions, and moving them to Attr would make think worse. But I\u0027ll see if that\u0027s still an issue.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"863985a4efb7a370f05df29a10ae09d3605afe7f","unresolved":false,"context_lines":[{"line_number":67,"context_line":"        # NOTE(yorik-sar): We should escape everything (including \u0027*\u0027) to avoid"},{"line_number":68,"context_line":"        # user data injections, but here we special-case \u0027*\u0027 to avoid"},{"line_number":69,"context_line":"        # programming error (it\u0027ll get escaped) and warn programmer to use"},{"line_number":70,"context_line":"        # STAR instead."},{"line_number":71,"context_line":"        if value \u003d\u003d \u0027*\u0027:"},{"line_number":72,"context_line":"            raise NotImplementedError("},{"line_number":73,"context_line":"                _(\"\u0027*\u0027 cannot be used in equaliry checks. Use STAR constant.\")"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a930d6b_6dd36704","line":70,"updated":"2015-01-24 15:12:12.000000000","message":"This code doesn\u0027t know whether a * was passed in because of a programmer error or if the user just pased in a * on the query. This check should be removed.","commit_id":"8a6fb25fd361f06cd009874d922a6c7f7bfdaeaa"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"2cdb553c169590c26b1ac57c0d5be9832fde5e64","unresolved":false,"context_lines":[{"line_number":67,"context_line":"        # NOTE(yorik-sar): We should escape everything (including \u0027*\u0027) to avoid"},{"line_number":68,"context_line":"        # user data injections, but here we special-case \u0027*\u0027 to avoid"},{"line_number":69,"context_line":"        # programming error (it\u0027ll get escaped) and warn programmer to use"},{"line_number":70,"context_line":"        # STAR instead."},{"line_number":71,"context_line":"        if value \u003d\u003d \u0027*\u0027:"},{"line_number":72,"context_line":"            raise NotImplementedError("},{"line_number":73,"context_line":"                _(\"\u0027*\u0027 cannot be used in equaliry checks. Use STAR constant.\")"}],"source_content_type":"text/x-python","patch_set":15,"id":"1a930d6b_1c43ef6c","line":70,"in_reply_to":"1a930d6b_6dd36704","updated":"2015-01-25 11:26:36.000000000","message":"We have all this code to proper escape filter and DN values to make proper requests to LDAP _and_ to avoid possible \"LDAP injections\". Let me draw an analogy with SQL. No ORM would escape every value except \"\u0027; DROP DATABASE Users--\" because programmer might\u0027ve passed this in by mistake. The same applies here. If we use filter like \"Attr(\u0027cn\u0027) \u003d\u003d username\", we don\u0027t want user to be able to provide username \u0027*\u0027 and get every record we have in LDAP. That\u0027s the very basic injection protection.","commit_id":"8a6fb25fd361f06cd009874d922a6c7f7bfdaeaa"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"99c1d4821201fd531ce2e71b49927b5668f09e9c","unresolved":false,"context_lines":[{"line_number":68,"context_line":"        # user data injections, but here we special-case \u0027*\u0027 to avoid"},{"line_number":69,"context_line":"        # programming error (it\u0027ll get escaped) and warn programmer to use"},{"line_number":70,"context_line":"        # STAR instead."},{"line_number":71,"context_line":"        if value \u003d\u003d \u0027*\u0027:"},{"line_number":72,"context_line":"            raise NotImplementedError("},{"line_number":73,"context_line":"                _(\"\u0027*\u0027 cannot be used in equaliry checks. Use STAR constant.\")"},{"line_number":74,"context_line":"            )"}],"source_content_type":"text/x-python","patch_set":18,"id":"da86d52c_18ae7fe6","line":71,"updated":"2015-02-05 01:54:30.000000000","message":"The response in patch set 15 said that using cn\u003d* as a filter was a problem since it will return every entry... ok, so is cn\u003da*, since it will also return lots of entries. So why are we being picky about value \u003d\u003d \u0027*\u0027 here? There\u0027s no need for this check. If self.value \u003d \u0027*\u0027 then the filter will wind up cn\u003d\\* so there\u0027s no point to checking for value \u003d\u003d \u0027*\u0027 here.","commit_id":"4af2d0400c275756da4d24012dd66b9bfc3d28e1"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"e960e0e6e4e954c4f38ebadaa2c593e283ac7a80","unresolved":false,"context_lines":[{"line_number":68,"context_line":"        # user data injections, but here we special-case \u0027*\u0027 to avoid"},{"line_number":69,"context_line":"        # programming error (it\u0027ll get escaped) and warn programmer to use"},{"line_number":70,"context_line":"        # STAR instead."},{"line_number":71,"context_line":"        if value \u003d\u003d \u0027*\u0027:"},{"line_number":72,"context_line":"            raise NotImplementedError("},{"line_number":73,"context_line":"                _(\"\u0027*\u0027 cannot be used in equaliry checks. Use STAR constant.\")"},{"line_number":74,"context_line":"            )"}],"source_content_type":"text/x-python","patch_set":18,"id":"da86d52c_367c2fb5","line":71,"in_reply_to":"da86d52c_18ae7fe6","updated":"2015-02-05 08:05:08.000000000","message":"It\u0027s here to avoid programmer\u0027s error since one can think that writing\n\n    Attr(\u0027cn\u0027) \u003d\u003d \u0027*\u0027\n\nis the right thing to do to get any cn.\n\nException here can be replaced with a warning though.","commit_id":"4af2d0400c275756da4d24012dd66b9bfc3d28e1"}],"keystone/identity/backends/ldap.py":[{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fddcbcb08fb1dfb5ec9cf0ab0a13dd4ad335bcd9","unresolved":false,"context_lines":[{"line_number":345,"context_line":""},{"line_number":346,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":347,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d user_dn) \u0026"},{"line_number":348,"context_line":"                 self.ldap_filter or \u0027\u0027)"},{"line_number":349,"context_line":"        return self.get_all(query)"},{"line_number":350,"context_line":""},{"line_number":351,"context_line":"    def list_user_groups_filtered(self, user_dn):"}],"source_content_type":"text/x-python","patch_set":12,"id":"baa201ad_d9732014","line":348,"updated":"2014-10-16 00:40:01.000000000","message":"It looks like a mistake to have \u0027\u0027 here. Maybe a more obvious sentinel could be used instead (expr.NO_FILTER or something). Or, make filter \u0026 self.ldap_filter handle an empty self.ldap_filter so \u0027\u0027 isn\u0027t needed.","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":354,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d user_dn) \u0026"},{"line_number":355,"context_line":"                 self.ldap_filter or expr.EMPTY_ADDEND)"},{"line_number":356,"context_line":"        return self.get_all(query)"},{"line_number":357,"context_line":""},{"line_number":358,"context_line":"    def list_user_groups_filtered(self, user_dn):"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_ca7032df","line":355,"updated":"2014-12-28 17:50:09.000000000","message":"Can self.ldap_filter default to expr.EMPTY_ADDEND? Then this could be simpler.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        query \u003d ((expr.objectClass \u003d\u003d self.object_class) \u0026"},{"line_number":354,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d user_dn) \u0026"},{"line_number":355,"context_line":"                 self.ldap_filter or expr.EMPTY_ADDEND)"},{"line_number":356,"context_line":"        return self.get_all(query)"},{"line_number":357,"context_line":""},{"line_number":358,"context_line":"    def list_user_groups_filtered(self, user_dn):"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_01ca5c4e","line":355,"in_reply_to":"3a961159_ca7032df","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":351,"context_line":"        \"\"\"Return a list of groups for which the user is a member.\"\"\""},{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        query \u003d (self.object_class_expr \u0026 self.ldap_filter \u0026"},{"line_number":354,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d user_dn))"},{"line_number":355,"context_line":"        return self.get_all(query)"},{"line_number":356,"context_line":""},{"line_number":357,"context_line":"    def list_user_groups_filtered(self, user_dn):"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_754e3cc3","line":354,"updated":"2015-01-21 16:56:12.000000000","message":"Similar comment here about handling of a None value --\n\n query \u003d (self.object_class_expr \u0026 (expr.Attr(self.member_attribute) \u003d\u003d user_dn))\n if self.ldap_filter:\n     query \u0026\u003d self.ldap_filter","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"35515f441ff31daa4c4765cbdddeaeda90b2443b","unresolved":false,"context_lines":[{"line_number":351,"context_line":"        \"\"\"Return a list of groups for which the user is a member.\"\"\""},{"line_number":352,"context_line":""},{"line_number":353,"context_line":"        query \u003d (self.object_class_expr \u0026 self.ldap_filter \u0026"},{"line_number":354,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d user_dn))"},{"line_number":355,"context_line":"        return self.get_all(query)"},{"line_number":356,"context_line":""},{"line_number":357,"context_line":"    def list_user_groups_filtered(self, user_dn):"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_5373d37f","line":354,"in_reply_to":"1a930d6b_754e3cc3","updated":"2015-01-23 11:45:35.000000000","message":"Done","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"58f32052c0909c61acb98c4a5c19a7395f27af4d","unresolved":false,"context_lines":[{"line_number":358,"context_line":"        \"\"\"Return a filtered list of groups for which the user is a member.\"\"\""},{"line_number":359,"context_line":""},{"line_number":360,"context_line":"        query \u003d (self.object_class_expr \u0026 self.ldap_filter \u0026"},{"line_number":361,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d user_dn))"},{"line_number":362,"context_line":"        return self.get_all_filtered(query)"},{"line_number":363,"context_line":""},{"line_number":364,"context_line":"    def list_group_users(self, group_id):"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_d5cc5038","line":361,"updated":"2015-01-21 16:56:12.000000000","message":"similar comment here.","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"35515f441ff31daa4c4765cbdddeaeda90b2443b","unresolved":false,"context_lines":[{"line_number":358,"context_line":"        \"\"\"Return a filtered list of groups for which the user is a member.\"\"\""},{"line_number":359,"context_line":""},{"line_number":360,"context_line":"        query \u003d (self.object_class_expr \u0026 self.ldap_filter \u0026"},{"line_number":361,"context_line":"                 (expr.Attr(self.member_attribute) \u003d\u003d user_dn))"},{"line_number":362,"context_line":"        return self.get_all_filtered(query)"},{"line_number":363,"context_line":""},{"line_number":364,"context_line":"    def list_group_users(self, group_id):"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a930d6b_736e0f98","line":361,"in_reply_to":"1a930d6b_d5cc5038","updated":"2015-01-23 11:45:35.000000000","message":"Done","commit_id":"cae9d364c068159beb4a4944fbd4dfc8cb4bbc37"}],"keystone/tests/test_expr.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"92ba30fe73af8d7343f8bff1a6b96fa30bd27551","unresolved":false,"context_lines":[{"line_number":1,"context_line":"import ldap"},{"line_number":2,"context_line":"import six"},{"line_number":3,"context_line":"import uuid"},{"line_number":4,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"fa98f980_c6c7fb10","line":1,"updated":"2014-09-10 13:47:09.000000000","message":"Missing the license and the imports are all out of order.\n\nhttp://docs.openstack.org/developer/hacking/#imports","commit_id":"5772e8b2676ae9a1cdb57bcd4b78e5259a53b91d"},{"author":{"_account_id":13009,"name":"Peter Razumovsky","email":"prazumovsky@mirantis.com","username":"prazumovsky"},"change_message_id":"56581556c299772affb436a75d57ae902a7fc0f9","unresolved":false,"context_lines":[{"line_number":1,"context_line":"import ldap"},{"line_number":2,"context_line":"import six"},{"line_number":3,"context_line":"import uuid"},{"line_number":4,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"fa98f980_6270db72","line":1,"in_reply_to":"fa98f980_c6c7fb10","updated":"2014-09-11 10:05:02.000000000","message":"Done","commit_id":"5772e8b2676ae9a1cdb57bcd4b78e5259a53b91d"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"92ba30fe73af8d7343f8bff1a6b96fa30bd27551","unresolved":false,"context_lines":[{"line_number":3,"context_line":"import uuid"},{"line_number":4,"context_line":""},{"line_number":5,"context_line":"from keystone import tests"},{"line_number":6,"context_line":"from testtools import ExpectedException"},{"line_number":7,"context_line":""},{"line_number":8,"context_line":"from keystone.common.ldap import expr"},{"line_number":9,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"fa98f980_46022b3f","line":6,"updated":"2014-09-10 13:47:09.000000000","message":"Only import modules.","commit_id":"5772e8b2676ae9a1cdb57bcd4b78e5259a53b91d"},{"author":{"_account_id":13009,"name":"Peter Razumovsky","email":"prazumovsky@mirantis.com","username":"prazumovsky"},"change_message_id":"56581556c299772affb436a75d57ae902a7fc0f9","unresolved":false,"context_lines":[{"line_number":3,"context_line":"import uuid"},{"line_number":4,"context_line":""},{"line_number":5,"context_line":"from keystone import tests"},{"line_number":6,"context_line":"from testtools import ExpectedException"},{"line_number":7,"context_line":""},{"line_number":8,"context_line":"from keystone.common.ldap import expr"},{"line_number":9,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"fa98f980_4273d77f","line":6,"in_reply_to":"fa98f980_46022b3f","updated":"2014-09-11 10:05:02.000000000","message":"Done","commit_id":"5772e8b2676ae9a1cdb57bcd4b78e5259a53b91d"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fddcbcb08fb1dfb5ec9cf0ab0a13dd4ad335bcd9","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2014 Mirantis Inc"},{"line_number":2,"context_line":"# All Rights Reserved."},{"line_number":3,"context_line":"#"},{"line_number":4,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"}],"source_content_type":"text/x-python","patch_set":12,"id":"baa201ad_595570c0","line":1,"updated":"2014-10-16 00:40:01.000000000","message":"This should be in keystone/tests/unit/common/ldap/","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"8eb6dfafc56f84d04cfb0a2fa0979996aaca4a4c","unresolved":false,"context_lines":[{"line_number":32,"context_line":"class DNExprTest(tests.TestCase):"},{"line_number":33,"context_line":"    def test_radd_instance(self):"},{"line_number":34,"context_line":"        \"\"\"Test instance of result of right adding."},{"line_number":35,"context_line":"        \"\"\""},{"line_number":36,"context_line":"        filter_str \u003d (ID_ATTR, OBJECT_ID) + expr.DN(TREE_DN)"},{"line_number":37,"context_line":"        self.assertIsInstance(filter_str, expr.DN)"},{"line_number":38,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"5a890539_38fe296c","line":35,"updated":"2014-12-01 19:55:25.000000000","message":"nit: could pull the \u0027\"\" up a line: \n\n    \"\"\"Test instance of result of right adding.\"\"\"","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"8eb6dfafc56f84d04cfb0a2fa0979996aaca4a4c","unresolved":false,"context_lines":[{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def test_radd_to_added_instance(self):"},{"line_number":40,"context_line":"        \"\"\"Test instance of result of another right adding."},{"line_number":41,"context_line":"        \"\"\""},{"line_number":42,"context_line":"        filter_str \u003d ((expr.objectClass, OBJECT_CLASS) +"},{"line_number":43,"context_line":"                      ((ID_ATTR, OBJECT_ID) + expr.DN(TREE_DN)))"},{"line_number":44,"context_line":"        self.assertIsInstance(filter_str, expr.DN)"}],"source_content_type":"text/x-python","patch_set":12,"id":"5a890539_98f2bd99","line":41,"updated":"2014-12-01 19:55:25.000000000","message":"same comment here and applies throughout file as long as the line doesn\u0027t exceed 80 characters.","commit_id":"044aafe789cf6d36e5acf9c43e8a37b844734f25"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd10c69f8ea305a884df07b0deaeaeafd443324e","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2012 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_f0079c16","line":1,"updated":"2014-12-28 17:55:49.000000000","message":"This file should be in keystone/tests/unit/common/ldap/","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2012 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_ea740ed2","line":1,"updated":"2014-12-28 17:50:09.000000000","message":"it\u0027s not 2012 anymore.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2012 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_e1a47008","line":1,"in_reply_to":"3a961159_ea740ed2","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"ID_ATTR \u003d \"cn\""},{"line_number":26,"context_line":"OBJECT_CLASS \u003d \"groupOfNames\""},{"line_number":27,"context_line":"OBJECT_ID \u003d uuid.uuid4().hex"},{"line_number":28,"context_line":"TREE_DN \u003d \"dc\u003dexample,dc\u003dcom\""},{"line_number":29,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_2a7ff6ac","line":26,"updated":"2014-12-28 17:50:09.000000000","message":"seems like these can also be UUIDs.","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"fd5e5890f427800d998472c953937310a100ff5c","unresolved":false,"context_lines":[{"line_number":84,"context_line":""},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"class AttrExprTest(tests.TestCase):"},{"line_number":87,"context_line":"    def test_global_filed(self):"},{"line_number":88,"context_line":"        self.assertEqual(six.text_type(expr.ALL), \u0027objectClass\u003d*\u0027)"},{"line_number":89,"context_line":"        self.assertEqual(six.text_type(expr.EMPTY_ADDEND), \u0027\u0027)"},{"line_number":90,"context_line":"        self.assertIsInstance(expr.objectClass, expr.Attr)"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_aa420666","line":87,"updated":"2014-12-28 17:50:09.000000000","message":"change \"filed\" to \"fields\".","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"},{"author":{"_account_id":708,"name":"Yuriy Taraday","email":"yuriy@taraday.nl","username":"yorik-sar"},"change_message_id":"a0ed62a781416fe991daccf3f4616c9d7cfca315","unresolved":false,"context_lines":[{"line_number":84,"context_line":""},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"class AttrExprTest(tests.TestCase):"},{"line_number":87,"context_line":"    def test_global_filed(self):"},{"line_number":88,"context_line":"        self.assertEqual(six.text_type(expr.ALL), \u0027objectClass\u003d*\u0027)"},{"line_number":89,"context_line":"        self.assertEqual(six.text_type(expr.EMPTY_ADDEND), \u0027\u0027)"},{"line_number":90,"context_line":"        self.assertIsInstance(expr.objectClass, expr.Attr)"}],"source_content_type":"text/x-python","patch_set":13,"id":"3a961159_01ddfc6f","line":87,"in_reply_to":"3a961159_aa420666","updated":"2015-01-16 20:40:24.000000000","message":"Done","commit_id":"e8807e71adf2599154752035c24c197f1cd83348"}]}
