)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"ef8d350d8dc6f64951229b9283efdd75e828386a","unresolved":false,"context_lines":[{"line_number":9,"context_line":"The docstring provides an overview of the purpose and usage of the"},{"line_number":10,"context_line":"module; previously this was not documented."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"Change-Id: I9c83883a6d9ae3201c9037c979689cb82c232120"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"AAAATn%2F%2Bz8c%3D","line":12,"updated":"2013-11-19 20:30:31.000000000","message":"Please add the relevant bug information line.  See https://wiki.openstack.org/wiki/GitCommitMessages#Summary_of_GIT_commit_message_structure for more information on proper git commit messages.\n\nIn this case the line would be:\n\ncloses-bug: #1252428","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"}],"keystone/common/dependency.py":[{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"61368e3da6d5bfdeda8c2458ec8de3a410c42f49","unresolved":false,"context_lines":[{"line_number":30,"context_line":"    @dependency.requires(\u0027foo_api\u0027)"},{"line_number":31,"context_line":"    class FooClient:"},{"line_number":32,"context_line":"        ..."},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"Once an instance of the class Foo has been created, each FooClient will have"},{"line_number":35,"context_line":"an attribute \u0027foo_api\u0027, which refers to the instance of Foo (of which there"},{"line_number":36,"context_line":"should be only one). FooClients can be created both before and after the"}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATn%2F%2B5SM%3D","line":33,"updated":"2013-11-18 21:30:32.000000000","message":"There should also be a quick documentation of the optional() decorator as that rounds out the 3 used/provided here.","commit_id":"eb193bee24974daa31c43d37e2a5f7b0c698eea9"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"61368e3da6d5bfdeda8c2458ec8de3a410c42f49","unresolved":false,"context_lines":[{"line_number":38,"context_line":"instantiated."},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"The heaviest use of this module is the class keystone.common.manager.Manager"},{"line_number":41,"context_line":"and it\u0027s descendants, but there are a few others as well."},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"\"\"\""},{"line_number":44,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAATn%2F%2B5S8%3D","line":41,"updated":"2013-11-18 21:30:32.000000000","message":"Suggest removing this line, as it doesn\u0027t contribute to the documentation of the functionality provided here.","commit_id":"eb193bee24974daa31c43d37e2a5f7b0c698eea9"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"5fc03d7b2da8b548c52db506bfbbdeb54b1007a2","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"\"\"\"Controlled access to objects without the need for multiple instantiation."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"This module provides a controlled way to access objects from different pieces"},{"line_number":20,"context_line":"of code, without having multiple instances. The most important routines are"},{"line_number":21,"context_line":"provider and requires, which are used as decorators to register or retrieve an"},{"line_number":22,"context_line":"object, respectively."}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Bzuw%3D","line":19,"updated":"2013-11-19 21:45:03.000000000","message":"I\u0027m not sure what \"controlled\" means here... controlled by what?\n\nThis module is for dependency injection so that should be mentioned.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"dca5138338f5abc88b1733dea3d592a2e46cb1ee","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"\"\"\"Controlled access to objects without the need for multiple instantiation."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"This module provides a controlled way to access objects from different pieces"},{"line_number":20,"context_line":"of code, without having multiple instances. The most important routines are"},{"line_number":21,"context_line":"provider and requires, which are used as decorators to register or retrieve an"},{"line_number":22,"context_line":"object, respectively."}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Bq88%3D","line":19,"in_reply_to":"AAAATn%2F%2BrEc%3D","updated":"2013-11-21 18:45:50.000000000","message":"http://en.wikipedia.org/wiki/Dependency_injection\n\n\"\"\"\nDependency injection involves at least three elements:\n\n    a dependent consumer,\n    a declaration of a component\u0027s dependencies, defined as interface contracts,\n    an injector (sometimes referred to as a provider or container) that creates instances of classes that implement a given dependency interface on request.\n\"\"\"","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":8949,"name":"Ian Denhardt","email":"ian@zenhack.net","username":"isd"},"change_message_id":"5e7a9535001f1749981c348352017590b3f31c56","unresolved":false,"context_lines":[{"line_number":16,"context_line":""},{"line_number":17,"context_line":"\"\"\"Controlled access to objects without the need for multiple instantiation."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"This module provides a controlled way to access objects from different pieces"},{"line_number":20,"context_line":"of code, without having multiple instances. The most important routines are"},{"line_number":21,"context_line":"provider and requires, which are used as decorators to register or retrieve an"},{"line_number":22,"context_line":"object, respectively."}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2BrEc%3D","line":19,"in_reply_to":"AAAATn%2F%2Bzuw%3D","updated":"2013-11-21 18:34:10.000000000","message":"I just meant \"controlled\" as a synonym for \"structured\" or \"organized\" or \"not spaghetti code\". Perhaps I could make that more clear.\n\nI don\u0027t think I understand what you mean by dependency injection.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"5fc03d7b2da8b548c52db506bfbbdeb54b1007a2","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"This module provides a controlled way to access objects from different pieces"},{"line_number":20,"context_line":"of code, without having multiple instances. The most important routines are"},{"line_number":21,"context_line":"provider and requires, which are used as decorators to register or retrieve an"},{"line_number":22,"context_line":"object, respectively."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"By way of example, in the following code fragment:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Bzuk%3D","line":21,"updated":"2013-11-19 21:45:03.000000000","message":"suggest change \"routines\" to \"decorators\"\n\nrequires doesn\u0027t really retrieve an object... it injects the provider.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":8949,"name":"Ian Denhardt","email":"ian@zenhack.net","username":"isd"},"change_message_id":"5e7a9535001f1749981c348352017590b3f31c56","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"This module provides a controlled way to access objects from different pieces"},{"line_number":20,"context_line":"of code, without having multiple instances. The most important routines are"},{"line_number":21,"context_line":"provider and requires, which are used as decorators to register or retrieve an"},{"line_number":22,"context_line":"object, respectively."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"By way of example, in the following code fragment:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2BrBs%3D","line":21,"in_reply_to":"AAAATn%2F%2Bzuk%3D","updated":"2013-11-21 18:34:10.000000000","message":"Again, the word \u0027inject\u0027 here feels very vague to me.\n\nI agree that this is a bit wordy, and could be improved by just calling them decorators, rather than \u0027routines ... which are used as decorators\u0027. I\u0027ll change that.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"5fc03d7b2da8b548c52db506bfbbdeb54b1007a2","unresolved":false,"context_lines":[{"line_number":31,"context_line":"    class FooClient:"},{"line_number":32,"context_line":"        ..."},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"Once an instance of the class Foo has been created, each FooClient will have"},{"line_number":35,"context_line":"an attribute \u0027foo_api\u0027, which refers to the instance of Foo (of which there"},{"line_number":36,"context_line":"should be only one). FooClients can be created both before and after the"},{"line_number":37,"context_line":"instance of Foo, but their \u0027foo_api\u0027 attribute will not exist until Foo is"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2BzuY%3D","line":34,"updated":"2013-11-19 21:45:03.000000000","message":"suggest remove \"Once an instance of the class Foo has been created,\" .. not really how we want to think of this.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":8949,"name":"Ian Denhardt","email":"ian@zenhack.net","username":"isd"},"change_message_id":"5e7a9535001f1749981c348352017590b3f31c56","unresolved":false,"context_lines":[{"line_number":31,"context_line":"    class FooClient:"},{"line_number":32,"context_line":"        ..."},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"Once an instance of the class Foo has been created, each FooClient will have"},{"line_number":35,"context_line":"an attribute \u0027foo_api\u0027, which refers to the instance of Foo (of which there"},{"line_number":36,"context_line":"should be only one). FooClients can be created both before and after the"},{"line_number":37,"context_line":"instance of Foo, but their \u0027foo_api\u0027 attribute will not exist until Foo is"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Bq%2F8%3D","line":34,"in_reply_to":"AAAATn%2F%2BzuY%3D","updated":"2013-11-21 18:34:10.000000000","message":"I think it\u0027s important to specify the interface fully. without this, it isn\u0027t clear that the attributes don\u0027t get set until the provider is initialized. If it\u0027s not written down somewhere, I don\u0027t know whether:\n\n- The provider isn\u0027t available until it\u0027s initialized for the first time\n- The provider is initialized the first time an object which requires it is initialized\n- I\u0027m supposed to wait until after resolve_future_dependencies is called to actually access the providers\n- The interface is some other reasonable thing I haven\u0027t thought of.\n\nI agree the documentation I\u0027ve written could stand to be less procedural, but I\u0027m wary of achieving this by just omitting information required to use the module correctly.\n\n(incidentally, for all I know the third bullet point really is the correct one - please let me know)","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"5fc03d7b2da8b548c52db506bfbbdeb54b1007a2","unresolved":false,"context_lines":[{"line_number":40,"context_line":"The resolve_future_dependencies function will ensure that any outstanding"},{"line_number":41,"context_line":"dependencies are resolved. If, when it is called, any object has a dependency"},{"line_number":42,"context_line":"for which no provider exists, an UnresolvableDependencyException will be"},{"line_number":43,"context_line":"raised."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"optional is like requires except that when resolve_future_dependencies is"},{"line_number":46,"context_line":"called, unmet dependencies registered via optional will just be set to None; no"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2BzuQ%3D","line":43,"updated":"2013-11-19 21:45:03.000000000","message":"resolve_future_dependencies should be called only once, after he initial \"global\" objects are created (this happens in service.py). It was put in to handle a circular dependency during startup and wasn\u0027t planned to be used in any other case. We should just not have circular dependencies in objects created after startup (i.e., after the call to resolve_future_dependencies().","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":8949,"name":"Ian Denhardt","email":"ian@zenhack.net","username":"isd"},"change_message_id":"f3ef445e9f0c63ef7e18ce9f4007ec4384d8cd58","unresolved":false,"context_lines":[{"line_number":41,"context_line":"dependencies are resolved. If, when it is called, any object has a dependency"},{"line_number":42,"context_line":"for which no provider exists, an UnresolvableDependencyException will be"},{"line_number":43,"context_line":"raised."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"optional is like requires except that when resolve_future_dependencies is"},{"line_number":46,"context_line":"called, unmet dependencies registered via optional will just be set to None; no"},{"line_number":47,"context_line":"exception will be raised."}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2B4%2BI%3D","line":44,"updated":"2013-11-19 21:04:03.000000000","message":"I decided a description of resolve_future_dependencies was necessary to give context to the difference between requires and optional.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"dca5138338f5abc88b1733dea3d592a2e46cb1ee","unresolved":false,"context_lines":[{"line_number":41,"context_line":"dependencies are resolved. If, when it is called, any object has a dependency"},{"line_number":42,"context_line":"for which no provider exists, an UnresolvableDependencyException will be"},{"line_number":43,"context_line":"raised."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"optional is like requires except that when resolve_future_dependencies is"},{"line_number":46,"context_line":"called, unmet dependencies registered via optional will just be set to None; no"},{"line_number":47,"context_line":"exception will be raised."}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Bq8E%3D","line":44,"in_reply_to":"AAAATn%2F%2B4%2BI%3D","updated":"2013-11-21 18:45:50.000000000","message":"seems like the difference between requires and optional is pretty obvious just from the names... requires are required and optional are optional. description of resolve_future_dependencies should be added to the end. It\u0027s there to handle circular dependencies. (I\u0027m not sure that it works correctly when optional is used after initialization...)","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"ea7fa71d0e58a40e43092c32483786ec62beae67","unresolved":false,"context_lines":[{"line_number":42,"context_line":"for which no provider exists, an UnresolvableDependencyException will be"},{"line_number":43,"context_line":"raised."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"optional is like requires except that when resolve_future_dependencies is"},{"line_number":46,"context_line":"called, unmet dependencies registered via optional will just be set to None; no"},{"line_number":47,"context_line":"exception will be raised."},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2B4ss%3D","line":45,"updated":"2013-11-18 23:30:37.000000000","message":"nit: Optional should be capitalized.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"dca5138338f5abc88b1733dea3d592a2e46cb1ee","unresolved":false,"context_lines":[{"line_number":42,"context_line":"for which no provider exists, an UnresolvableDependencyException will be"},{"line_number":43,"context_line":"raised."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"optional is like requires except that when resolve_future_dependencies is"},{"line_number":46,"context_line":"called, unmet dependencies registered via optional will just be set to None; no"},{"line_number":47,"context_line":"exception will be raised."},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Bq8A%3D","line":45,"in_reply_to":"AAAATn%2F%2B4cI%3D","updated":"2013-11-21 18:45:50.000000000","message":"could put \u0027optional\u0027 in quotes.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":8949,"name":"Ian Denhardt","email":"ian@zenhack.net","username":"isd"},"change_message_id":"f3ef445e9f0c63ef7e18ce9f4007ec4384d8cd58","unresolved":false,"context_lines":[{"line_number":42,"context_line":"for which no provider exists, an UnresolvableDependencyException will be"},{"line_number":43,"context_line":"raised."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"optional is like requires except that when resolve_future_dependencies is"},{"line_number":46,"context_line":"called, unmet dependencies registered via optional will just be set to None; no"},{"line_number":47,"context_line":"exception will be raised."},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2B4cI%3D","line":45,"in_reply_to":"AAAATn%2F%2B4ss%3D","updated":"2013-11-19 21:04:03.000000000","message":"My default tends to be to not adjust the capitalization of identifiers, even when it conflicts with English grammar. If you think it would be better to capitalize it, I can do so.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"5fc03d7b2da8b548c52db506bfbbdeb54b1007a2","unresolved":false,"context_lines":[{"line_number":44,"context_line":""},{"line_number":45,"context_line":"optional is like requires except that when resolve_future_dependencies is"},{"line_number":46,"context_line":"called, unmet dependencies registered via optional will just be set to None; no"},{"line_number":47,"context_line":"exception will be raised."},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"\"\"\""},{"line_number":50,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAATn%2F%2Bzt8%3D","line":47,"updated":"2013-11-19 21:45:03.000000000","message":"this is more a description of what happens and not really how users should think about it. optional is to be used if the provider may not be registered. The member will be set to None if there\u0027s no provider.","commit_id":"cb1d6afa441d5276cce6ad50d877d266c3d73677"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"ac88a1beb66f38b1851c02626412714c0ba069b7","unresolved":false,"context_lines":[{"line_number":58,"context_line":"        foo \u003d Foo()"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    The object \u0027foo\u0027 will be registered as a provider for \u0027foo_api\u0027. No more"},{"line_number":61,"context_line":"    than one such object should be created."},{"line_number":62,"context_line":"    \"\"\""},{"line_number":63,"context_line":"    def wrapper(cls):"},{"line_number":64,"context_line":"        def wrapped(init):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BcWw%3D","line":61,"updated":"2013-11-26 00:44:06.000000000","message":"suggest change \"object\" to \"instance\".\n\nsuggest also provide a reason why shouldn\u0027t create more than one instance... because each new instance will replace the current provider and you might wind up with different instances used by different consumers.","commit_id":"bd17f256f89a78bdd232f4d25b2b17fdc8b5e689"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"ac88a1beb66f38b1851c02626412714c0ba069b7","unresolved":false,"context_lines":[{"line_number":99,"context_line":"    \"\"\"\u0027requires\u0027 is a class decorator used to inject providers into consumers."},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    The required providers will be made available to instances of the decorated"},{"line_number":102,"context_line":"    class via an attribute. For example, in the code fragment:"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"        @dependency.requires(\u0027foo_api\u0027, \u0027bar_api\u0027)"},{"line_number":105,"context_line":"        class FooBarClient:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BcWE%3D","line":102,"updated":"2013-11-26 00:44:06.000000000","message":"suggest add \"with the same name as the provider\" after \"via an attribute\"... this is less vague.","commit_id":"bd17f256f89a78bdd232f4d25b2b17fdc8b5e689"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"ac88a1beb66f38b1851c02626412714c0ba069b7","unresolved":false,"context_lines":[{"line_number":173,"context_line":"    Before this function is called, circular dependencies may not have been"},{"line_number":174,"context_line":"    injected. This function should be called only once, after all global"},{"line_number":175,"context_line":"    providers are registered. If an object needs to be created after this"},{"line_number":176,"context_line":"    call, It must not have circular dependencies."},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"    If any required dependencies are unresolvable, this function will raise an"},{"line_number":179,"context_line":"    UnresolvableDependencyException."}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BcV4%3D","line":176,"updated":"2013-11-26 00:44:06.000000000","message":"change \"It\" to \"it\" (lowercase)","commit_id":"bd17f256f89a78bdd232f4d25b2b17fdc8b5e689"},{"author":{"_account_id":6486,"name":"Brant Knudson","email":"blk@acm.org","username":"blk-u"},"change_message_id":"ac88a1beb66f38b1851c02626412714c0ba069b7","unresolved":false,"context_lines":[{"line_number":179,"context_line":"    UnresolvableDependencyException."},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"    Outside of this module, this function should be called with no arguments;"},{"line_number":182,"context_line":"    The optional argument is used internally, and should be treated as an"},{"line_number":183,"context_line":"    implementation detail."},{"line_number":184,"context_line":"    \"\"\""},{"line_number":185,"context_line":"    if provider_name:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAATn%2F%2BcVw%3D","line":182,"updated":"2013-11-26 00:44:06.000000000","message":"change \"The\" to \"the\" (lowercase)","commit_id":"bd17f256f89a78bdd232f4d25b2b17fdc8b5e689"}]}
