)]}'
{"sushy_tools/emulator/drivers/libvirtdriver.py":[{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":133,"context_line":"        :returns: current power state as *On* or *Off* `str` or `None`"},{"line_number":134,"context_line":"            if power state can\u0027t be determined"},{"line_number":135,"context_line":"        \"\"\""},{"line_number":136,"context_line":"        domain \u003d self._get_domain(identity, readonly\u003dTrue)"},{"line_number":137,"context_line":"        return \u0027On\u0027 if domain.isActive() else \u0027Off\u0027"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def set_power_state(self, identity, state):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_21daf7e5","line":136,"updated":"2018-10-31 13:25:34.000000000","message":"okay, so what if the cached domain was changed by something else? e.g. the vm was powered off from inside?","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":133,"context_line":"        :returns: current power state as *On* or *Off* `str` or `None`"},{"line_number":134,"context_line":"            if power state can\u0027t be determined"},{"line_number":135,"context_line":"        \"\"\""},{"line_number":136,"context_line":"        domain \u003d self._get_domain(identity, readonly\u003dTrue)"},{"line_number":137,"context_line":"        return \u0027On\u0027 if domain.isActive() else \u0027Off\u0027"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"    def set_power_state(self, identity, state):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_39bf60fe","line":136,"in_reply_to":"3f79a3b5_21daf7e5","updated":"2018-11-02 13:01:46.000000000","message":"Unless decorated with `memoize(permanet_cache)`, the memoization lasts for the duration of a single REST API call.\n\nThere is indeed a chance for an external power flip during the REST API call, but it seems that such a short term caching does not greatly raises the chances for racing...\n\nThe openstackbmc script has permanent cache which comes with the precaution that the user must ensure that VMs are only touched through this script.\n\nCaching is not that important with IPMI because its power status call requires just one nova call. It\u0027s much heavier with Redfish because we can\u0027t ask Redfish for just power status - for that we need to pull the whole ComputerSystem document which needs many nova calls to get reasonably populated.","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":230,"context_line":""},{"line_number":231,"context_line":"        try:"},{"line_number":232,"context_line":"            with libvirt_open(self._uri) as conn:"},{"line_number":233,"context_line":"                conn.defineXML(ET.tostring(tree).decode(\u0027utf-8\u0027))"},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"        except libvirt.libvirtError as e:"},{"line_number":236,"context_line":"            msg \u003d (\u0027Error changing boot device at libvirt URI \"%(uri)s\": \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_c1e8e37f","line":233,"updated":"2018-10-31 13:25:34.000000000","message":"++ to the question.","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":27909,"name":"Aija Jauntēva","email":"code@clusums.eu","username":"ajya"},"change_message_id":"0ea2fbb7edecb49c94c6ee9813d4b0002e2a8915","unresolved":false,"context_lines":[{"line_number":230,"context_line":""},{"line_number":231,"context_line":"        try:"},{"line_number":232,"context_line":"            with libvirt_open(self._uri) as conn:"},{"line_number":233,"context_line":"                conn.defineXML(ET.tostring(tree).decode(\u0027utf-8\u0027))"},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"        except libvirt.libvirtError as e:"},{"line_number":236,"context_line":"            msg \u003d (\u0027Error changing boot device at libvirt URI \"%(uri)s\": \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_eb5bae1f","line":233,"range":{"start_line":233,"start_character":21,"end_line":233,"end_character":30},"updated":"2018-10-29 13:28:21.000000000","message":"Q: as this is making changes to domain XML (here and other \"set\" methods that change data), how does this invalidate or update the cache of \"domain\"? (same for novadriver update methods)","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":230,"context_line":""},{"line_number":231,"context_line":"        try:"},{"line_number":232,"context_line":"            with libvirt_open(self._uri) as conn:"},{"line_number":233,"context_line":"                conn.defineXML(ET.tostring(tree).decode(\u0027utf-8\u0027))"},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"        except libvirt.libvirtError as e:"},{"line_number":236,"context_line":"            msg \u003d (\u0027Error changing boot device at libvirt URI \"%(uri)s\": \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_19e5c407","line":233,"in_reply_to":"3f79a3b5_c1e8e37f","updated":"2018-11-02 13:01:46.000000000","message":"Done","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":230,"context_line":""},{"line_number":231,"context_line":"        try:"},{"line_number":232,"context_line":"            with libvirt_open(self._uri) as conn:"},{"line_number":233,"context_line":"                conn.defineXML(ET.tostring(tree).decode(\u0027utf-8\u0027))"},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"        except libvirt.libvirtError as e:"},{"line_number":236,"context_line":"            msg \u003d (\u0027Error changing boot device at libvirt URI \"%(uri)s\": \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_f9e9e8e3","line":233,"range":{"start_line":233,"start_character":21,"end_line":233,"end_character":30},"in_reply_to":"3f79a3b5_eb5bae1f","updated":"2018-11-02 13:01:46.000000000","message":"The thing is that by default the `memoize` cache only lasts for essentially one REST API call. With the code below, the cache will only be reused within the `with`context manager:\n\n        with virt_driver() as driver:\n            return flask.render_template(\n                \u0027system.json\u0027, identity\u003didentity,\n                uuid\u003ddriver.uuid(identity),\n                power_state\u003ddriver.get_power_state(identity),\n                total_memory_gb\u003ddriver.get_total_memory(identity),\n                total_cpus\u003ddriver.get_total_cpus(identity),\n                boot_source_target\u003ddriver.get_boot_device(identity),\n                boot_source_mode\u003ddriver.get_boot_mode(identity)\n            )\n\nSo the sure way to hit an invalid cache entry would be to do read and write REST API calls in one shot.\n\nThe user can still achieve long-term (permanent) caching by passing `permanent_cache` dict to the decorator. This should not be done for the methods that operate on volatile data.","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":16635,"name":"deray","email":"debayan.ray@gmail.com","username":"deray"},"change_message_id":"9116a334def81e55d6474bd5d18e8ac6f7105f0e","unresolved":false,"context_lines":[{"line_number":19,"context_line":"import xml.etree.ElementTree as ET"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from sushy_tools.emulator.drivers.base import AbstractDriver"},{"line_number":22,"context_line":"from sushy_tools.emulator.drivers.memoize import memoize"},{"line_number":23,"context_line":"from sushy_tools import error"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"try:"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_b61f005c","line":22,"range":{"start_line":22,"start_character":0,"end_line":22,"end_character":56},"updated":"2018-12-03 13:14:29.000000000","message":"just to maintain consistency import the module and not the method.\n\n    from sushy_tools.emulator.drivers import memoize\n    ...\n    @memoize.memoize()","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"7718ea41c1a12ed2b49f4dd3ed7ad6a8428c9983","unresolved":false,"context_lines":[{"line_number":19,"context_line":"import xml.etree.ElementTree as ET"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from sushy_tools.emulator.drivers.base import AbstractDriver"},{"line_number":22,"context_line":"from sushy_tools.emulator.drivers.memoize import memoize"},{"line_number":23,"context_line":"from sushy_tools import error"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"try:"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_ae9b1676","line":22,"range":{"start_line":22,"start_character":0,"end_line":22,"end_character":56},"in_reply_to":"3f79a3b5_b61f005c","updated":"2018-12-04 09:26:07.000000000","message":"Done","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"}],"sushy_tools/emulator/drivers/memoize.py":[{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":12,"context_line":"#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"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":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone, purge_cache\u003dNone):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_41fcd33f","line":15,"updated":"2018-10-31 13:25:34.000000000","message":"also please do not import functions, only modules (why does pep8 even allow it here?)","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":15519,"name":"Iury Gregory Melo Ferreira","display_name":"Iury Gregory","email":"iurygregory@gmail.com","username":"iurygregory"},"change_message_id":"69f60d77188129abcac3441ac3d2cd3034ffd8c7","unresolved":false,"context_lines":[{"line_number":12,"context_line":"#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"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":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone, purge_cache\u003dNone):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_b05f61e2","line":15,"updated":"2018-10-29 13:10:18.000000000","message":"nit: maybe skip one line just to keep same pattern other files have?","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":12,"context_line":"#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"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":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone, purge_cache\u003dNone):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_2730abb7","line":15,"in_reply_to":"3f79a3b5_41fcd33f","updated":"2018-11-02 13:01:46.000000000","message":"Done","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":12,"context_line":"#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"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":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone, purge_cache\u003dNone):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_07f1ef00","line":15,"in_reply_to":"3f79a3b5_b05f61e2","updated":"2018-11-02 13:01:46.000000000","message":"Done","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":24,"context_line":"        created `dict`."},{"line_number":25,"context_line":"    :param purge_cache: if given, this should be a reference to"},{"line_number":26,"context_line":"        a callable to purge all cache entries previously collected"},{"line_number":27,"context_line":"        by calling that callable."},{"line_number":28,"context_line":"    :return:"},{"line_number":29,"context_line":"    \"\"\""},{"line_number":30,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_61f9cf4d","line":27,"updated":"2018-10-31 13:25:34.000000000","message":"I cannot quite get how this is related to memoize() decorator. in what case should it be set?","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":24,"context_line":"        created `dict`."},{"line_number":25,"context_line":"    :param purge_cache: if given, this should be a reference to"},{"line_number":26,"context_line":"        a callable to purge all cache entries previously collected"},{"line_number":27,"context_line":"        by calling that callable."},{"line_number":28,"context_line":"    :return:"},{"line_number":29,"context_line":"    \"\"\""},{"line_number":30,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_464fdbbe","line":27,"in_reply_to":"3f79a3b5_61f9cf4d","updated":"2018-11-02 13:01:46.000000000","message":"That can be the other function that (when called) invalidates the cache for the decorated function.","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":27909,"name":"Aija Jauntēva","email":"code@clusums.eu","username":"ajya"},"change_message_id":"0ea2fbb7edecb49c94c6ee9813d4b0002e2a8915","unresolved":false,"context_lines":[{"line_number":25,"context_line":"    :param purge_cache: if given, this should be a reference to"},{"line_number":26,"context_line":"        a callable to purge all cache entries previously collected"},{"line_number":27,"context_line":"        by calling that callable."},{"line_number":28,"context_line":"    :return:"},{"line_number":29,"context_line":"    \"\"\""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    def decorator(method):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_50392d9f","line":28,"range":{"start_line":28,"start_character":4,"end_line":28,"end_character":12},"updated":"2018-10-29 13:28:21.000000000","message":"is this missing doc on return?","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":25,"context_line":"    :param purge_cache: if given, this should be a reference to"},{"line_number":26,"context_line":"        a callable to purge all cache entries previously collected"},{"line_number":27,"context_line":"        by calling that callable."},{"line_number":28,"context_line":"    :return:"},{"line_number":29,"context_line":"    \"\"\""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    def decorator(method):"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_671463eb","line":28,"range":{"start_line":28,"start_character":4,"end_line":28,"end_character":12},"in_reply_to":"3f79a3b5_50392d9f","updated":"2018-11-02 13:01:46.000000000","message":"Done","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":45,"context_line":"            if method not in cache:"},{"line_number":46,"context_line":"                cache[method] \u003d {}"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"            cache \u003d cache[method]"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"            if purge_cache:"},{"line_number":51,"context_line":"                cache.pop(purge_cache, None)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_01f6db5f","line":48,"updated":"2018-10-31 13:25:34.000000000","message":"nit: these 3 lines can be replaced with\n\n cache \u003d cache.setdefault(method, {})","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":45,"context_line":"            if method not in cache:"},{"line_number":46,"context_line":"                cache[method] \u003d {}"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"            cache \u003d cache[method]"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"            if purge_cache:"},{"line_number":51,"context_line":"                cache.pop(purge_cache, None)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_a6e6efae","line":48,"in_reply_to":"3f79a3b5_01f6db5f","updated":"2018-11-02 13:01:46.000000000","message":"Done","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":51,"context_line":"                cache.pop(purge_cache, None)"},{"line_number":52,"context_line":"                return method(self, *args, **kwargs)"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"            key \u003d frozenset(args), frozenset(kwargs)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"            try:"},{"line_number":57,"context_line":"                return cache[key]"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_21f3d76f","line":54,"updated":"2018-10-31 13:25:34.000000000","message":"frozenset(kwargs) captures only names, but not values. I don\u0027t think this is what you want, you probably meants frozenset(kwargs.items()), which will blow up if any argument value is not hashable.","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":51,"context_line":"                cache.pop(purge_cache, None)"},{"line_number":52,"context_line":"                return method(self, *args, **kwargs)"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"            key \u003d frozenset(args), frozenset(kwargs)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"            try:"},{"line_number":57,"context_line":"                return cache[key]"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_66021710","line":54,"in_reply_to":"3f79a3b5_21f3d76f","updated":"2018-11-02 13:01:46.000000000","message":"Done","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":16635,"name":"deray","email":"debayan.ray@gmail.com","username":"deray"},"change_message_id":"9116a334def81e55d6474bd5d18e8ac6f7105f0e","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone):"},{"line_number":19,"context_line":"    \"\"\"Cache the return value of the decorated method."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param permament_cache: a `dict` like object to use as a cache."}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_56a1ccf3","line":18,"range":{"start_line":18,"start_character":4,"end_line":18,"end_character":11},"updated":"2018-12-03 13:14:29.000000000","message":"Briskly thinking if this can also be leveraged even for static emulator\u0027s get method. If yes, then we may need to place this in some util.py module under base tree, ``sushy_tools``.","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":16635,"name":"deray","email":"debayan.ray@gmail.com","username":"deray"},"change_message_id":"9116a334def81e55d6474bd5d18e8ac6f7105f0e","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone):"},{"line_number":19,"context_line":"    \"\"\"Cache the return value of the decorated method."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param permament_cache: a `dict` like object to use as a cache."}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_0b91f150","line":18,"range":{"start_line":18,"start_character":4,"end_line":18,"end_character":11},"updated":"2018-12-03 13:14:29.000000000","message":"can we have some unit test cases for this ``memoize``?","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"7718ea41c1a12ed2b49f4dd3ed7ad6a8428c9983","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone):"},{"line_number":19,"context_line":"    \"\"\"Cache the return value of the decorated method."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param permament_cache: a `dict` like object to use as a cache."}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_64a51db3","line":18,"range":{"start_line":18,"start_character":4,"end_line":18,"end_character":11},"in_reply_to":"3f79a3b5_0b91f150","updated":"2018-12-04 09:26:07.000000000","message":"Done","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"7718ea41c1a12ed2b49f4dd3ed7ad6a8428c9983","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone):"},{"line_number":19,"context_line":"    \"\"\"Cache the return value of the decorated method."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param permament_cache: a `dict` like object to use as a cache."}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_6ee17ece","line":18,"range":{"start_line":18,"start_character":4,"end_line":18,"end_character":11},"in_reply_to":"3f79a3b5_56a1ccf3","updated":"2018-12-04 09:26:07.000000000","message":"I am not sure that would make any noticeable difference... Here it does because OpenStack/public clouds can be quite slow. ;-)","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":16635,"name":"deray","email":"debayan.ray@gmail.com","username":"deray"},"change_message_id":"9116a334def81e55d6474bd5d18e8ac6f7105f0e","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            else:"},{"line_number":40,"context_line":"                cache \u003d permament_cache"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"            cache \u003d cache.setdefault(method, {})"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"            key \u003d frozenset(args), frozenset(kwargs)"},{"line_number":45,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_ab98fd7b","line":42,"range":{"start_line":42,"start_character":12,"end_line":42,"end_character":17},"updated":"2018-12-03 13:14:29.000000000","message":"nit: name of the variable could be ``method_cache``","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"7718ea41c1a12ed2b49f4dd3ed7ad6a8428c9983","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            else:"},{"line_number":40,"context_line":"                cache \u003d permament_cache"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"            cache \u003d cache.setdefault(method, {})"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"            key \u003d frozenset(args), frozenset(kwargs)"},{"line_number":45,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_ee690e5b","line":42,"range":{"start_line":42,"start_character":12,"end_line":42,"end_character":17},"in_reply_to":"3f79a3b5_ab98fd7b","updated":"2018-12-04 09:26:07.000000000","message":"Done","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from functools import wraps"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone):"},{"line_number":19,"context_line":"    \"\"\"Cache the return value of the decorated method."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param permament_cache: a `dict` like object to use as a cache."}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_c4fe7106","line":18,"range":{"start_line":18,"start_character":12,"end_line":18,"end_character":27},"updated":"2018-12-04 09:52:33.000000000","message":"permanent_cache","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"},{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":18,"context_line":"def memoize(permament_cache\u003dNone):"},{"line_number":19,"context_line":"    \"\"\"Cache the return value of the decorated method."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param permament_cache: a `dict` like object to use as a cache."},{"line_number":22,"context_line":"        If not given, the `._cache` attribute would be added to"},{"line_number":23,"context_line":"        the object of the decorated method pointing to a newly"},{"line_number":24,"context_line":"        created `dict`."}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_bf133e5a","line":21,"range":{"start_line":21,"start_character":11,"end_line":21,"end_character":26},"updated":"2018-12-04 09:52:33.000000000","message":"ditto","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"},{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":29,"context_line":""},{"line_number":30,"context_line":"        @wraps(method)"},{"line_number":31,"context_line":"        def wrapped(self, *args, **kwargs):"},{"line_number":32,"context_line":"            if permament_cache is None:"},{"line_number":33,"context_line":"                try:"},{"line_number":34,"context_line":"                    cache \u003d self._cache"},{"line_number":35,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_9f2202a5","line":32,"range":{"start_line":32,"start_character":15,"end_line":32,"end_character":30},"updated":"2018-12-04 09:52:33.000000000","message":"ditto","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"},{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":37,"context_line":"                    cache \u003d self._cache \u003d {}"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"            else:"},{"line_number":40,"context_line":"                cache \u003d permament_cache"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"            method_cache \u003d cache.setdefault(method, {})"},{"line_number":43,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_ff3216f4","line":40,"range":{"start_line":40,"start_character":24,"end_line":40,"end_character":39},"updated":"2018-12-04 09:52:33.000000000","message":"ditto","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"}],"sushy_tools/emulator/drivers/novadriver.py":[{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":72,"context_line":""},{"line_number":73,"context_line":"        raise FishyError(msg)"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    @memoize(permament_cache\u003d{})"},{"line_number":76,"context_line":"    def _get_flavor(self, identity):"},{"line_number":77,"context_line":"        instance \u003d self._get_instance(identity)"},{"line_number":78,"context_line":"        return self._cc.get_flavor(instance.flavor.id)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_81e2eb9b","line":75,"updated":"2018-10-31 13:25:34.000000000","message":"This is very confusing. I\u0027m not sure what it achieves even after reading the docstring of memoize. Is it like per method cache instead of per instance? why?","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":72,"context_line":""},{"line_number":73,"context_line":"        raise FishyError(msg)"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    @memoize(permament_cache\u003d{})"},{"line_number":76,"context_line":"    def _get_flavor(self, identity):"},{"line_number":77,"context_line":"        instance \u003d self._get_instance(identity)"},{"line_number":78,"context_line":"        return self._cc.get_flavor(instance.flavor.id)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_970d1b42","line":75,"in_reply_to":"3f79a3b5_81e2eb9b","updated":"2018-11-02 13:01:46.000000000","message":"Done","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    def _get_server_metadata(self, identity):"},{"line_number":86,"context_line":"        return self._cc.compute.get_server_metadata(identity).to_dict()"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    @memoize(purge_cache\u003d_get_server_metadata)"},{"line_number":89,"context_line":"    def _set_server_metadata(self, identity, metadata):"},{"line_number":90,"context_line":"        self._cc.compute.set_server_metadata(identity, metadata)"},{"line_number":91,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_a1e7e7ab","line":88,"updated":"2018-10-31 13:25:34.000000000","message":"okay, now I see how it works. still super confusing, let\u0027s maybe clear the cache explicitly? something like\n\n self._get_server_metadata.invalidate_cache()","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    def _get_server_metadata(self, identity):"},{"line_number":86,"context_line":"        return self._cc.compute.get_server_metadata(identity).to_dict()"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    @memoize(purge_cache\u003d_get_server_metadata)"},{"line_number":89,"context_line":"    def _set_server_metadata(self, identity, metadata):"},{"line_number":90,"context_line":"        self._cc.compute.set_server_metadata(identity, metadata)"},{"line_number":91,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_f716cf57","line":88,"in_reply_to":"3f79a3b5_a1e7e7ab","updated":"2018-11-02 13:01:46.000000000","message":"I tried to achieve the same differently, but could not put thing together in a nice fashion. So I just removed this cache purging feature for now. ;-)","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        raise error.FishyError(msg)"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"    @memoize.memoize(permament_cache\u003dPERMANENT_CACHE)"},{"line_number":81,"context_line":"    def _get_flavor(self, identity):"},{"line_number":82,"context_line":"        instance \u003d self._get_instance(identity)"},{"line_number":83,"context_line":"        return self._cc.get_flavor(instance.flavor.id)"}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_5f6a2ab4","line":80,"range":{"start_line":80,"start_character":21,"end_line":80,"end_character":36},"updated":"2018-12-04 09:52:33.000000000","message":"permanent_cache","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"},{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        instance \u003d self._get_instance(identity)"},{"line_number":83,"context_line":"        return self._cc.get_flavor(instance.flavor.id)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    @memoize.memoize(permament_cache\u003dPERMANENT_CACHE)"},{"line_number":86,"context_line":"    def _get_image_info(self, identity):"},{"line_number":87,"context_line":"        return self._cc.image.find_image(identity)"},{"line_number":88,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_9f952296","line":85,"range":{"start_line":85,"start_character":21,"end_line":85,"end_character":36},"updated":"2018-12-04 09:52:33.000000000","message":"ditto","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"}],"sushy_tools/emulator/main.py":[{"author":{"_account_id":10239,"name":"Dmitry Tantsur","email":"dtantsur@protonmail.com","username":"dtantsur"},"change_message_id":"ce14d048ec1b03e5d12bc6712240056de1253523","unresolved":false,"context_lines":[{"line_number":303,"context_line":""},{"line_number":304,"context_line":""},{"line_number":305,"context_line":"def main():"},{"line_number":306,"context_line":"    global Driver"},{"line_number":307,"context_line":""},{"line_number":308,"context_line":"    args \u003d parse_args()"},{"line_number":309,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_e1eddf8d","line":306,"updated":"2018-10-31 13:25:34.000000000","message":"nit: global constants should be all upper-case. just variables should be all lower-case.","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":303,"context_line":""},{"line_number":304,"context_line":""},{"line_number":305,"context_line":"def main():"},{"line_number":306,"context_line":"    global Driver"},{"line_number":307,"context_line":""},{"line_number":308,"context_line":"    args \u003d parse_args()"},{"line_number":309,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_b9fff067","line":306,"in_reply_to":"3f79a3b5_e1eddf8d","updated":"2018-11-02 13:01:46.000000000","message":"Done, though it\u0027s not quite a constant. And it\u0027s a class. ;-)","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":16635,"name":"deray","email":"debayan.ray@gmail.com","username":"deray"},"change_message_id":"9116a334def81e55d6474bd5d18e8ac6f7105f0e","unresolved":false,"context_lines":[{"line_number":47,"context_line":"                    app.logger.error(\u0027Nova driver not loaded\u0027)"},{"line_number":48,"context_line":"                    sys.exit(1)"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"                DRIVER \u003d novadriver.OpenStackDriver.initialize("},{"line_number":51,"context_line":"                    os.environ[\u0027OS_CLOUD\u0027])"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_76f72890","line":50,"range":{"start_line":50,"start_character":16,"end_line":50,"end_character":22},"updated":"2018-12-03 13:14:29.000000000","message":"May be I couldn\u0027t intently look through the objective, but I am failing to understand why we are moving towards loading the appropriate driver class with respective options and instantiating the class every time for each call. What overhead the earlier approach had which as I understand was instantiating the driver class once for the first call of the API and then using that cached driver instance for every other call. Have I missed anything here or have I not understood the code properly? Is the intent altogether different?","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"7718ea41c1a12ed2b49f4dd3ed7ad6a8428c9983","unresolved":false,"context_lines":[{"line_number":47,"context_line":"                    app.logger.error(\u0027Nova driver not loaded\u0027)"},{"line_number":48,"context_line":"                    sys.exit(1)"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"                DRIVER \u003d novadriver.OpenStackDriver.initialize("},{"line_number":51,"context_line":"                    os.environ[\u0027OS_CLOUD\u0027])"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_0ea9ea24","line":50,"range":{"start_line":50,"start_character":16,"end_line":50,"end_character":22},"in_reply_to":"3f79a3b5_76f72890","updated":"2018-12-04 09:26:07.000000000","message":"Right, that\u0027s confusing! The idea is to use driver objects to maintain short-term, single-session cache inside these objects.\n\nI\u0027ve added this docstring to explain the intention:\n\n\n        Since drivers may need to cache thing short-term. The emulator\n        instantiates the driver every time it serves a client query.\n\n        Driver objects can cache whenever it makes sense for the duration\n        of a single session. It is guaranteed that the driver object will\n        never be reused for any other session.\n        \n        The `initialize` method is provided to set up the driver in a way\n        that would affect all the subsequent sessions.\n\nDoes it make sense?","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":16635,"name":"deray","email":"debayan.ray@gmail.com","username":"deray"},"change_message_id":"9116a334def81e55d6474bd5d18e8ac6f7105f0e","unresolved":false,"context_lines":[{"line_number":62,"context_line":"                        os.environ.get(\u0027SUSHY_EMULATOR_LIBVIRT_URL\u0027))"},{"line_number":63,"context_line":"                )"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"                app.logger.debug(\u0027Running with %s\u0027, DRIVER.driver)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        return decorated_func(*args, **kwargs)"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_967e8418","line":65,"range":{"start_line":65,"start_character":16,"end_line":65,"end_character":66},"updated":"2018-12-03 13:14:29.000000000","message":"this line should be out of if-else block, it seems!","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"7718ea41c1a12ed2b49f4dd3ed7ad6a8428c9983","unresolved":false,"context_lines":[{"line_number":62,"context_line":"                        os.environ.get(\u0027SUSHY_EMULATOR_LIBVIRT_URL\u0027))"},{"line_number":63,"context_line":"                )"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"                app.logger.debug(\u0027Running with %s\u0027, DRIVER.driver)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        return decorated_func(*args, **kwargs)"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_8e289a9e","line":65,"range":{"start_line":65,"start_character":16,"end_line":65,"end_character":66},"in_reply_to":"3f79a3b5_967e8418","updated":"2018-12-04 09:26:07.000000000","message":"Ah, let\u0027s blame insane rebasing...","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":16635,"name":"deray","email":"debayan.ray@gmail.com","username":"deray"},"change_message_id":"9116a334def81e55d6474bd5d18e8ac6f7105f0e","unresolved":false,"context_lines":[{"line_number":70,"context_line":""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"@contextlib.contextmanager"},{"line_number":73,"context_line":"def virt_driver():"},{"line_number":74,"context_line":"    yield DRIVER()"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_f6f9f8c5","line":73,"range":{"start_line":73,"start_character":4,"end_line":73,"end_character":15},"updated":"2018-12-03 13:14:29.000000000","message":"can\u0027t we memoize this also?","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"7718ea41c1a12ed2b49f4dd3ed7ad6a8428c9983","unresolved":false,"context_lines":[{"line_number":70,"context_line":""},{"line_number":71,"context_line":""},{"line_number":72,"context_line":"@contextlib.contextmanager"},{"line_number":73,"context_line":"def virt_driver():"},{"line_number":74,"context_line":"    yield DRIVER()"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_6903b80c","line":73,"range":{"start_line":73,"start_character":4,"end_line":73,"end_character":15},"in_reply_to":"3f79a3b5_f6f9f8c5","updated":"2018-12-04 09:26:07.000000000","message":"No! This would undermine the purpose of short-lived driver objects! I hope my explanation above makes sense.","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":16635,"name":"deray","email":"debayan.ray@gmail.com","username":"deray"},"change_message_id":"9116a334def81e55d6474bd5d18e8ac6f7105f0e","unresolved":false,"context_lines":[{"line_number":313,"context_line":""},{"line_number":314,"context_line":"    args \u003d parse_args()"},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"    if args.os_cloud:"},{"line_number":317,"context_line":"        if not novadriver.is_loaded:"},{"line_number":318,"context_line":"            app.logger.error(\u0027Nova driver not loaded\u0027)"},{"line_number":319,"context_line":"            return 1"},{"line_number":320,"context_line":""},{"line_number":321,"context_line":"        DRIVER \u003d novadriver.OpenStackDriver.initialize(args.os_cloud)"},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"    else:"},{"line_number":324,"context_line":"        if not libvirtdriver.is_loaded:"},{"line_number":325,"context_line":"            app.logger.error(\u0027libvirt driver not loaded\u0027)"},{"line_number":326,"context_line":"            return 1"},{"line_number":327,"context_line":""},{"line_number":328,"context_line":"        DRIVER \u003d libvirtdriver.LibvirtDriver.initialize(args.libvirt_uri)"},{"line_number":329,"context_line":""},{"line_number":330,"context_line":"    app.logger.debug(\u0027Running with %s\u0027, DRIVER.driver)"},{"line_number":331,"context_line":""},{"line_number":332,"context_line":"    ssl_context \u003d None"},{"line_number":333,"context_line":"    if args.ssl_certificate and args.ssl_key:"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_9693e44d","line":330,"range":{"start_line":316,"start_character":4,"end_line":330,"end_character":54},"updated":"2018-12-03 13:14:29.000000000","message":"portion of ``init_virt_driver`` method seems quite matching with this part. Can\u0027t this plucked out and reused in both these cases by passing ``libvirt`` and ``novadriver`` based options?","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"7718ea41c1a12ed2b49f4dd3ed7ad6a8428c9983","unresolved":false,"context_lines":[{"line_number":313,"context_line":""},{"line_number":314,"context_line":"    args \u003d parse_args()"},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"    if args.os_cloud:"},{"line_number":317,"context_line":"        if not novadriver.is_loaded:"},{"line_number":318,"context_line":"            app.logger.error(\u0027Nova driver not loaded\u0027)"},{"line_number":319,"context_line":"            return 1"},{"line_number":320,"context_line":""},{"line_number":321,"context_line":"        DRIVER \u003d novadriver.OpenStackDriver.initialize(args.os_cloud)"},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"    else:"},{"line_number":324,"context_line":"        if not libvirtdriver.is_loaded:"},{"line_number":325,"context_line":"            app.logger.error(\u0027libvirt driver not loaded\u0027)"},{"line_number":326,"context_line":"            return 1"},{"line_number":327,"context_line":""},{"line_number":328,"context_line":"        DRIVER \u003d libvirtdriver.LibvirtDriver.initialize(args.libvirt_uri)"},{"line_number":329,"context_line":""},{"line_number":330,"context_line":"    app.logger.debug(\u0027Running with %s\u0027, DRIVER.driver)"},{"line_number":331,"context_line":""},{"line_number":332,"context_line":"    ssl_context \u003d None"},{"line_number":333,"context_line":"    if args.ssl_certificate and args.ssl_key:"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f79a3b5_6951780c","line":330,"range":{"start_line":316,"start_character":4,"end_line":330,"end_character":54},"in_reply_to":"3f79a3b5_9693e44d","updated":"2018-12-04 09:26:07.000000000","message":"Perhaps, we should see how much of the readability it would add...\n\nLet\u0027s do that in a separate patch?","commit_id":"642029ab8683cf61c069c062888fd3224a3fb66e"}],"sushy_tools/tests/unit/emulator/test_libvirt.py":[{"author":{"_account_id":15519,"name":"Iury Gregory Melo Ferreira","display_name":"Iury Gregory","email":"iurygregory@gmail.com","username":"iurygregory"},"change_message_id":"69f60d77188129abcac3441ac3d2cd3034ffd8c7","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"        # This enables libvirt driver"},{"line_number":30,"context_line":"        main.Driver \u003d None"},{"line_number":31,"context_line":"        TestDriver \u003d LibvirtDriver.initialize()"},{"line_number":32,"context_line":"        self.test_driver \u003d TestDriver()"},{"line_number":33,"context_line":"        super(EmulatorTestCase, self).setUp()"},{"line_number":34,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_905fc54b","line":31,"updated":"2018-10-29 13:10:18.000000000","message":"just wondering if would be necessary create this new variable","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":"        # This enables libvirt driver"},{"line_number":30,"context_line":"        main.Driver \u003d None"},{"line_number":31,"context_line":"        TestDriver \u003d LibvirtDriver.initialize()"},{"line_number":32,"context_line":"        self.test_driver \u003d TestDriver()"},{"line_number":33,"context_line":"        super(EmulatorTestCase, self).setUp()"},{"line_number":34,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_d9274c1d","line":31,"in_reply_to":"3f79a3b5_905fc54b","updated":"2018-11-02 13:01:46.000000000","message":"Well, technically - no. But hopefully that improves readability. ;-)","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"}],"sushy_tools/tests/unit/emulator/test_main.py":[{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"301dfcf3a69b57afbca0be36e67e8eda3e6cf1c9","unresolved":false,"context_lines":[{"line_number":16,"context_line":"from sushy_tools.emulator import main"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"@mock.patch.object(main, \u0027DRIVER\u0027)  # This enables libvirt driver"},{"line_number":20,"context_line":"class EmulatorTestCase(base.BaseTestCase):"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    name \u003d \u0027QEmu-fedora-i686\u0027"}],"source_content_type":"text/x-python","patch_set":15,"id":"9fdfeff1_e7556151","line":19,"range":{"start_line":19,"start_character":33,"end_line":19,"end_character":34},"updated":"2019-02-13 14:31:23.000000000","message":"we ought to use autospec\u003dTrue here unless the tests just functionally don\u0027t work at all with it.","commit_id":"82901923478c8baa2938cbde4946f3856e760ed6"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"e15bd967af5f7530d8c24797135dd8de3a89d932","unresolved":false,"context_lines":[{"line_number":16,"context_line":"from sushy_tools.emulator import main"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"@mock.patch.object(main, \u0027DRIVER\u0027)  # This enables libvirt driver"},{"line_number":20,"context_line":"class EmulatorTestCase(base.BaseTestCase):"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"    name \u003d \u0027QEmu-fedora-i686\u0027"}],"source_content_type":"text/x-python","patch_set":15,"id":"9fdfeff1_29a7b8be","line":19,"range":{"start_line":19,"start_character":33,"end_line":19,"end_character":34},"in_reply_to":"9fdfeff1_e7556151","updated":"2019-02-13 17:40:05.000000000","message":"Hmm, the original value for this global variable is None, at least on the first run. It will later be assigned a driver object. So I am not sure we could autopspec here because that would autopspec None, not the driver object...\n\nThis global variable business is shaky.","commit_id":"82901923478c8baa2938cbde4946f3856e760ed6"}],"sushy_tools/tests/unit/emulator/test_memoize.py":[{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":51,"context_line":""},{"line_number":52,"context_line":"    def test_external_cache(self):"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        permament_cache \u003d {}"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        class Driver(object):"},{"line_number":57,"context_line":"            call_count \u003d 0"}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_7f7b667c","line":54,"range":{"start_line":54,"start_character":8,"end_line":54,"end_character":23},"updated":"2018-12-04 09:52:33.000000000","message":"permanent_cache","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"},{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        class Driver(object):"},{"line_number":57,"context_line":"            call_count \u003d 0"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"            @memoize.memoize(permament_cache\u003dpermament_cache)"},{"line_number":60,"context_line":"            def fun(self, *args, **kwargs):"},{"line_number":61,"context_line":"                self.call_count +\u003d 1"},{"line_number":62,"context_line":"                return args, kwargs"}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_bf881e6c","line":59,"range":{"start_line":59,"start_character":45,"end_line":59,"end_character":60},"updated":"2018-12-04 09:52:33.000000000","message":"ditto","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"},{"author":{"_account_id":29209,"name":"Dhanuka Warusadura","email":"csx@tuta.io","username":"dnuka"},"change_message_id":"9f2f276ac60ba447737ff673f34a5ba5f7527faf","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        class Driver(object):"},{"line_number":57,"context_line":"            call_count \u003d 0"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"            @memoize.memoize(permament_cache\u003dpermament_cache)"},{"line_number":60,"context_line":"            def fun(self, *args, **kwargs):"},{"line_number":61,"context_line":"                self.call_count +\u003d 1"},{"line_number":62,"context_line":"                return args, kwargs"}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_ff8e9679","line":59,"range":{"start_line":59,"start_character":29,"end_line":59,"end_character":44},"updated":"2018-12-04 09:52:33.000000000","message":"ditto","commit_id":"1cb1764f618f516b73d3af9dc8adda184510ff22"}],"sushy_tools/tests/unit/emulator/third_party_driver_mocks.py":[{"author":{"_account_id":15519,"name":"Iury Gregory Melo Ferreira","display_name":"Iury Gregory","email":"iurygregory@gmail.com","username":"iurygregory"},"change_message_id":"69f60d77188129abcac3441ac3d2cd3034ffd8c7","unresolved":false,"context_lines":[{"line_number":62,"context_line":"    openstack \u003d mock.MagicMock(spec_set\u003dmock_specs.OPENSTACKSDK_SPEC)"},{"line_number":63,"context_line":"    sys.modules[\u0027openstack\u0027] \u003d openstack"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"\u0027sushy_tools.emulator.drivers.libvirtdriver\u0027"},{"line_number":66,"context_line":"if \u0027sushy_tools.emulator.drivers.novadriver\u0027 in sys.modules:"},{"line_number":67,"context_line":"    six.moves.reload_module("},{"line_number":68,"context_line":"        sys.modules[\u0027sushy_tools.emulator.drivers.novadriver\u0027])"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_d0269dcc","line":65,"updated":"2018-10-29 13:10:18.000000000","message":"I don\u0027t think this is necessary, if possible could you explain? Thanks","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"},{"author":{"_account_id":26340,"name":"Ilya Etingof","email":"etingof@gmail.com","username":"etingof"},"change_message_id":"1a4567fe22beaacefa35e191eddd0303863b05c1","unresolved":false,"context_lines":[{"line_number":62,"context_line":"    openstack \u003d mock.MagicMock(spec_set\u003dmock_specs.OPENSTACKSDK_SPEC)"},{"line_number":63,"context_line":"    sys.modules[\u0027openstack\u0027] \u003d openstack"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"\u0027sushy_tools.emulator.drivers.libvirtdriver\u0027"},{"line_number":66,"context_line":"if \u0027sushy_tools.emulator.drivers.novadriver\u0027 in sys.modules:"},{"line_number":67,"context_line":"    six.moves.reload_module("},{"line_number":68,"context_line":"        sys.modules[\u0027sushy_tools.emulator.drivers.novadriver\u0027])"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f79a3b5_5cd1ea59","line":65,"in_reply_to":"3f79a3b5_d0269dcc","updated":"2018-11-02 13:01:46.000000000","message":"Yes, so here we simulate module import even if the module itself is not available. By the time we run this code, the above-mentioned module may have tried to load the very same module and failed silently. Since we may have injected the mocked module here (e.g. if the real module does not exist), we need the other module that we know depends on the mocked module to import it once again.\n\nMay be we can move this condition under the if statement on line #61 though.","commit_id":"6cc27b9a712f6f9a68c0c46e6bd8406a8b5e7144"}]}
