)]}'
{"shade/openstackcloud.py":[{"author":{"_account_id":6488,"name":"Clint Byrum","email":"clint@fewbar.com","username":"clint-fewbar"},"change_message_id":"25363d4040819e9a1e0ea41f1d399b7c5f3e1f35","unresolved":false,"context_lines":[{"line_number":1564,"context_line":"        \"\"\""},{"line_number":1565,"context_line":"        return _utils._get_entity(self.search_images, name_or_id, filters)"},{"line_number":1566,"context_line":""},{"line_number":1567,"context_line":"    def save_image(self, name_or_id, output_path\u003dNone):"},{"line_number":1568,"context_line":"        \"\"\"Download an image from glance by name or ID"},{"line_number":1569,"context_line":""},{"line_number":1570,"context_line":"        :param str name_or_id: Name or ID of the image."}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_604a3ac7","line":1567,"updated":"2016-02-15 19:32:40.000000000","message":"This method name seems odd to me. get_image_data or download_image would make more sense to me.","commit_id":"752f69a9cebf4116b306bd0af9cf39aa43a14a6d"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"f4baaecea5066656cfafeef9e6913205f667f581","unresolved":false,"context_lines":[{"line_number":1564,"context_line":"        \"\"\""},{"line_number":1565,"context_line":"        return _utils._get_entity(self.search_images, name_or_id, filters)"},{"line_number":1566,"context_line":""},{"line_number":1567,"context_line":"    def save_image(self, name_or_id, output_path\u003dNone):"},{"line_number":1568,"context_line":"        \"\"\"Download an image from glance by name or ID"},{"line_number":1569,"context_line":""},{"line_number":1570,"context_line":"        :param str name_or_id: Name or ID of the image."}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_a41388b7","line":1567,"in_reply_to":"dae33548_604a3ac7","updated":"2016-02-16 16:02:13.000000000","message":"Done","commit_id":"752f69a9cebf4116b306bd0af9cf39aa43a14a6d"},{"author":{"_account_id":6488,"name":"Clint Byrum","email":"clint@fewbar.com","username":"clint-fewbar"},"change_message_id":"25363d4040819e9a1e0ea41f1d399b7c5f3e1f35","unresolved":false,"context_lines":[{"line_number":1571,"context_line":"        :param output_path: the optional output path to write the image to."},{"line_number":1572,"context_line":""},{"line_number":1573,"context_line":"        :return: the contents of the image or nothing if it is written to a"},{"line_number":1574,"context_line":"                 file"},{"line_number":1575,"context_line":"        \"\"\""},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"        image \u003d self.search_images(name_or_id)[0]"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_404736bb","line":1574,"updated":"2016-02-15 19:32:40.000000000","message":"This is very ambiguous. \"The contents\" is not a type. Can we be more specific? What is that object? We never want to leak objects from the client libraries, so if it is one of those, we need to think about how best to proceed. IMO, instead of returning the object, we should accept either a path, or an fd, and always write to one or the other.","commit_id":"752f69a9cebf4116b306bd0af9cf39aa43a14a6d"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"f4baaecea5066656cfafeef9e6913205f667f581","unresolved":false,"context_lines":[{"line_number":1571,"context_line":"        :param output_path: the optional output path to write the image to."},{"line_number":1572,"context_line":""},{"line_number":1573,"context_line":"        :return: the contents of the image or nothing if it is written to a"},{"line_number":1574,"context_line":"                 file"},{"line_number":1575,"context_line":"        \"\"\""},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"        image \u003d self.search_images(name_or_id)[0]"}],"source_content_type":"text/x-python","patch_set":5,"id":"dae33548_043cf42d","line":1574,"in_reply_to":"dae33548_404736bb","updated":"2016-02-16 16:02:13.000000000","message":"Yeah it\u0027s the response from glanceclient. Looking through the glanceclient code it\u0027s a custom class IterableWithLength that gets returned. (which I\u0027m not sure why it exists at all) So I agree here, I\u0027ll add support for writing to a file object passed into the function and not have any default return.","commit_id":"752f69a9cebf4116b306bd0af9cf39aa43a14a6d"},{"author":{"_account_id":6488,"name":"Clint Byrum","email":"clint@fewbar.com","username":"clint-fewbar"},"change_message_id":"cbcd7b2cb6b6ceef307c0233ef1381226a45603b","unresolved":false,"context_lines":[{"line_number":1574,"context_line":"            image data to. Only write() will be called on this object. Either"},{"line_number":1575,"context_line":"            this or output_path must be specified"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"        :raises: TypeError if neither output_path or output_file is specified"},{"line_number":1578,"context_line":"        \"\"\""},{"line_number":1579,"context_line":""},{"line_number":1580,"context_line":"        image \u003d self.search_images(name_or_id)[0]"}],"source_content_type":"text/x-python","patch_set":6,"id":"dae33548_2f161ea7","line":1577,"updated":"2016-02-16 22:22:46.000000000","message":"I\u0027m not sure it\u0027s what I want. OK, how about this wording for raises instead:\n\n    :raises: TypeError in the event download_image is called without exactly one of either output_path or output_file.\n\nThat seems like it would sit better. :) Also I realize now what I said before isn\u0027t duck typing. :)","commit_id":"914c3f10b9101aa63477416e10e7f6ce9a699985"},{"author":{"_account_id":6488,"name":"Clint Byrum","email":"clint@fewbar.com","username":"clint-fewbar"},"change_message_id":"8f46f970067ff7b9aeed8e810576f89aaa9139f7","unresolved":false,"context_lines":[{"line_number":1574,"context_line":"            image data to. Only write() will be called on this object. Either"},{"line_number":1575,"context_line":"            this or output_path must be specified"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"        :raises: TypeError if neither output_path or output_file is specified"},{"line_number":1578,"context_line":"        \"\"\""},{"line_number":1579,"context_line":""},{"line_number":1580,"context_line":"        image \u003d self.search_images(name_or_id)[0]"}],"source_content_type":"text/x-python","patch_set":6,"id":"dae33548_21e2c59f","line":1577,"updated":"2016-02-16 16:52:37.000000000","message":"So, I tried to reword this and I realized that duck typing may be a better option here. What if we just have one parameter, \u0027output\u0027, and it may be either a string which will be interpreted as the path to a file, or a file-like object to write the data to. That way we can make it a required parameter, and we don\u0027t have to specify a raises at all.","commit_id":"914c3f10b9101aa63477416e10e7f6ce9a699985"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"b1d206f41c4cdb30cbc23f0c20ee4e7598f03afd","unresolved":false,"context_lines":[{"line_number":1574,"context_line":"            image data to. Only write() will be called on this object. Either"},{"line_number":1575,"context_line":"            this or output_path must be specified"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"        :raises: TypeError if neither output_path or output_file is specified"},{"line_number":1578,"context_line":"        \"\"\""},{"line_number":1579,"context_line":""},{"line_number":1580,"context_line":"        image \u003d self.search_images(name_or_id)[0]"}],"source_content_type":"text/x-python","patch_set":6,"id":"dae33548_77964ff1","line":1577,"in_reply_to":"dae33548_21e2c59f","updated":"2016-02-16 17:26:24.000000000","message":"Personally, I\u0027m not a big fan of parameters that can be more than 1 type. But, I can implement it that way if that\u0027s what you want.","commit_id":"914c3f10b9101aa63477416e10e7f6ce9a699985"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"5558667897f53956b7a17ed47b9f441b4f6a139b","unresolved":false,"context_lines":[{"line_number":1574,"context_line":"            image data to. Only write() will be called on this object. Either"},{"line_number":1575,"context_line":"            this or output_path must be specified"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"        :raises: TypeError if neither output_path or output_file is specified"},{"line_number":1578,"context_line":"        \"\"\""},{"line_number":1579,"context_line":""},{"line_number":1580,"context_line":"        image \u003d self.search_images(name_or_id)[0]"}],"source_content_type":"text/x-python","patch_set":6,"id":"dae33548_0f507a5c","line":1577,"in_reply_to":"dae33548_2f161ea7","updated":"2016-02-16 23:05:42.000000000","message":"Done","commit_id":"914c3f10b9101aa63477416e10e7f6ce9a699985"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"6c41d70a793277f05fc0259a8312b6c009dfc948","unresolved":false,"context_lines":[{"line_number":1575,"context_line":"            this or output_path must be specified"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"        :raises: TypeError in the event download_image is called without"},{"line_number":1578,"context_line":"            exactly one of either output_path or output_file."},{"line_number":1579,"context_line":"        \"\"\""},{"line_number":1580,"context_line":"        if output_path is None and output_file is None:"},{"line_number":1581,"context_line":"            raise TypeError(\u0027No output specified, an output path or file \u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_a57fbdde","line":1578,"updated":"2016-02-17 17:19:57.000000000","message":"All of our other API calls explicitly raise OpenStackCloudExceptions. This should follow suit. See below.","commit_id":"682494d8fa3f3db7cbef24a6a2badf45da36954f"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"791274496bd522e1395526216fe38e8dbec17cfd","unresolved":false,"context_lines":[{"line_number":1575,"context_line":"            this or output_path must be specified"},{"line_number":1576,"context_line":""},{"line_number":1577,"context_line":"        :raises: TypeError in the event download_image is called without"},{"line_number":1578,"context_line":"            exactly one of either output_path or output_file."},{"line_number":1579,"context_line":"        \"\"\""},{"line_number":1580,"context_line":"        if output_path is None and output_file is None:"},{"line_number":1581,"context_line":"            raise TypeError(\u0027No output specified, an output path or file \u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_5b2fb287","line":1578,"in_reply_to":"dae33548_a57fbdde","updated":"2016-02-17 17:56:02.000000000","message":"Done","commit_id":"682494d8fa3f3db7cbef24a6a2badf45da36954f"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"6c41d70a793277f05fc0259a8312b6c009dfc948","unresolved":false,"context_lines":[{"line_number":1582,"context_line":"                            \u0027object is necessary to write the image data to\u0027)"},{"line_number":1583,"context_line":"        elif output_path is not None and output_file is not None:"},{"line_number":1584,"context_line":"            raise TypeError(\u0027Both an output path and file object were provided\u0027"},{"line_number":1585,"context_line":"                            \u0027, however only one can be used at once\u0027)"},{"line_number":1586,"context_line":""},{"line_number":1587,"context_line":"        image \u003d self.search_images(name_or_id)[0]"},{"line_number":1588,"context_line":"        image_contents \u003d self.glance_client.images.data(image[\u0027id\u0027])"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_c52761b4","line":1585,"updated":"2016-02-17 17:19:57.000000000","message":"Instead of TypeError, let\u0027s use OpenStackCloudException\u0027s. Reason being, if a user does something wrong, that is what is expected and usually handled (e.g., our OpenStack Ansible modules all expect the shade custom exception).","commit_id":"682494d8fa3f3db7cbef24a6a2badf45da36954f"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"791274496bd522e1395526216fe38e8dbec17cfd","unresolved":false,"context_lines":[{"line_number":1582,"context_line":"                            \u0027object is necessary to write the image data to\u0027)"},{"line_number":1583,"context_line":"        elif output_path is not None and output_file is not None:"},{"line_number":1584,"context_line":"            raise TypeError(\u0027Both an output path and file object were provided\u0027"},{"line_number":1585,"context_line":"                            \u0027, however only one can be used at once\u0027)"},{"line_number":1586,"context_line":""},{"line_number":1587,"context_line":"        image \u003d self.search_images(name_or_id)[0]"},{"line_number":1588,"context_line":"        image_contents \u003d self.glance_client.images.data(image[\u0027id\u0027])"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_7b3276f3","line":1585,"in_reply_to":"dae33548_c52761b4","updated":"2016-02-17 17:56:02.000000000","message":"Done","commit_id":"682494d8fa3f3db7cbef24a6a2badf45da36954f"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"6c41d70a793277f05fc0259a8312b6c009dfc948","unresolved":false,"context_lines":[{"line_number":1584,"context_line":"            raise TypeError(\u0027Both an output path and file object were provided\u0027"},{"line_number":1585,"context_line":"                            \u0027, however only one can be used at once\u0027)"},{"line_number":1586,"context_line":""},{"line_number":1587,"context_line":"        image \u003d self.search_images(name_or_id)[0]"},{"line_number":1588,"context_line":"        image_contents \u003d self.glance_client.images.data(image[\u0027id\u0027])"},{"line_number":1589,"context_line":"        if output_path:"},{"line_number":1590,"context_line":"            with open(output_path, \u0027wb\u0027) as fd:"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_c54e416e","line":1587,"updated":"2016-02-17 17:19:57.000000000","message":"If no images are found, this will throw an exception when trying to access the first element. Best to check for that and raise OSCE exception if not found.","commit_id":"682494d8fa3f3db7cbef24a6a2badf45da36954f"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"791274496bd522e1395526216fe38e8dbec17cfd","unresolved":false,"context_lines":[{"line_number":1584,"context_line":"            raise TypeError(\u0027Both an output path and file object were provided\u0027"},{"line_number":1585,"context_line":"                            \u0027, however only one can be used at once\u0027)"},{"line_number":1586,"context_line":""},{"line_number":1587,"context_line":"        image \u003d self.search_images(name_or_id)[0]"},{"line_number":1588,"context_line":"        image_contents \u003d self.glance_client.images.data(image[\u0027id\u0027])"},{"line_number":1589,"context_line":"        if output_path:"},{"line_number":1590,"context_line":"            with open(output_path, \u0027wb\u0027) as fd:"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_9b881a73","line":1587,"in_reply_to":"dae33548_c54e416e","updated":"2016-02-17 17:56:02.000000000","message":"Done","commit_id":"682494d8fa3f3db7cbef24a6a2badf45da36954f"},{"author":{"_account_id":3099,"name":"David Shrewsbury","email":"dshrewsb@redhat.com","username":"dshrews"},"change_message_id":"6c41d70a793277f05fc0259a8312b6c009dfc948","unresolved":false,"context_lines":[{"line_number":1594,"context_line":"        elif output_file:"},{"line_number":1595,"context_line":"            for chunk in image_contents:"},{"line_number":1596,"context_line":"                output_file.write(chunk)"},{"line_number":1597,"context_line":"            return"},{"line_number":1598,"context_line":""},{"line_number":1599,"context_line":"    def get_floating_ip(self, id, filters\u003dNone):"},{"line_number":1600,"context_line":"        \"\"\"Get a floating IP by ID"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_05330963","line":1597,"updated":"2016-02-17 17:19:57.000000000","message":"This entire if-else should be inside a _utils.shade_exceptions() context manager so that possible file based exceptions (write permission errors, etc) will be thrown as a OSCE exception. E.g.)\n\nwith _utils.shade_exceptions(\"Unable to download image\"):\n  if ...\n  else","commit_id":"682494d8fa3f3db7cbef24a6a2badf45da36954f"},{"author":{"_account_id":5196,"name":"Matthew Treinish","email":"mtreinish@kortar.org","username":"treinish"},"change_message_id":"791274496bd522e1395526216fe38e8dbec17cfd","unresolved":false,"context_lines":[{"line_number":1594,"context_line":"        elif output_file:"},{"line_number":1595,"context_line":"            for chunk in image_contents:"},{"line_number":1596,"context_line":"                output_file.write(chunk)"},{"line_number":1597,"context_line":"            return"},{"line_number":1598,"context_line":""},{"line_number":1599,"context_line":"    def get_floating_ip(self, id, filters\u003dNone):"},{"line_number":1600,"context_line":"        \"\"\"Get a floating IP by ID"}],"source_content_type":"text/x-python","patch_set":7,"id":"dae33548_3b98eebf","line":1597,"in_reply_to":"dae33548_05330963","updated":"2016-02-17 17:56:02.000000000","message":"Done","commit_id":"682494d8fa3f3db7cbef24a6a2badf45da36954f"}]}
