)]}'
{"openstack/tests/volume/v2/test_proxy.py":[{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":33,"context_line":"        self.proxy \u003d _proxy.Proxy(self.session)"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"class Test_types(TestVolumeProxy, base.TestTransportBase):"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    TEST_URL \u003d fakes.FakeAuthenticator.ENDPOINT"},{"line_number":39,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_afc3b455","line":36,"updated":"2015-02-10 14:28:01.000000000","message":"Is there no other way other than having multiple base classes?","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":41,"context_line":"        super(Test_types, self).setUp()"},{"line_number":42,"context_line":"        self.transport \u003d transport.Transport(accept\u003dtransport.JSON)"},{"line_number":43,"context_line":"        self.auth \u003d fakes.FakeAuthenticator()"},{"line_number":44,"context_line":"        self.session \u003d session.Session(self.transport, self.auth)"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"        self.proxy \u003d _proxy.Proxy(self.session)"},{"line_number":47,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_eabafadf","line":44,"updated":"2015-02-10 14:28:01.000000000","message":"test_proxy_base has a mock session\n\nConstructing these end to end tests are extremely painful to maintain.  We end up testing all sorts of code that is not in the proxy.  I know using mocks and testing just the code in the method looks dumb sometimes, but there is something to be gained by it.\n\nI like the idea of automated functional tests a lot better to test things end to end.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"}],"openstack/tests/volume/v2/test_type.py":[{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":43,"context_line":"        self.assertEqual(FAKE_ID, sot.id)"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_create(self):"},{"line_number":46,"context_line":"        sot \u003d type.Type.existing(**TYPE)"},{"line_number":47,"context_line":"        self.assertEqual(TYPE[\"id\"], sot.id)"},{"line_number":48,"context_line":"        self.assertEqual(TYPE[\"extra_specs\"], sot.extra_specs)"},{"line_number":49,"context_line":"        self.assertEqual(TYPE[\"name\"], sot.name)"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_6a136a5c","line":46,"updated":"2015-02-10 14:28:01.000000000","message":"What are we gaining by testing existing here over just the constructor?  All we really have to test is the properties since this class doesn\u0027t override either.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"}],"openstack/volume/v2/_proxy.py":[{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":27,"context_line":"        :rtype: :class:`~openstack.volume.v2.type.Type`"},{"line_number":28,"context_line":"        \"\"\""},{"line_number":29,"context_line":"        # Note: We retrieve types by page instead of list because the volume"},{"line_number":30,"context_line":"        # service doesn\u0027t paginate them."},{"line_number":31,"context_line":"        for type in _type.Type.page(self.session):"},{"line_number":32,"context_line":"            yield _type.Type.existing(**type)"},{"line_number":33,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_60138b5c","line":30,"updated":"2015-02-10 14:28:01.000000000","message":"This problem should be pushed to the resource level.  If list is broken in the resource, fix it there.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":41,"context_line":"        \"\"\""},{"line_number":42,"context_line":"        try:"},{"line_number":43,"context_line":"            type \u003d _type.Type.get_by_id(self.session, id)"},{"line_number":44,"context_line":"        except exceptions.HttpException as exc:"},{"line_number":45,"context_line":"            if exc.status_code \u003d\u003d 404:"},{"line_number":46,"context_line":"                type \u003d None"},{"line_number":47,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_a062e3d5","line":44,"updated":"2015-02-10 14:28:01.000000000","message":"Currently, all our other gets throw 404 if it isn\u0027t found, if we are going to change that, let\u0027s do that in a different change. and change it for everything.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":49,"context_line":""},{"line_number":50,"context_line":"        return type"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"    def volumes(self, detailed\u003dFalse):"},{"line_number":53,"context_line":"        \"\"\"Get all available volumes"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        :returns: A generator of volumes"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_2010b300","line":52,"updated":"2015-02-10 14:28:01.000000000","message":"At least most of the other proxies call list_resources, so this would be list_volumes.  I know object store probably does something different, but it is different this proxy fits the mold more with all the rest of them.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"dbd2718a94394c0de7d37e21730d3cc833274265","unresolved":false,"context_lines":[{"line_number":49,"context_line":""},{"line_number":50,"context_line":"        return type"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"    def volumes(self, detailed\u003dFalse):"},{"line_number":53,"context_line":"        \"\"\"Get all available volumes"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"        :returns: A generator of volumes"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_a763cf18","line":52,"in_reply_to":"da86d52c_2010b300","updated":"2015-02-10 17:59:50.000000000","message":"I\u0027m not worried about what other proxies are doing at the moment since I believe everything is up for grabs right now while we figure out how to build a great interface. Until we\u0027ve built applications and had some user feedback and looked at how things work with each other, nothing is set in stone. Everything will at some point follow the same conventions, one way or another, but I think that\u0027s what we\u0027re trying to figure out as we go along, and we\u0027re a long way away from having to freeze the APIs or consider backwards compatibility.\n\nMy personal take on this naming style comes from the fact that it\u0027s describing what you\u0027re receiving, not what it\u0027s doing, based on how it is used. Since it\u0027s returning an iterator, specifically a generator, it\u0027s either used in a for-loop or consumed by something that knows how to follow the iterator protocol. Naming this a plural we obviously agree with, but the \"list_\" prefix can be tied to at least two things which are not directly relevant to this operation at this level.\n\n    for volume in conn.volume.volumes():\n        ...\n\n    big_vols \u003d filter(lambda vol: vol.size \u003e 50, conn.volume.volumes())\n\nOn one hand, a \"list_\" prefix would be immediately confusing to people who expect it to return a list, as it violates the principle of least astonishment. You can\u0027t do the following list behavior regardless of how this method is named:\n\n    conn.volume.list_volumes()[0] # I know there\u0027s only one volume, just grab it.\n\nOne the other, a \"list_\" prefix can be seen as bringing ideas in from lower levels. Resource.list is correctly named because within that level, it deals with a server returning a list of resources. However, I believe the connection level aims to be a higher-level Python interface, where the details of how something works below or on the server aren\u0027t relevant. Within the connection level, we\u0027re already several levels removed from working with a list, and we\u0027ve converted that list into Resources, which we\u0027ve then converted into some Resource-subclass, and they\u0027ve been yielded to us in the connection level, so we\u0027re a ways away from that concept in my opinion.\n\nI also think there\u0027s precedent for skipping a prefix on a method like this, based on how things have moved in Python 3, which libraries are starting to follow. The most visible example is that the dictionary type used to have iterkeys and itervalues but moved to keys and values.\n\nFWIW, I\u0027m also thinking about the get_volume name on the singular call. I don\u0027t think I want that to just become volume(), but maybe.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        :returns: A generator of volumes"},{"line_number":56,"context_line":"        :rtype: :class:`~openstack.volume.v2.volume.Volume`"},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        volume_type \u003d _volume.VolumeDetail if detailed else _volume.Volume"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        for volume in volume_type.page(self.session):"},{"line_number":61,"context_line":"            yield volume_type.existing(**volume)"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_00be4fd4","line":58,"updated":"2015-02-10 14:28:01.000000000","message":"Realistically, list_volumes and list_volume_details methods would be better.  I know it doesn\u0027t hide the lameness of the underlying implementation, but it fewer moving parts.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"dbd2718a94394c0de7d37e21730d3cc833274265","unresolved":false,"context_lines":[{"line_number":55,"context_line":"        :returns: A generator of volumes"},{"line_number":56,"context_line":"        :rtype: :class:`~openstack.volume.v2.volume.Volume`"},{"line_number":57,"context_line":"        \"\"\""},{"line_number":58,"context_line":"        volume_type \u003d _volume.VolumeDetail if detailed else _volume.Volume"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        for volume in volume_type.page(self.session):"},{"line_number":61,"context_line":"            yield volume_type.existing(**volume)"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_87016b08","line":58,"in_reply_to":"da86d52c_00be4fd4","updated":"2015-02-10 17:59:50.000000000","message":"But they\u0027re fundamentally the same thing. I think this is a great place for us to make things nicer to work with by passing a bool instead of working with a separate method.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        for volume in volume_type.page(self.session):"},{"line_number":61,"context_line":"            yield volume_type.existing(**volume)"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def create_volume(self, size\u003dNone, name\u003dNone, type\u003dNone, image\u003dNone,"},{"line_number":64,"context_line":"                      bootable\u003dNone, source_volume\u003dNone,"},{"line_number":65,"context_line":"                      availability_zone\u003dNone, description\u003dNone,"},{"line_number":66,"context_line":"                      metadata\u003dNone, volume\u003dNone):"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_bb8e96ce","line":63,"updated":"2015-02-10 14:28:01.000000000","message":"These creates and updates should support **kwargs so we can support extensions without changes.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"dbd2718a94394c0de7d37e21730d3cc833274265","unresolved":false,"context_lines":[{"line_number":60,"context_line":"        for volume in volume_type.page(self.session):"},{"line_number":61,"context_line":"            yield volume_type.existing(**volume)"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"    def create_volume(self, size\u003dNone, name\u003dNone, type\u003dNone, image\u003dNone,"},{"line_number":64,"context_line":"                      bootable\u003dNone, source_volume\u003dNone,"},{"line_number":65,"context_line":"                      availability_zone\u003dNone, description\u003dNone,"},{"line_number":66,"context_line":"                      metadata\u003dNone, volume\u003dNone):"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_da097a2d","line":63,"in_reply_to":"da86d52c_bb8e96ce","updated":"2015-02-10 17:59:50.000000000","message":"Good point, will address that.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":96,"context_line":"        :raises ValueError: if you have not passed in a ``volume``"},{"line_number":97,"context_line":"                            and the ``size`` parameter is ``None``."},{"line_number":98,"context_line":"        \"\"\""},{"line_number":99,"context_line":"        if not isinstance(volume, _volume.Volume):"},{"line_number":100,"context_line":"            if size is None:"},{"line_number":101,"context_line":"                raise ValueError(\"missing required size argument\")"},{"line_number":102,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_7b341dde","line":99,"updated":"2015-02-10 14:28:01.000000000","message":"Not sure why we support conn.volume.create_volume(volume) when the user could just conn.create(volume)","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"dbd2718a94394c0de7d37e21730d3cc833274265","unresolved":false,"context_lines":[{"line_number":96,"context_line":"        :raises ValueError: if you have not passed in a ``volume``"},{"line_number":97,"context_line":"                            and the ``size`` parameter is ``None``."},{"line_number":98,"context_line":"        \"\"\""},{"line_number":99,"context_line":"        if not isinstance(volume, _volume.Volume):"},{"line_number":100,"context_line":"            if size is None:"},{"line_number":101,"context_line":"                raise ValueError(\"missing required size argument\")"},{"line_number":102,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_3ac9b679","line":99,"in_reply_to":"da86d52c_7b341dde","updated":"2015-02-10 17:59:50.000000000","message":"I\u0027m honestly not the biggest fan of that conn.create(volume) way. I get why it\u0027s there, and I get why it may remain there, but while working in a sea of code around volumes, I think it\u0027s much more natural to use operations off of the volume namespace.\n\nWhile *we* know that conn.create is just calling POST on whatever resource you pass into it, lacking an explicit namespace would make me do a double take when seeing it in code.\n\nI think the following reads more clearly as to what is going on:\n\n    old_vol \u003d conn.volume.get_volume(1)\n    new_vol \u003d copy.copy(old_vol)\n    new_vol.size \u003d 100 # bump up the size\n    conn.volume.create_volume(new_vol)","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":156,"context_line":""},{"line_number":157,"context_line":"        :rtype: None"},{"line_number":158,"context_line":"        \"\"\""},{"line_number":159,"context_line":"        volume \u003d _volume.Volume.from_id(volume)"},{"line_number":160,"context_line":"        volume.delete(self.session)"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"    def create_type(self, name, **extra_specs):"}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_3b13860e","line":159,"updated":"2015-02-10 14:28:01.000000000","message":"One line these deletes maybe","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"}],"openstack/volume/v2/volume.py":[{"author":{"_account_id":8736,"name":"Terry Howe","email":"terrylhowe@gmail.com","username":"terrylhowe"},"change_message_id":"4a84c115a5864d1425fe5189a9059583e37f8fc9","unresolved":false,"context_lines":[{"line_number":72,"context_line":"    created \u003d resource.prop(\"created_at\")"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"class VolumeDetail(Volume):"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    base_path \u003d \"/volumes/detail\""},{"line_number":78,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_bb8bf666","line":75,"updated":"2015-02-10 14:28:01.000000000","message":"Our example code will hit this automatically if it is in volume_detail.py","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"},{"author":{"_account_id":8257,"name":"Brian Curtin","email":"brian@python.org","username":"briancurtin"},"change_message_id":"dbd2718a94394c0de7d37e21730d3cc833274265","unresolved":false,"context_lines":[{"line_number":72,"context_line":"    created \u003d resource.prop(\"created_at\")"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"class VolumeDetail(Volume):"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    base_path \u003d \"/volumes/detail\""},{"line_number":78,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"da86d52c_da0c1a97","line":75,"in_reply_to":"da86d52c_bb8bf666","updated":"2015-02-10 17:59:50.000000000","message":"Given the inheritance and how these two classes just work together in use, organizationally I prefer that they live together. I would rather not organize code based on using the examples. In-real-life usage will be covered by a full example and the user guide.","commit_id":"0d26e7c8d2f780a272352a1a9eddf275d2892a6e"}]}
