)]}'
{"openstack/common/fileutils.py":[{"author":{"_account_id":385,"name":"Jason Kölker","email":"jason@koelker.net","username":"jason-koelker"},"change_message_id":"3292530507d755cfb2a0cd98430ff6af0cd37b09","unresolved":false,"context_lines":[{"line_number":40,"context_line":"            raise"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"def read_cached_file(filename, cache_info, reload_func\u003dNone):"},{"line_number":44,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    :param cache_info: dictionary to hold opaque cache."}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAOn%2F%2FrMA%3D","line":43,"updated":"2013-04-29 16:16:20.000000000","message":"Instead of passing in the cache_info dict, I\u0027m thinking a decorator should be used to manage the cache dict.","commit_id":"acdd0664c5990cb310f87ef653650bbede951cd1"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"f435afcad6f8c0381b7f991154175341f5582281","unresolved":false,"context_lines":[{"line_number":40,"context_line":"            raise"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"def read_cached_file(filename, cache_info, reload_func\u003dNone):"},{"line_number":44,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    :param cache_info: dictionary to hold opaque cache."}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAOn%2F%2FrJc%3D","line":43,"in_reply_to":"AAAAOn%2F%2FrMA%3D","updated":"2013-04-29 16:40:50.000000000","message":"mhh, indeed, that would make it cleaner. I think that, as far as there\u0027s a way to clear the cache (passing \u0027fore_reload\u0027) it is ok.\n\nNOTE: this function was shamelessly copied from nova.","commit_id":"acdd0664c5990cb310f87ef653650bbede951cd1"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"32f581097aa00b75caeda6f07fd6cac2ef1ce3f2","unresolved":false,"context_lines":[{"line_number":45,"context_line":"def read_cached_file(filename, reload_func\u003dNone, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param reload_func: optional function to be called with data when"},{"line_number":49,"context_line":"                        file is reloaded due to a modification."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAOn%2F%2Fpyk%3D","line":48,"updated":"2013-04-30 15:27:53.000000000","message":"This callback API feels like it is mixing responsibility for managing the cache with responsibility for doing something when the data is updated. It would be simpler to just return a tuple with a boolean saying whether the data was fresh or not, and let the caller decide if it needs to take the action.","commit_id":"d28b0f096f869b49cd6a71bf804274f572da4453"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"7ef7fbba7aad45de94fd68da635f3f3f6f104a9f","unresolved":false,"context_lines":[{"line_number":45,"context_line":"def read_cached_file(filename, reload_func\u003dNone, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param reload_func: optional function to be called with data when"},{"line_number":49,"context_line":"                        file is reloaded due to a modification."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAOn%2F%2FptA%3D","line":48,"in_reply_to":"AAAAOn%2F%2Fpyk%3D","updated":"2013-04-30 15:59:45.000000000","message":"Agreed, will do!","commit_id":"d28b0f096f869b49cd6a71bf804274f572da4453"},{"author":{"_account_id":1247,"name":"Mark McLoughlin","email":"markmc@redhat.com","username":"markmc"},"change_message_id":"dc60802026fbd851fe626865e12dca7b05599849","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            raise"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def read_cached_file(filename, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAOn%2F%2FlVU%3D","line":45,"updated":"2013-05-02 21:59:34.000000000","message":"I think I\u0027d be happier if the API user could pass in the file cache dict to use rather than library having the global","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"881868430f72955be97a1da629941f513243a7d9","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            raise"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def read_cached_file(filename, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAOn%2F%2FkoM%3D","line":45,"in_reply_to":"AAAAOn%2F%2Fk5w%3D","updated":"2013-05-03 13:28:38.000000000","message":"mmh, TBH, that seems a bit over-engineered to me. I\u0027d simply use a dict.\n\nI don\u0027t like having globals around the code but it makes a bit of sense here. If the caller wants to \"ignore the cache\" it could simply use force_reload\u003dTrue.","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":385,"name":"Jason Kölker","email":"jason@koelker.net","username":"jason-koelker"},"change_message_id":"5ee49a0f1fb308c13043bafb6937da8fb6a48960","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            raise"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def read_cached_file(filename, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAOn%2F%2Fk5w%3D","line":45,"in_reply_to":"AAAAOn%2F%2Fk8o%3D","updated":"2013-05-03 07:32:54.000000000","message":"Earlier I was thinking just a decorator wrapped function that defined the cache within its scope and returned in the inner cache function, but I\u0027m now thinking a cache manager object would fit better for everyone something along the lines of:\n\n class FileCache(object):\n      def __init__(self):\n          self.cache \u003d collections.defaultdict(dict))\n\n      def __call__(self, filename, force_reload\u003dFalse):\n          ...\n          return (reloaded, self.cache[\u0027data\u0027])\n\nread_cached_file \u003d FileCache()\n\nCourse so far this looks like the classic don\u0027t use classes example ;). But perhaps we can figure out a better api on the class for getting the reloaded attribute of a particular file. Donno, its late over here ;).","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"3a1f61acbe3a6ff9d37b543e66d3af4de72f1a26","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            raise"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def read_cached_file(filename, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAOn%2F%2Fk8o%3D","line":45,"in_reply_to":"AAAAOn%2F%2FlVU%3D","updated":"2013-05-03 06:37:11.000000000","message":"That was the main idea, I then got a comment from Jason and thought that having it global would be cleaner to let this be managed by the library itself.\n\nWhat would be the benefit of passing a dictionary instead of letting the lib manage it? \n\nWhat about having both? If the caller passes the cache dict then that can be used, otherwise the global one would be used.","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"45e0971cca3f44e3b3cc66ec3bbb4c5ed07d9ec0","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            raise"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def read_cached_file(filename, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAOn%2F%2FTxc%3D","line":45,"updated":"2013-05-15 07:19:22.000000000","message":"Do we need a semaphore for this method?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"5a515a36924b4a07db73fcfeaea46ec7cb5e41a4","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            raise"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def read_cached_file(filename, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2Fzk%3D","line":45,"in_reply_to":"AAAAOn%2F%2FTxc%3D","updated":"2013-05-15 08:36:09.000000000","message":"That\u0027s a good question. TBH, I\u0027d prefer keeping this function simpler and leave the locking part to the caller.","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"45e0971cca3f44e3b3cc66ec3bbb4c5ed07d9ec0","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    global _FILE_CACHE"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    if force_reload:"},{"line_number":55,"context_line":"        _FILE_CACHE.pop(filename, None)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"},{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAOn%2F%2FTxM%3D","line":55,"updated":"2013-05-15 07:19:22.000000000","message":"Since pop() is same as \"x \u003d s[i]; del s[i]; return x\" and we don\u0027t care about the return value, wouldn\u0027t just a \"del _FILE_CACHE[filename]\" be better?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"e463640ff7e42bb2148b55941fb3f2b715e99f24","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    global _FILE_CACHE"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    if force_reload:"},{"line_number":55,"context_line":"        _FILE_CACHE.pop(filename, None)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"},{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2Fws%3D","line":55,"in_reply_to":"AAAAO3%2F%2F%2F1A%3D","updated":"2013-05-15 08:39:40.000000000","message":"Doesn\u0027t pop on a empty key also raise a KeyError?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"460278d90618a3404d91a7c50c023df33bdbf4de","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    global _FILE_CACHE"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    if force_reload:"},{"line_number":55,"context_line":"        _FILE_CACHE.pop(filename, None)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"},{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2B%2F8%3D","line":55,"in_reply_to":"AAAAO3%2F%2F%2FA0%3D","updated":"2013-05-15 15:21:13.000000000","message":"Ah didn\u0027t realize there was a none","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":679,"name":"Kevin L. Mitchell","email":"klmitch@mit.edu","username":"klmitch"},"change_message_id":"b87eab0ef9cae1bf89652840305202a65790ccfe","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    global _FILE_CACHE"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    if force_reload:"},{"line_number":55,"context_line":"        _FILE_CACHE.pop(filename, None)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"},{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2FA0%3D","line":55,"in_reply_to":"AAAAO3%2F%2F%2Fws%3D","updated":"2013-05-15 15:17:57.000000000","message":"It does, unless you provide the default value, which is the case here.","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"5a515a36924b4a07db73fcfeaea46ec7cb5e41a4","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    global _FILE_CACHE"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    if force_reload:"},{"line_number":55,"context_line":"        _FILE_CACHE.pop(filename, None)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"},{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2F1A%3D","line":55,"in_reply_to":"AAAAOn%2F%2FTxM%3D","updated":"2013-05-15 08:36:09.000000000","message":"filename may not exist, that\u0027s why pop is being used.","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"f4b4f550282602125b4e86036a983a7351930033","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"},{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime !\u003d cache_info.get(\u0027mtime\u0027):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAOn%2F%2FVCU%3D","line":59,"updated":"2013-05-14 15:11:09.000000000","message":"where do we set cache_info back into _FILE_CACHE? does setdefault do it for us?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"45e0971cca3f44e3b3cc66ec3bbb4c5ed07d9ec0","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"},{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime !\u003d cache_info.get(\u0027mtime\u0027):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAOn%2F%2FTyM%3D","line":59,"in_reply_to":"AAAAOn%2F%2FVCU%3D","updated":"2013-05-15 07:19:22.000000000","message":"Yes setdefault() returns the same object as get() but sets the second argument as the value for the key before returning if key is absent.","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"f4b4f550282602125b4e86036a983a7351930033","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime !\u003d cache_info.get(\u0027mtime\u0027):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"},{"line_number":63,"context_line":"        with open(filename) as fap:"},{"line_number":64,"context_line":"            cache_info[\u0027data\u0027] \u003d fap.read()"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAOn%2F%2FU%2F0%3D","line":61,"updated":"2013-05-14 15:11:09.000000000","message":"should this check for newer file instead of just a different time?\n\n    mtime \u003e cache_info.get(\u0027mtime\u0027)l","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"5a515a36924b4a07db73fcfeaea46ec7cb5e41a4","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime !\u003d cache_info.get(\u0027mtime\u0027):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"},{"line_number":63,"context_line":"        with open(filename) as fap:"},{"line_number":64,"context_line":"            cache_info[\u0027data\u0027] \u003d fap.read()"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2F0U%3D","line":61,"in_reply_to":"AAAAOn%2F%2FU%2F0%3D","updated":"2013-05-15 08:36:09.000000000","message":"mmhh, I guess we could just check for newer files. I can\u0027t think about a case where doing that would be an issue.\n\nConsider it done!","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"6ee1d56465cabee6fac48f4a857a82a4a1e97e0e","unresolved":false,"context_lines":[{"line_number":51,"context_line":"    \"\"\""},{"line_number":52,"context_line":"    global _FILE_CACHE"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    if force_reload:"},{"line_number":55,"context_line":"        _FILE_CACHE.pop(filename, None)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAO3%2F%2F%2FwQ%3D","line":54,"updated":"2013-05-15 08:41:32.000000000","message":"Then this part should be\n\n if force_reload and filename in _FILE_CACHE:\n     del _FILE_CACHE[filename]","commit_id":"dfaeea855255b004c24c826590b22fafb5e250b4"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"880cff977f803db4e16177550b2cd1665e850123","unresolved":false,"context_lines":[{"line_number":51,"context_line":"    \"\"\""},{"line_number":52,"context_line":"    global _FILE_CACHE"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    if force_reload:"},{"line_number":55,"context_line":"        _FILE_CACHE.pop(filename, None)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    reloaded \u003d False"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAO3%2F%2F%2Fu0%3D","line":54,"in_reply_to":"AAAAO3%2F%2F%2FwQ%3D","updated":"2013-05-15 08:59:19.000000000","message":"mmh, isn\u0027t that the same? I mean, it\u0027s a bit more explicit but does the same thing. \n\nConsider it done.","commit_id":"dfaeea855255b004c24c826590b22fafb5e250b4"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"183669c7efea181aa024451b141882dc0977419c","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime \u003e cache_info.get(\u0027mtime\u0027, 0):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"},{"line_number":63,"context_line":"        with open(filename) as fap:"},{"line_number":64,"context_line":"            cache_info[\u0027data\u0027] \u003d fap.read()"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAO3%2F%2F%2Fvg%3D","line":61,"updated":"2013-05-15 08:45:37.000000000","message":"Is there a case where cache_info doesn\u0027t have key \u0027mtime\u0027? well maybe if fap suddenly disappears then it might happen. Then do we need exception handling on line 63?","commit_id":"dfaeea855255b004c24c826590b22fafb5e250b4"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"c80c5f8d27651ab661bee86571a3e7fb1860e23f","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime \u003e cache_info.get(\u0027mtime\u0027, 0):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"},{"line_number":63,"context_line":"        with open(filename) as fap:"},{"line_number":64,"context_line":"            cache_info[\u0027data\u0027] \u003d fap.read()"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAO3%2F%2F%2FuY%3D","line":61,"in_reply_to":"AAAAO3%2F%2F%2Fuw%3D","updated":"2013-05-15 09:01:32.000000000","message":"But my point is that \"not cache_info\" covers that case.","commit_id":"dfaeea855255b004c24c826590b22fafb5e250b4"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"880cff977f803db4e16177550b2cd1665e850123","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime \u003e cache_info.get(\u0027mtime\u0027, 0):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"},{"line_number":63,"context_line":"        with open(filename) as fap:"},{"line_number":64,"context_line":"            cache_info[\u0027data\u0027] \u003d fap.read()"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAO3%2F%2F%2Fuw%3D","line":61,"in_reply_to":"AAAAO3%2F%2F%2Fvg%3D","updated":"2013-05-15 08:59:19.000000000","message":"If filename didn\u0027t exist (so cache_info \u003d\u003d {}) then mtime doesn\u0027t exist.","commit_id":"dfaeea855255b004c24c826590b22fafb5e250b4"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"f7b174a9301bd8eab006e44fa3fcde564e77b6c6","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            raise"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def read_cached_file(filename, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAO3%2F%2F%2Frs%3D","line":45,"updated":"2013-05-15 09:35:24.000000000","message":"Any thoughts about using lockutils.synchronized here?","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"0600a6bd43790cc31f56b67809296e441803adef","unresolved":false,"context_lines":[{"line_number":42,"context_line":"            raise"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def read_cached_file(filename, force_reload\u003dFalse):"},{"line_number":46,"context_line":"    \"\"\"Read from a file if it has been modified."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param force_reload: Whether to reload the file."}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAO3%2F%2F%2Fl0%3D","line":45,"in_reply_to":"AAAAO3%2F%2F%2Frs%3D","updated":"2013-05-15 10:26:38.000000000","message":"mmh, I\u0027m not against but not sure we need it. My other concern is that using synchronize here means we\u0027ve got to add another dependency for something that, most likely, will be handled by the caller as well.","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"f7b174a9301bd8eab006e44fa3fcde564e77b6c6","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime \u003e cache_info.get(\u0027mtime\u0027, 0):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"},{"line_number":63,"context_line":"        with open(filename) as fap:"},{"line_number":64,"context_line":"            cache_info[\u0027data\u0027] \u003d fap.read()"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAO3%2F%2F%2Frg%3D","line":61,"updated":"2013-05-15 09:35:24.000000000","message":"so what I wanted to say was... even if filename did not exist, there won\u0027t be a case where cache_info only has \u0027data\u0027 and not \u0027mtime\u0027. Therefore \"not cache_info\" will handle the case where cache_info is empty. \n\nAlso if policy.json file suddenly disappears, shouldn\u0027t we log something in a try/catch on line 63? Wouldn\u0027t happen that often but sounds kind of scary.","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"0600a6bd43790cc31f56b67809296e441803adef","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    mtime \u003d os.path.getmtime(filename)"},{"line_number":59,"context_line":"    cache_info \u003d _FILE_CACHE.setdefault(filename, {})"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    if not cache_info or mtime \u003e cache_info.get(\u0027mtime\u0027, 0):"},{"line_number":62,"context_line":"        LOG.debug(_(\"Reloading cached file %s\") % filename)"},{"line_number":63,"context_line":"        with open(filename) as fap:"},{"line_number":64,"context_line":"            cache_info[\u0027data\u0027] \u003d fap.read()"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAO3%2F%2F%2Fl4%3D","line":61,"in_reply_to":"AAAAO3%2F%2F%2Frg%3D","updated":"2013-05-15 10:26:38.000000000","message":"mtime: ahhh gotcha! missed that.\n\ntry/except: mmh, indeed, that seems like something we\u0027d like to catch. What should happen in that case? Should we clear the cache or keep the old state? (I think #2 would be better)","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"}],"openstack/common/policy.py":[{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"32f581097aa00b75caeda6f07fd6cac2ef1ce3f2","unresolved":false,"context_lines":[{"line_number":233,"context_line":"        \"\"\""},{"line_number":234,"context_line":"        Checks authorization of a rule against the target and credentials."},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"        :param rule: The rule to evaluate."},{"line_number":237,"context_line":"        :param target: As much information about the object being operated"},{"line_number":238,"context_line":"                    on as possible, as a dictionary."},{"line_number":239,"context_line":"        :param creds: As much information about the user performing the"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAOn%2F%2FpxU%3D","line":236,"updated":"2013-04-30 15:27:53.000000000","message":"It looks like \"rule\" can be one of several different things. What types are allowed?","commit_id":"d28b0f096f869b49cd6a71bf804274f572da4453"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"7ef7fbba7aad45de94fd68da635f3f3f6f104a9f","unresolved":false,"context_lines":[{"line_number":233,"context_line":"        \"\"\""},{"line_number":234,"context_line":"        Checks authorization of a rule against the target and credentials."},{"line_number":235,"context_line":""},{"line_number":236,"context_line":"        :param rule: The rule to evaluate."},{"line_number":237,"context_line":"        :param target: As much information about the object being operated"},{"line_number":238,"context_line":"                    on as possible, as a dictionary."},{"line_number":239,"context_line":"        :param creds: As much information about the user performing the"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAOn%2F%2Fps8%3D","line":236,"in_reply_to":"AAAAOn%2F%2FpxU%3D","updated":"2013-04-30 15:59:45.000000000","message":"Will specify!","commit_id":"d28b0f096f869b49cd6a71bf804274f572da4453"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"32f581097aa00b75caeda6f07fd6cac2ef1ce3f2","unresolved":false,"context_lines":[{"line_number":873,"context_line":"            return match \u003d\u003d unicode(creds[self.kind])"},{"line_number":874,"context_line":"        return False"},{"line_number":875,"context_line":""},{"line_number":876,"context_line":"ENFORCER \u003d Enforcer()"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAOn%2F%2Fpw0%3D","line":876,"updated":"2013-04-30 15:27:53.000000000","message":"I think this is a mistake. If an app wants to implement a global enforcer, that\u0027s up to the app, but the library should not be creating globals at all.","commit_id":"d28b0f096f869b49cd6a71bf804274f572da4453"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"e34d18698b9fbf94e8b0b9d8f002974b09528513","unresolved":false,"context_lines":[{"line_number":873,"context_line":"            return match \u003d\u003d unicode(creds[self.kind])"},{"line_number":874,"context_line":"        return False"},{"line_number":875,"context_line":""},{"line_number":876,"context_line":"ENFORCER \u003d Enforcer()"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAOn%2F%2Fph0%3D","line":876,"in_reply_to":"AAAAOn%2F%2Fpr0%3D","updated":"2013-04-30 16:59:45.000000000","message":"We ran into quite a bit of trouble in ceilometer updating to oslo.config when it moved into a library because of that global object. I would prefer not to repeat the problems. So, if an app creates a global then that\u0027s up to the developers there, but the common libraries should avoid forcing that pattern.","commit_id":"d28b0f096f869b49cd6a71bf804274f572da4453"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"7ef7fbba7aad45de94fd68da635f3f3f6f104a9f","unresolved":false,"context_lines":[{"line_number":873,"context_line":"            return match \u003d\u003d unicode(creds[self.kind])"},{"line_number":874,"context_line":"        return False"},{"line_number":875,"context_line":""},{"line_number":876,"context_line":"ENFORCER \u003d Enforcer()"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAOn%2F%2Fpr0%3D","line":876,"in_reply_to":"AAAAOn%2F%2Fpw0%3D","updated":"2013-04-30 15:59:45.000000000","message":"mmh I partially agree. TBH, I followed oslo.config steps here. The idea is to let applications to simply do:\n\n    from openstack.common import policy \n\nThe above will provide the app an easy-to-access/share enforcer instance.\n\nThat being said, I think it would be fair enough to define the app enforcer in the main __init__ (?) and then use it like:\n\n    import myapp \n    myapp.ENFORCER\n\nI think most applications will have to have a policy.py anyway - they, most likely, will want to define their own checkers - but for those that want to use default checkers, I think the above example could be enough.\n\nThoughts?","commit_id":"d28b0f096f869b49cd6a71bf804274f572da4453"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"b1daec2d5e4f689c7bd7fc4adc20f3afc20b9947","unresolved":false,"context_lines":[{"line_number":88,"context_line":"class PolicyNotAuthorized(Exception):"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    def __init__(self, rule):"},{"line_number":91,"context_line":"        msg \u003d _(\"Policy doesn\u0027t allow %s to be performed.\" % rule)"},{"line_number":92,"context_line":"        super(PolicyNotAuthorized, self).__init__(msg)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAOn%2F%2FWlE%3D","line":91,"updated":"2013-05-13 21:15:58.000000000","message":"I think you want the % rule part of this line outside of the ().","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"f831fb9627b6e249fa22192958723bd768dfb86a","unresolved":false,"context_lines":[{"line_number":88,"context_line":"class PolicyNotAuthorized(Exception):"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    def __init__(self, rule):"},{"line_number":91,"context_line":"        msg \u003d _(\"Policy doesn\u0027t allow %s to be performed.\" % rule)"},{"line_number":92,"context_line":"        super(PolicyNotAuthorized, self).__init__(msg)"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAOn%2F%2FVUY%3D","line":91,"in_reply_to":"AAAAOn%2F%2FWlE%3D","updated":"2013-05-14 13:54:15.000000000","message":"Good catch, thanks!","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"b1daec2d5e4f689c7bd7fc4adc20f3afc20b9947","unresolved":false,"context_lines":[{"line_number":163,"context_line":"        self.policy_path \u003d None"},{"line_number":164,"context_line":"        self.policy_file \u003d policy_file or CONF.policy_file"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    def set_rules(self, rules, overwrite\u003dTrue):"},{"line_number":167,"context_line":"        \"\"\""},{"line_number":168,"context_line":"        Create a new Rules object based on the provided dict of rules"},{"line_number":169,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAOn%2F%2FWlA%3D","line":166,"updated":"2013-05-13 21:15:58.000000000","message":"Why does this method take a dictionary instead of a Rules instance?","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"f831fb9627b6e249fa22192958723bd768dfb86a","unresolved":false,"context_lines":[{"line_number":163,"context_line":"        self.policy_path \u003d None"},{"line_number":164,"context_line":"        self.policy_file \u003d policy_file or CONF.policy_file"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    def set_rules(self, rules, overwrite\u003dTrue):"},{"line_number":167,"context_line":"        \"\"\""},{"line_number":168,"context_line":"        Create a new Rules object based on the provided dict of rules"},{"line_number":169,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAOn%2F%2FVUM%3D","line":166,"in_reply_to":"AAAAOn%2F%2FWlA%3D","updated":"2013-05-14 13:54:15.000000000","message":"It can actually take both. Rules inherits from dict and implements some useful methods. In both cases, either set_rules gets a dict or a Rules instance, a new Rules instance will be created from it.","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"461cc14bd988bc81625bcf178200c796011e8e0c","unresolved":false,"context_lines":[{"line_number":172,"context_line":"                          with the new rules."},{"line_number":173,"context_line":"        \"\"\""},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"        if not isinstance(rules, dict):"},{"line_number":176,"context_line":"            raise TypeError(_(\"Rules must be an instance of dict, \""},{"line_number":177,"context_line":"                            \"got %s instead\") % type(rules))"},{"line_number":178,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAO3%2F%2F%2FIc%3D","line":175,"updated":"2013-05-21 13:57:04.000000000","message":"This check is what made me think the arg needed to be a dict. If that\u0027s the base class for Rules, that\u0027s fine, but maybe the error message (and docstring above) should also say that a Rules instance can be used.","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"461cc14bd988bc81625bcf178200c796011e8e0c","unresolved":false,"context_lines":[{"line_number":176,"context_line":"            raise TypeError(_(\"Rules must be an instance of dict, \""},{"line_number":177,"context_line":"                            \"got %s instead\") % type(rules))"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":"        new_rules \u003d rules"},{"line_number":180,"context_line":"        if not overwrite and self.rules:"},{"line_number":181,"context_line":"            new_rules \u003d self.rules"},{"line_number":182,"context_line":"            new_rules.update(rules)"}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAO3%2F%2F%2FIk%3D","line":179,"updated":"2013-05-21 13:57:04.000000000","message":"This logic is a bit convoluted. I think all you need to do is.\n\n  if overwrite:\n    self.rules \u003d Rules(rules)\n  else:\n    self.rules.update(rules)","commit_id":"c3e90026b6cea37f359cee79d57acb205c0d3b29"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"f4b4f550282602125b4e86036a983a7351930033","unresolved":false,"context_lines":[{"line_number":72,"context_line":"policy_opts \u003d ["},{"line_number":73,"context_line":"    cfg.StrOpt(\u0027policy_file\u0027,"},{"line_number":74,"context_line":"               default\u003d\u0027policy.json\u0027,"},{"line_number":75,"context_line":"               help\u003d_(\u0027JSON file representing policy\u0027)),"},{"line_number":76,"context_line":"    cfg.StrOpt(\u0027policy_default_rule\u0027,"},{"line_number":77,"context_line":"               default\u003d\u0027default\u0027,"},{"line_number":78,"context_line":"               help\u003d_(\u0027Rule checked when requested rule is not found\u0027)),"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAOn%2F%2FVCQ%3D","line":75,"updated":"2013-05-14 15:11:09.000000000","message":"containing the policy?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"5a515a36924b4a07db73fcfeaea46ec7cb5e41a4","unresolved":false,"context_lines":[{"line_number":72,"context_line":"policy_opts \u003d ["},{"line_number":73,"context_line":"    cfg.StrOpt(\u0027policy_file\u0027,"},{"line_number":74,"context_line":"               default\u003d\u0027policy.json\u0027,"},{"line_number":75,"context_line":"               help\u003d_(\u0027JSON file representing policy\u0027)),"},{"line_number":76,"context_line":"    cfg.StrOpt(\u0027policy_default_rule\u0027,"},{"line_number":77,"context_line":"               default\u003d\u0027default\u0027,"},{"line_number":78,"context_line":"               help\u003d_(\u0027Rule checked when requested rule is not found\u0027)),"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2Fzc%3D","line":75,"in_reply_to":"AAAAOn%2F%2FVCQ%3D","updated":"2013-05-15 08:36:09.000000000","message":"Done","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"f4b4f550282602125b4e86036a983a7351930033","unresolved":false,"context_lines":[{"line_number":75,"context_line":"               help\u003d_(\u0027JSON file representing policy\u0027)),"},{"line_number":76,"context_line":"    cfg.StrOpt(\u0027policy_default_rule\u0027,"},{"line_number":77,"context_line":"               default\u003d\u0027default\u0027,"},{"line_number":78,"context_line":"               help\u003d_(\u0027Rule checked when requested rule is not found\u0027)),"},{"line_number":79,"context_line":"]"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"CONF \u003d cfg.CONF"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAOn%2F%2FVCI%3D","line":78,"updated":"2013-05-14 15:11:09.000000000","message":"Rule enforced?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"5a515a36924b4a07db73fcfeaea46ec7cb5e41a4","unresolved":false,"context_lines":[{"line_number":75,"context_line":"               help\u003d_(\u0027JSON file representing policy\u0027)),"},{"line_number":76,"context_line":"    cfg.StrOpt(\u0027policy_default_rule\u0027,"},{"line_number":77,"context_line":"               default\u003d\u0027default\u0027,"},{"line_number":78,"context_line":"               help\u003d_(\u0027Rule checked when requested rule is not found\u0027)),"},{"line_number":79,"context_line":"]"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"CONF \u003d cfg.CONF"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2FzY%3D","line":78,"in_reply_to":"AAAAOn%2F%2FVCI%3D","updated":"2013-05-15 08:36:09.000000000","message":"Done","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":1994,"name":"Zhongyue Luo","email":"zhongyue.luo@gmail.com","username":"zyluo"},"change_message_id":"45e0971cca3f44e3b3cc66ec3bbb4c5ed07d9ec0","unresolved":false,"context_lines":[{"line_number":189,"context_line":"        Clears Enforcer rules,  policy\u0027s cache"},{"line_number":190,"context_line":"        and policy\u0027s path."},{"line_number":191,"context_line":"        \"\"\""},{"line_number":192,"context_line":"        self.set_rules({})"},{"line_number":193,"context_line":"        self.policy_path \u003d None"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"    def load_rules(self, force_reload\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2F20%3D","line":192,"updated":"2013-05-15 07:19:22.000000000","message":"How about we\n\n def set_rules(self, rules\u003dNone, overwrite\u003dTrue):\n     rules \u003d rules or {}\n\nand pass nothing here?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"5a515a36924b4a07db73fcfeaea46ec7cb5e41a4","unresolved":false,"context_lines":[{"line_number":189,"context_line":"        Clears Enforcer rules,  policy\u0027s cache"},{"line_number":190,"context_line":"        and policy\u0027s path."},{"line_number":191,"context_line":"        \"\"\""},{"line_number":192,"context_line":"        self.set_rules({})"},{"line_number":193,"context_line":"        self.policy_path \u003d None"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"    def load_rules(self, force_reload\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2Fy8%3D","line":192,"in_reply_to":"AAAAO3%2F%2F%2F20%3D","updated":"2013-05-15 08:36:09.000000000","message":"mmh, I kind of thought about doing it that way but then I thought that:\n\n  1) Rules are required for set_rules (that\u0027s what it is supposed to do)\n  2) Allowing that would give the user 2 ways for clearing the rules. This worries me less.\n\nthoughts?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":5638,"name":"Davanum Srinivas","email":"davanum@gmail.com","username":"dims-v"},"change_message_id":"f4b4f550282602125b4e86036a983a7351930033","unresolved":false,"context_lines":[{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        raise cfg.ConfigFilesNotFoundError(path\u003dCONF.policy_file)"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"    def enforce(self, rule, target, creds, do_raise\u003dFalse,"},{"line_number":232,"context_line":"                exc\u003dNone, *args, **kwargs):"},{"line_number":233,"context_line":"        \"\"\""},{"line_number":234,"context_line":"        Checks authorization of a rule against the target and credentials."}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAOn%2F%2FU%2Fk%3D","line":231,"updated":"2013-05-14 15:11:09.000000000","message":"do we need some log.debug()\u0027s to help with diagnosing issues/servicability?","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"5a515a36924b4a07db73fcfeaea46ec7cb5e41a4","unresolved":false,"context_lines":[{"line_number":228,"context_line":""},{"line_number":229,"context_line":"        raise cfg.ConfigFilesNotFoundError(path\u003dCONF.policy_file)"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"    def enforce(self, rule, target, creds, do_raise\u003dFalse,"},{"line_number":232,"context_line":"                exc\u003dNone, *args, **kwargs):"},{"line_number":233,"context_line":"        \"\"\""},{"line_number":234,"context_line":"        Checks authorization of a rule against the target and credentials."}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F%2Fy4%3D","line":231,"in_reply_to":"AAAAOn%2F%2FU%2Fk%3D","updated":"2013-05-15 08:36:09.000000000","message":"Done","commit_id":"4d7e5935e6e5924fe237523a23ae2b0b8543b896"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"b20977659bc1f01ed89fcd7bb8f9915b238f4622","unresolved":false,"context_lines":[{"line_number":174,"context_line":"        \"\"\""},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        if not isinstance(rules, dict):"},{"line_number":177,"context_line":"            raise TypeError(_(\"Rules must be an instance of dict, \""},{"line_number":178,"context_line":"                            \"got %s instead\") % type(rules))"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        new_rules \u003d rules"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPH%2F%2F3K8%3D","line":177,"updated":"2013-05-21 14:07:43.000000000","message":"The rules argument does not have to be a dict, right? It can also be another Rules instance?","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"b2dd9756a0a0e817f95bb03b9c65adc5de87353a","unresolved":false,"context_lines":[{"line_number":174,"context_line":"        \"\"\""},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"        if not isinstance(rules, dict):"},{"line_number":177,"context_line":"            raise TypeError(_(\"Rules must be an instance of dict, \""},{"line_number":178,"context_line":"                            \"got %s instead\") % type(rules))"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        new_rules \u003d rules"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPH%2F%2F2%2B8%3D","line":177,"in_reply_to":"AAAAPH%2F%2F3K8%3D","updated":"2013-05-21 15:16:26.000000000","message":"Done","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"b20977659bc1f01ed89fcd7bb8f9915b238f4622","unresolved":false,"context_lines":[{"line_number":177,"context_line":"            raise TypeError(_(\"Rules must be an instance of dict, \""},{"line_number":178,"context_line":"                            \"got %s instead\") % type(rules))"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        new_rules \u003d rules"},{"line_number":181,"context_line":"        if not overwrite and self.rules:"},{"line_number":182,"context_line":"            new_rules \u003d self.rules"},{"line_number":183,"context_line":"            new_rules.update(rules)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPH%2F%2F3LU%3D","line":180,"updated":"2013-05-21 14:07:43.000000000","message":"This logic is a bit convoluted. I think all you need to do is.\n\n  if overwrite:\n    self.rules \u003d Rules(rules)\n  else:\n    self.rules.update(rules)","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"b2dd9756a0a0e817f95bb03b9c65adc5de87353a","unresolved":false,"context_lines":[{"line_number":177,"context_line":"            raise TypeError(_(\"Rules must be an instance of dict, \""},{"line_number":178,"context_line":"                            \"got %s instead\") % type(rules))"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        new_rules \u003d rules"},{"line_number":181,"context_line":"        if not overwrite and self.rules:"},{"line_number":182,"context_line":"            new_rules \u003d self.rules"},{"line_number":183,"context_line":"            new_rules.update(rules)"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPH%2F%2F2%2B4%3D","line":180,"in_reply_to":"AAAAPH%2F%2F3LU%3D","updated":"2013-05-21 15:16:26.000000000","message":"totally agree","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"b20977659bc1f01ed89fcd7bb8f9915b238f4622","unresolved":false,"context_lines":[{"line_number":208,"context_line":""},{"line_number":209,"context_line":"        if reloaded:"},{"line_number":210,"context_line":"            rules \u003d Rules.load_json(data, self.default_rule)"},{"line_number":211,"context_line":"            self.set_rules(rules, force_reload)"},{"line_number":212,"context_line":"            LOG.debug(_(\"Rules successfully reloaded\"))"},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"    def _get_policy_path(self):"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPH%2F%2F3KA%3D","line":211,"updated":"2013-05-21 14:07:43.000000000","message":"Is force_reload right here? The overwrite and force reload behaviors seem orthogonal. Should this method have 2 arguments to separate the conditions? Why not always overwrite if the rules are re-read? Why overwrite when something forces the re-read?","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"b2dd9756a0a0e817f95bb03b9c65adc5de87353a","unresolved":false,"context_lines":[{"line_number":208,"context_line":""},{"line_number":209,"context_line":"        if reloaded:"},{"line_number":210,"context_line":"            rules \u003d Rules.load_json(data, self.default_rule)"},{"line_number":211,"context_line":"            self.set_rules(rules, force_reload)"},{"line_number":212,"context_line":"            LOG.debug(_(\"Rules successfully reloaded\"))"},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"    def _get_policy_path(self):"}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPH%2F%2F278%3D","line":211,"in_reply_to":"AAAAPH%2F%2F3KA%3D","updated":"2013-05-21 15:16:26.000000000","message":"mhh, good point. I\u0027ll remove force_reload from here. Having a separate keyword for overwrite would make sense if we were able to read from multiple files but this is not the case, yet.","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"b20977659bc1f01ed89fcd7bb8f9915b238f4622","unresolved":false,"context_lines":[{"line_number":277,"context_line":"                result \u003d False"},{"line_number":278,"context_line":""},{"line_number":279,"context_line":"        # If it is False, raise the exception if requested"},{"line_number":280,"context_line":"        if do_raise and result is False:"},{"line_number":281,"context_line":"            if exc:"},{"line_number":282,"context_line":"                raise exc(*args, **kwargs)"},{"line_number":283,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPH%2F%2F3Jg%3D","line":280,"updated":"2013-05-21 14:07:43.000000000","message":"if do_raise and not result","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"},{"author":{"_account_id":6159,"name":"Flavio Percoco Premoli","display_name":"flaper87","email":"flavio.percoco@flyrlabs.com","username":"flaper87"},"change_message_id":"b2dd9756a0a0e817f95bb03b9c65adc5de87353a","unresolved":false,"context_lines":[{"line_number":277,"context_line":"                result \u003d False"},{"line_number":278,"context_line":""},{"line_number":279,"context_line":"        # If it is False, raise the exception if requested"},{"line_number":280,"context_line":"        if do_raise and result is False:"},{"line_number":281,"context_line":"            if exc:"},{"line_number":282,"context_line":"                raise exc(*args, **kwargs)"},{"line_number":283,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"AAAAPH%2F%2F29I%3D","line":280,"in_reply_to":"AAAAPH%2F%2F3Jg%3D","updated":"2013-05-21 15:16:26.000000000","message":"Done","commit_id":"e3cf2e4c405546f1b6bf2e0b90b7afc13b2e9cd7"}]}
