)]}'
{"placement/objects/research_context.py":[{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"74fb2aee09740a33cac19108ae9ab0c86e0d407b","unresolved":false,"context_lines":[{"line_number":625,"context_line":""},{"line_number":626,"context_line":""},{"line_number":627,"context_line":"@db_api.placement_context_manager.reader"},{"line_number":628,"context_line":"def _get_roots_with_traits(ctx, required_traits, forbidden_traits):"},{"line_number":629,"context_line":"    \"\"\"Return a set of IDs of root providers (NOT trees) that can satisfy trait"},{"line_number":630,"context_line":"    requirements."},{"line_number":631,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9fb8cfa7_50f6fdfb","line":628,"updated":"2019-06-17 11:17:54.000000000","message":"The way you\u0027ve used this further down the stack it is used in a public way (that is, outside of the same package), so if we go with this, that should get fixed.","commit_id":"efc396010c334c511c5df7c53857b64b1f77ee7a"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"b1768cdbe7da48e278ef13f99c61215d0bc59513","unresolved":false,"context_lines":[{"line_number":625,"context_line":""},{"line_number":626,"context_line":""},{"line_number":627,"context_line":"@db_api.placement_context_manager.reader"},{"line_number":628,"context_line":"def _get_roots_with_traits(ctx, required_traits, forbidden_traits):"},{"line_number":629,"context_line":"    \"\"\"Return a set of IDs of root providers (NOT trees) that can satisfy trait"},{"line_number":630,"context_line":"    requirements."},{"line_number":631,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9fb8cfa7_bf1f02b6","line":628,"in_reply_to":"9fb8cfa7_3fdb1250","updated":"2019-06-17 15:52:40.000000000","message":"\u003e Come to think of it, though, would it be more appropriate in\n \u003e objects/allocation_candidates.py?\n\n[Later] Leaving it here. It makes a lot more sense with the introduction of RequestWideSearchContext\n\n...whereupon it makes sense to stay private too.","commit_id":"efc396010c334c511c5df7c53857b64b1f77ee7a"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"bdbc13cf7cdc377c6c85f294089c25bf6805edd7","unresolved":false,"context_lines":[{"line_number":625,"context_line":""},{"line_number":626,"context_line":""},{"line_number":627,"context_line":"@db_api.placement_context_manager.reader"},{"line_number":628,"context_line":"def _get_roots_with_traits(ctx, required_traits, forbidden_traits):"},{"line_number":629,"context_line":"    \"\"\"Return a set of IDs of root providers (NOT trees) that can satisfy trait"},{"line_number":630,"context_line":"    requirements."},{"line_number":631,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"9fb8cfa7_3fdb1250","line":628,"in_reply_to":"9fb8cfa7_50f6fdfb","updated":"2019-06-17 15:39:52.000000000","message":"Yup. Initially private because copied from _get_trees_with_traits. Fixed.\n\nCome to think of it, though, would it be more appropriate in objects/allocation_candidates.py?","commit_id":"efc396010c334c511c5df7c53857b64b1f77ee7a"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"ac5c4c29d12309d704d2a8492660aeea2b651a77","unresolved":false,"context_lines":[{"line_number":638,"context_line":"            provider must not have."},{"line_number":639,"context_line":"    :raises ValueError: If required_traits and forbidden_traits are both empty/"},{"line_number":640,"context_line":"            None."},{"line_number":641,"context_line":"    :raises ResourceProviderNotFound: If no resource providers exist with the"},{"line_number":642,"context_line":"            specified trait constraints."},{"line_number":643,"context_line":"    \"\"\""},{"line_number":644,"context_line":"    if not (required_traits or forbidden_traits):"},{"line_number":645,"context_line":"        raise ValueError(\"At least one of required_traits or forbidden_traits \""}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_3bef8188","line":642,"range":{"start_line":641,"start_character":12,"end_line":642,"end_character":40},"updated":"2019-06-19 08:42:06.000000000","message":"Is the really an exceptional case that no provider satisfies the request?","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"ac5c4c29d12309d704d2a8492660aeea2b651a77","unresolved":false,"context_lines":[{"line_number":639,"context_line":"    :raises ValueError: If required_traits and forbidden_traits are both empty/"},{"line_number":640,"context_line":"            None."},{"line_number":641,"context_line":"    :raises ResourceProviderNotFound: If no resource providers exist with the"},{"line_number":642,"context_line":"            specified trait constraints."},{"line_number":643,"context_line":"    \"\"\""},{"line_number":644,"context_line":"    if not (required_traits or forbidden_traits):"},{"line_number":645,"context_line":"        raise ValueError(\"At least one of required_traits or forbidden_traits \""}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_bbca914c","line":642,"updated":"2019-06-19 08:42:06.000000000","message":"nit: you can add a :return doc","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"64d77cc2952374b18932fa7d2b528f6b1eea53db","unresolved":false,"context_lines":[{"line_number":638,"context_line":"            provider must not have."},{"line_number":639,"context_line":"    :raises ValueError: If required_traits and forbidden_traits are both empty/"},{"line_number":640,"context_line":"            None."},{"line_number":641,"context_line":"    :raises ResourceProviderNotFound: If no resource providers exist with the"},{"line_number":642,"context_line":"            specified trait constraints."},{"line_number":643,"context_line":"    \"\"\""},{"line_number":644,"context_line":"    if not (required_traits or forbidden_traits):"},{"line_number":645,"context_line":"        raise ValueError(\"At least one of required_traits or forbidden_traits \""}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_d8065921","line":642,"range":{"start_line":641,"start_character":12,"end_line":642,"end_character":40},"in_reply_to":"9fb8cfa7_3bef8188","updated":"2019-06-19 23:17:46.000000000","message":"\u003e Is the really an exceptional case that no provider satisfies the\n \u003e request?\n\nI found this the easiest way to handle this [1]. If you would prefer, I could refactor to raise the exception from the caller.\n\n[1] https://review.opendev.org/#/c/665492/12/placement/objects/allocation_candidate.py@75","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"64d77cc2952374b18932fa7d2b528f6b1eea53db","unresolved":false,"context_lines":[{"line_number":639,"context_line":"    :raises ValueError: If required_traits and forbidden_traits are both empty/"},{"line_number":640,"context_line":"            None."},{"line_number":641,"context_line":"    :raises ResourceProviderNotFound: If no resource providers exist with the"},{"line_number":642,"context_line":"            specified trait constraints."},{"line_number":643,"context_line":"    \"\"\""},{"line_number":644,"context_line":"    if not (required_traits or forbidden_traits):"},{"line_number":645,"context_line":"        raise ValueError(\"At least one of required_traits or forbidden_traits \""}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_f801dd07","line":642,"in_reply_to":"9fb8cfa7_bbca914c","updated":"2019-06-19 23:17:46.000000000","message":"\u003e nit: you can add a :return doc\n\nThe docstring title says what it returns, but can do.","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"08e2a40b7603a6262e589a98bda37ab4919d8107","unresolved":false,"context_lines":[{"line_number":638,"context_line":"            provider must not have."},{"line_number":639,"context_line":"    :raises ValueError: If required_traits and forbidden_traits are both empty/"},{"line_number":640,"context_line":"            None."},{"line_number":641,"context_line":"    :raises ResourceProviderNotFound: If no resource providers exist with the"},{"line_number":642,"context_line":"            specified trait constraints."},{"line_number":643,"context_line":"    \"\"\""},{"line_number":644,"context_line":"    if not (required_traits or forbidden_traits):"},{"line_number":645,"context_line":"        raise ValueError(\"At least one of required_traits or forbidden_traits \""}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_e21603a8","line":642,"range":{"start_line":641,"start_character":12,"end_line":642,"end_character":40},"in_reply_to":"9fb8cfa7_d8065921","updated":"2019-06-20 13:48:06.000000000","message":"Done","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"08e2a40b7603a6262e589a98bda37ab4919d8107","unresolved":false,"context_lines":[{"line_number":639,"context_line":"    :raises ValueError: If required_traits and forbidden_traits are both empty/"},{"line_number":640,"context_line":"            None."},{"line_number":641,"context_line":"    :raises ResourceProviderNotFound: If no resource providers exist with the"},{"line_number":642,"context_line":"            specified trait constraints."},{"line_number":643,"context_line":"    \"\"\""},{"line_number":644,"context_line":"    if not (required_traits or forbidden_traits):"},{"line_number":645,"context_line":"        raise ValueError(\"At least one of required_traits or forbidden_traits \""}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_820dc791","line":642,"in_reply_to":"9fb8cfa7_f801dd07","updated":"2019-06-20 13:48:06.000000000","message":"Done","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"ac5c4c29d12309d704d2a8492660aeea2b651a77","unresolved":false,"context_lines":[{"line_number":688,"context_line":"            join_to, rptt_forbid, sa.and_("},{"line_number":689,"context_line":"                rpt.c.id \u003d\u003d rptt_forbid.c.resource_provider_id,"},{"line_number":690,"context_line":"                rptt_forbid.c.trait_id.in_(forbidden_traits)))"},{"line_number":691,"context_line":"        #   AND rptt_forbid.resource_provider_id IS NULL"},{"line_number":692,"context_line":"        cond.append(rptt_forbid.c.resource_provider_id.is_(None))"},{"line_number":693,"context_line":"        subq_join \u003d rpt_to_rptt_forbid"},{"line_number":694,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_3b2a21e7","line":691,"updated":"2019-06-19 08:42:06.000000000","message":"Just to be sure: Is the logic here to see that we don\u0027t match with RPs that has some of the forbidden traits attached?","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"64d77cc2952374b18932fa7d2b528f6b1eea53db","unresolved":false,"context_lines":[{"line_number":688,"context_line":"            join_to, rptt_forbid, sa.and_("},{"line_number":689,"context_line":"                rpt.c.id \u003d\u003d rptt_forbid.c.resource_provider_id,"},{"line_number":690,"context_line":"                rptt_forbid.c.trait_id.in_(forbidden_traits)))"},{"line_number":691,"context_line":"        #   AND rptt_forbid.resource_provider_id IS NULL"},{"line_number":692,"context_line":"        cond.append(rptt_forbid.c.resource_provider_id.is_(None))"},{"line_number":693,"context_line":"        subq_join \u003d rpt_to_rptt_forbid"},{"line_number":694,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_2312ea59","line":691,"in_reply_to":"9fb8cfa7_3b2a21e7","updated":"2019-06-19 23:17:46.000000000","message":"Copy/paste from _get_trees_with_traits above. But yes, I think that\u0027s what it\u0027s for.","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"78ce3ca3c84131ebeaff0b7e6cbc8000fa373c53","unresolved":false,"context_lines":[{"line_number":649,"context_line":"    #"},{"line_number":650,"context_line":"    #   SELECT rp.id FROM resource_providers AS rp"},{"line_number":651,"context_line":"    rpt \u003d sa.alias(_RP_TBL, name\u003d\"rp\")"},{"line_number":652,"context_line":"    sel \u003d sa.select([rpt.c.id]).distinct()"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"    #   WHERE rp.parent_provider_id IS NULL"},{"line_number":655,"context_line":"    cond \u003d [rpt.c.parent_provider_id.is_(None)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_e4f84e7d","line":652,"updated":"2019-06-20 16:08:14.000000000","message":"How/why did you decide to use distinct() here? I\u0027m pretty sure it redundant with the group by down at line 695.","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"e64fc6ec6e60ee4d4ad08c225aa657c06630c280","unresolved":false,"context_lines":[{"line_number":649,"context_line":"    #"},{"line_number":650,"context_line":"    #   SELECT rp.id FROM resource_providers AS rp"},{"line_number":651,"context_line":"    rpt \u003d sa.alias(_RP_TBL, name\u003d\"rp\")"},{"line_number":652,"context_line":"    sel \u003d sa.select([rpt.c.id]).distinct()"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"    #   WHERE rp.parent_provider_id IS NULL"},{"line_number":655,"context_line":"    cond \u003d [rpt.c.parent_provider_id.is_(None)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_7bd4f547","line":652,"in_reply_to":"9fb8cfa7_4a028171","updated":"2019-06-20 19:58:33.000000000","message":"Done","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"841af9f27d72d4215734c66da50567a2a9106bee","unresolved":false,"context_lines":[{"line_number":649,"context_line":"    #"},{"line_number":650,"context_line":"    #   SELECT rp.id FROM resource_providers AS rp"},{"line_number":651,"context_line":"    rpt \u003d sa.alias(_RP_TBL, name\u003d\"rp\")"},{"line_number":652,"context_line":"    sel \u003d sa.select([rpt.c.id]).distinct()"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"    #   WHERE rp.parent_provider_id IS NULL"},{"line_number":655,"context_line":"    cond \u003d [rpt.c.parent_provider_id.is_(None)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_4a028171","line":652,"in_reply_to":"9fb8cfa7_e4f84e7d","updated":"2019-06-20 17:29:07.000000000","message":"This discussion was had in another patch at some point and there turned out to be a difference in behavior among different database backends, but I can\u0027t remember what combination of GROUP BY and DISTINCT we decided was necessary to make it work etc etc. Is there any harm?","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"78ce3ca3c84131ebeaff0b7e6cbc8000fa373c53","unresolved":false,"context_lines":[{"line_number":651,"context_line":"    rpt \u003d sa.alias(_RP_TBL, name\u003d\"rp\")"},{"line_number":652,"context_line":"    sel \u003d sa.select([rpt.c.id]).distinct()"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"    #   WHERE rp.parent_provider_id IS NULL"},{"line_number":655,"context_line":"    cond \u003d [rpt.c.parent_provider_id.is_(None)]"},{"line_number":656,"context_line":"    subq_join \u003d None"},{"line_number":657,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_64053e7a","line":654,"updated":"2019-06-20 16:08:14.000000000","message":"I wonder if rp.id \u003d\u003d rp.root_provider_id is any better or worse? zzzeek would probably know, probably doesn\u0027t matter.","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"841af9f27d72d4215734c66da50567a2a9106bee","unresolved":false,"context_lines":[{"line_number":651,"context_line":"    rpt \u003d sa.alias(_RP_TBL, name\u003d\"rp\")"},{"line_number":652,"context_line":"    sel \u003d sa.select([rpt.c.id]).distinct()"},{"line_number":653,"context_line":""},{"line_number":654,"context_line":"    #   WHERE rp.parent_provider_id IS NULL"},{"line_number":655,"context_line":"    cond \u003d [rpt.c.parent_provider_id.is_(None)]"},{"line_number":656,"context_line":"    subq_join \u003d None"},{"line_number":657,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_8a863965","line":654,"in_reply_to":"9fb8cfa7_64053e7a","updated":"2019-06-20 17:29:07.000000000","message":"I\u0027m only guessing that, if it matters at all, a null check would be \"faster\" - but we\u0027re talking like maybe one machine instruction.","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"78ce3ca3c84131ebeaff0b7e6cbc8000fa373c53","unresolved":false,"context_lines":[{"line_number":676,"context_line":"        sel \u003d sel.having(having_cond)"},{"line_number":677,"context_line":""},{"line_number":678,"context_line":"    #   # Only if we have forbidden_traits..."},{"line_number":679,"context_line":"    if forbidden_traits:"},{"line_number":680,"context_line":"        #   LEFT JOIN resource_provider_traits AS rptt_forbid"},{"line_number":681,"context_line":"        rptt_forbid \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\"rptt_forbid\")"},{"line_number":682,"context_line":"        join_to \u003d rpt"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_04224202","line":679,"updated":"2019-06-20 16:08:14.000000000","message":"If there is at least one forbidden trait passed in, and no required traits, and the forbidden trait is not actually used anywhere, is the result set of this method every single provider that is a root?\n\nIf so, that might not be a big deal, but it seems awkward and worth thinking about.\n\n(all the while acking that make it, make it right, make it fast is good wisdom)","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"841af9f27d72d4215734c66da50567a2a9106bee","unresolved":false,"context_lines":[{"line_number":676,"context_line":"        sel \u003d sel.having(having_cond)"},{"line_number":677,"context_line":""},{"line_number":678,"context_line":"    #   # Only if we have forbidden_traits..."},{"line_number":679,"context_line":"    if forbidden_traits:"},{"line_number":680,"context_line":"        #   LEFT JOIN resource_provider_traits AS rptt_forbid"},{"line_number":681,"context_line":"        rptt_forbid \u003d sa.alias(_RP_TRAIT_TBL, name\u003d\"rptt_forbid\")"},{"line_number":682,"context_line":"        join_to \u003d rpt"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_ea26d516","line":679,"in_reply_to":"9fb8cfa7_04224202","updated":"2019-06-20 17:29:07.000000000","message":"\u003e If there is at least one forbidden trait passed in, and no required\n \u003e traits, and the forbidden trait is not actually used anywhere, is\n \u003e the result set of this method every single provider that is a root?\n\nYup by design. Not sure how else it would look.\n\nLater we might be able to optimize by tacking bits of this SQL onto other tree-ish queries instead of doing this independently.","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"}],"placement/tests/functional/db/test_allocation_candidates.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"ac5c4c29d12309d704d2a8492660aeea2b651a77","unresolved":false,"context_lines":[{"line_number":871,"context_line":"                set(trait.id for trait in forbidden or []))"},{"line_number":872,"context_line":"            if expected:"},{"line_number":873,"context_line":"                expected \u003d self._get_rp_ids_matching_names("},{"line_number":874,"context_line":"                    \u0027cn%d\u0027 % d for d in expected)"},{"line_number":875,"context_line":"            self.assertEqual(expected or set(), actual)"},{"line_number":876,"context_line":""},{"line_number":877,"context_line":"        # One of required/forbidden must be specified"}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_9b1d4dbf","line":874,"range":{"start_line":874,"start_character":31,"end_line":874,"end_character":48},"updated":"2019-06-19 08:42:06.000000000","message":"you can use the \u0027for d in expected or []\u0027 construct here as well like above.\n\n//later\n\nor _get_rp_ids_matching_names([]) blows?","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"64d77cc2952374b18932fa7d2b528f6b1eea53db","unresolved":false,"context_lines":[{"line_number":871,"context_line":"                set(trait.id for trait in forbidden or []))"},{"line_number":872,"context_line":"            if expected:"},{"line_number":873,"context_line":"                expected \u003d self._get_rp_ids_matching_names("},{"line_number":874,"context_line":"                    \u0027cn%d\u0027 % d for d in expected)"},{"line_number":875,"context_line":"            self.assertEqual(expected or set(), actual)"},{"line_number":876,"context_line":""},{"line_number":877,"context_line":"        # One of required/forbidden must be specified"}],"source_content_type":"text/x-python","patch_set":4,"id":"9fb8cfa7_430d9e33","line":874,"range":{"start_line":874,"start_character":31,"end_line":874,"end_character":48},"in_reply_to":"9fb8cfa7_9b1d4dbf","updated":"2019-06-19 23:17:46.000000000","message":"\u003e or _get_rp_ids_matching_names([]) blows?\n\nThis","commit_id":"cbb7d5cf007a4b1e9ba50ca18a51f450db1f95cf"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"78ce3ca3c84131ebeaff0b7e6cbc8000fa373c53","unresolved":false,"context_lines":[{"line_number":887,"context_line":"        do_test(required\u003d[geneve_t, ssd_t])"},{"line_number":888,"context_line":""},{"line_number":889,"context_line":"        # Forbid traits not on any roots"},{"line_number":890,"context_line":"        do_test(forbidden\u003d[geneve_t, ssl_t], expected\u003d(1, 2, 3, 4, 5, 6, 7))"},{"line_number":891,"context_line":"        # Forbid traits just on roots"},{"line_number":892,"context_line":"        do_test(forbidden\u003d[avx2_t, ssd_t], expected\u003d(4, 5, 6, 7))"},{"line_number":893,"context_line":"        # Forbid traits on roots and children"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_47cefcb4","line":890,"updated":"2019-06-20 16:08:14.000000000","message":"this is the test that shows that yes, all parents gets returned","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":11564,"name":"Chris Dent","email":"cdent@anticdent.org","username":"chdent"},"change_message_id":"78ce3ca3c84131ebeaff0b7e6cbc8000fa373c53","unresolved":false,"context_lines":[{"line_number":904,"context_line":""},{"line_number":905,"context_line":"        # Required \u0026 forbidden overlap. No results because it is impossible for"},{"line_number":906,"context_line":"        # one provider to both have and not have a trait."},{"line_number":907,"context_line":"        do_test(required\u003d[avx2_t, ssd_t], forbidden\u003d[ssd_t, geneve_t])"},{"line_number":908,"context_line":""},{"line_number":909,"context_line":""},{"line_number":910,"context_line":"class AllocationCandidatesTestCase(tb.PlacementDbBaseTestCase):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_c7eaecd6","line":907,"updated":"2019-06-20 16:08:14.000000000","message":"There might be a missing test or two here. We need a test for a trait that is not applied to any resource provider.\n\nsomething like:\n\n    hdd_t \u003d trait_obj.Trait.get_by_name(self.ctx, os_traits.storage.disk.HDD)\n    do_test(forbidden\u003d[hdd_t], expected\u003d(1, 2, 3, 4, 5, 6, 7))              \n\nI\u0027ve tried it locally, seems to work as expected.\n\nHaving something like this makes sure the join isn\u0027t weird.","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"e64fc6ec6e60ee4d4ad08c225aa657c06630c280","unresolved":false,"context_lines":[{"line_number":904,"context_line":""},{"line_number":905,"context_line":"        # Required \u0026 forbidden overlap. No results because it is impossible for"},{"line_number":906,"context_line":"        # one provider to both have and not have a trait."},{"line_number":907,"context_line":"        do_test(required\u003d[avx2_t, ssd_t], forbidden\u003d[ssd_t, geneve_t])"},{"line_number":908,"context_line":""},{"line_number":909,"context_line":""},{"line_number":910,"context_line":"class AllocationCandidatesTestCase(tb.PlacementDbBaseTestCase):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_5b36d1b6","line":907,"in_reply_to":"9fb8cfa7_aa20ddf8","updated":"2019-06-20 19:58:33.000000000","message":"Done","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"841af9f27d72d4215734c66da50567a2a9106bee","unresolved":false,"context_lines":[{"line_number":904,"context_line":""},{"line_number":905,"context_line":"        # Required \u0026 forbidden overlap. No results because it is impossible for"},{"line_number":906,"context_line":"        # one provider to both have and not have a trait."},{"line_number":907,"context_line":"        do_test(required\u003d[avx2_t, ssd_t], forbidden\u003d[ssd_t, geneve_t])"},{"line_number":908,"context_line":""},{"line_number":909,"context_line":""},{"line_number":910,"context_line":"class AllocationCandidatesTestCase(tb.PlacementDbBaseTestCase):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9fb8cfa7_aa20ddf8","line":907,"in_reply_to":"9fb8cfa7_c7eaecd6","updated":"2019-06-20 17:29:07.000000000","message":"can do","commit_id":"2aa821db91f08bb6455baed3eb92eda06909f32e"}]}
