)]}'
{"glance/common/artifacts/__init__.py":[{"author":{"_account_id":9712,"name":"Dougal Matthews","email":"dougal.matthews@canonical.com","username":"dougal"},"change_message_id":"bc4de9e502e13aad58dacacc30f2b63569a2c66d","unresolved":false,"context_lines":[{"line_number":16,"context_line":"class Blob(object):"},{"line_number":17,"context_line":"    def __init__(self, size):"},{"line_number":18,"context_line":"        self._size \u003d size"},{"line_number":19,"context_line":"        self._locations \u003d []"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    @property"},{"line_number":22,"context_line":"    def size(self):"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_f4ad9789","line":19,"updated":"2014-11-05 14:58:33.000000000","message":"What is a location in this context?","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"c651056448e409a2b63d445a1c49226174a9a01d","unresolved":false,"context_lines":[{"line_number":16,"context_line":"class Blob(object):"},{"line_number":17,"context_line":"    def __init__(self, size):"},{"line_number":18,"context_line":"        self._size \u003d size"},{"line_number":19,"context_line":"        self._locations \u003d []"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    @property"},{"line_number":22,"context_line":"    def size(self):"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_47406da5","line":19,"in_reply_to":"7a8c0949_f4ad9789","updated":"2014-11-14 10:50:28.000000000","message":"the same as locations for the present images: URI\u0027s to the blob locations in the backing stores. \n\nBTW, this class will be rewitten. I don\u0027t want it to be plain object, I\u0027ll make it use the declarative constraints as well as the artifacts. Will do it in the next patchset.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"}],"glance/common/artifacts/declarative.py":[{"author":{"_account_id":9712,"name":"Dougal Matthews","email":"dougal.matthews@canonical.com","username":"dougal"},"change_message_id":"bc4de9e502e13aad58dacacc30f2b63569a2c66d","unresolved":false,"context_lines":[{"line_number":92,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":93,"context_line":"                _(\u0027Invalid item type specification\u0027))"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    def __init__(self, item_type, min_size\u003d0, max_size\u003dNone, unique\u003dFalse,"},{"line_number":96,"context_line":"                 extra_items\u003dTrue, **kwargs):"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"        super(ListAttributeDefinition, self).__init__(**kwargs)"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_4f2a547f","line":95,"updated":"2014-11-05 14:58:33.000000000","message":"In general I think the logic needs to be broken out of the __init__.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"c651056448e409a2b63d445a1c49226174a9a01d","unresolved":false,"context_lines":[{"line_number":92,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":93,"context_line":"                _(\u0027Invalid item type specification\u0027))"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"    def __init__(self, item_type, min_size\u003d0, max_size\u003dNone, unique\u003dFalse,"},{"line_number":96,"context_line":"                 extra_items\u003dTrue, **kwargs):"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"        super(ListAttributeDefinition, self).__init__(**kwargs)"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_47b14d8e","line":95,"in_reply_to":"7a8c0949_4f2a547f","updated":"2014-11-14 10:50:28.000000000","message":"Not sure why.\n\nThe idea behind this is to be able to define artifact type properties with their constrains by a single attribute creation in the class definition, like these:\n\nclass ArtType(ArtifactType):\n    attribute \u003d AttributeType(constraint_1\u003dvalue1, constraint_2\u003dvalue2)\n\nThis is how SQLAlchemy defines its models and their mapping to database columns.\n\nIf we remove constrains from constructors of attributes, we\u0027ll have to make them as methods have to implement some kind of \"fluent syntax\" to construct chains, like this:\n\nclass ArtType(ArtifactType):\n   attribute \u003d AttributeType().constraint_1(value1).constraint_2(value2)\n\nI am not sure if this syntax is any better: it\u0027s similar but longer, and is not similar to SQLAlchemy or DjangoORM, unlike the proposed version.\n\nProbably I am missing something.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":9712,"name":"Dougal Matthews","email":"dougal.matthews@canonical.com","username":"dougal"},"change_message_id":"bc4de9e502e13aad58dacacc30f2b63569a2c66d","unresolved":false,"context_lines":[{"line_number":134,"context_line":"                    _(\"\u0027extra_items\u0027 may not be set to \u0027False\u0027 \""},{"line_number":135,"context_line":"                      \"if a non-iterable is passed as \u0027item_type\u0027\"))"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"        if min_size:"},{"line_number":138,"context_line":"            self._add_validator(lambda v: len(v) \u003e\u003d min_size,"},{"line_number":139,"context_line":"                                _(\u0027List size is less then minimum\u0027))"},{"line_number":140,"context_line":"        if max_size:"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_34de3f12","line":137,"updated":"2014-11-05 14:58:33.000000000","message":"Ontop of my comment above, defining the validators in the __init__ seems like a particularly bad idea. I\u0027d move all of these out.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"c651056448e409a2b63d445a1c49226174a9a01d","unresolved":false,"context_lines":[{"line_number":134,"context_line":"                    _(\"\u0027extra_items\u0027 may not be set to \u0027False\u0027 \""},{"line_number":135,"context_line":"                      \"if a non-iterable is passed as \u0027item_type\u0027\"))"},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"        if min_size:"},{"line_number":138,"context_line":"            self._add_validator(lambda v: len(v) \u003e\u003d min_size,"},{"line_number":139,"context_line":"                                _(\u0027List size is less then minimum\u0027))"},{"line_number":140,"context_line":"        if max_size:"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_2749a18b","line":137,"in_reply_to":"7a8c0949_34de3f12","updated":"2014-11-14 10:50:28.000000000","message":"Why? \nThe usage of closures seems to be wrong (we have to save the constrains as object fields, this is noted and will be fixed), but creating them in __init__ simplifies the definition","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":9712,"name":"Dougal Matthews","email":"dougal.matthews@canonical.com","username":"dougal"},"change_message_id":"bc4de9e502e13aad58dacacc30f2b63569a2c66d","unresolved":false,"context_lines":[{"line_number":218,"context_line":"            self._check_prop(None, properties)"},{"line_number":219,"context_line":"            self.properties \u003d properties"},{"line_number":220,"context_line":""},{"line_number":221,"context_line":"        if min_properties:"},{"line_number":222,"context_line":"            self._add_validator(lambda v: len(v) \u003e\u003d min_properties,"},{"line_number":223,"context_line":"                                _(\u0027Dictionary size is less then \u0027"},{"line_number":224,"context_line":"                                  \u0027minimum\u0027))"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_4f51740d","line":221,"updated":"2014-11-05 14:58:33.000000000","message":"Again, this feels weird.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":9712,"name":"Dougal Matthews","email":"dougal.matthews@canonical.com","username":"dougal"},"change_message_id":"bc4de9e502e13aad58dacacc30f2b63569a2c66d","unresolved":false,"context_lines":[{"line_number":271,"context_line":"    def __get__(self, instance, owner):"},{"line_number":272,"context_line":"        if instance is None:"},{"line_number":273,"context_line":"            return self.prop"},{"line_number":274,"context_line":"        else:"},{"line_number":275,"context_line":"            v \u003d getattr(instance, \u0027_\u0027 + self.prop.name, None)"},{"line_number":276,"context_line":"            if v is None and self.prop.default is not None:"},{"line_number":277,"context_line":"                v \u003d copy.copy(self.prop.default)"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_8fa99ce1","line":274,"updated":"2014-11-05 14:58:33.000000000","message":"The indentation for the else isn\u0027t needed given the above if always returns.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"c651056448e409a2b63d445a1c49226174a9a01d","unresolved":false,"context_lines":[{"line_number":271,"context_line":"    def __get__(self, instance, owner):"},{"line_number":272,"context_line":"        if instance is None:"},{"line_number":273,"context_line":"            return self.prop"},{"line_number":274,"context_line":"        else:"},{"line_number":275,"context_line":"            v \u003d getattr(instance, \u0027_\u0027 + self.prop.name, None)"},{"line_number":276,"context_line":"            if v is None and self.prop.default is not None:"},{"line_number":277,"context_line":"                v \u003d copy.copy(self.prop.default)"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_8759755c","line":274,"in_reply_to":"7a8c0949_8fa99ce1","updated":"2014-11-14 10:50:28.000000000","message":"Thanks. Will fix.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"7767195ea5d9fb44bf863b35d1ee2d9ef8ddf9d3","unresolved":false,"context_lines":[{"line_number":29,"context_line":"                 display_name\u003dNone,"},{"line_number":30,"context_line":"                 description\u003dNone,"},{"line_number":31,"context_line":"                 readonly\u003dFalse,"},{"line_number":32,"context_line":"                 mutable\u003dTrue,"},{"line_number":33,"context_line":"                 required\u003dFalse,"},{"line_number":34,"context_line":"                 default\u003dNone):"},{"line_number":35,"context_line":"        self.name \u003d None"}],"source_content_type":"text/x-python","patch_set":11,"id":"5a890539_87e9c71c","line":32,"updated":"2014-11-10 16:16:56.000000000","message":"I\u0027d suggest logical interconnection of mutable and default values the following way: if an argument without a default value is immutable, then the first time we set it to SOME_VALUE, we set SOME_VALUE as the default value of our argument.\n\nclass TestType(get_artifact_base()):\n    mutable_def \u003d AttributeDefinition(mutable\u003dFalse, default\u003d42)\n    mutable_no_def \u003d AttributeDefinition(mutable\u003dFalse)\n\ntt \u003d TestType()\n\nFor attribute mutable_def it is impossible to define a new value, and for any instance it will have the default value of 42.\nAs for mutable_no_def attribute after we set some value to it the first time like\n\ntt.mutable_no_def \u003d \"don\u0027t panic\"\n\nwe are unable to change it later. It seems to me that it is very much the same as a property with a default value. \n\nP.S. It would be extremely handy if we are to have JSONschema validation: a behaviour like that makes it possible to add support for immutable properties the most straightforward way.","commit_id":"07fb8626cbe596c67e34f0160c8a067713ae4c2f"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"90688aeca62af87dfd14fdb80b5d96e3111c8a62","unresolved":false,"context_lines":[{"line_number":681,"context_line":""},{"line_number":682,"context_line":"def _kwarg_init_constructor(self, **kwargs):"},{"line_number":683,"context_line":"    for k in kwargs:"},{"line_number":684,"context_line":"        if not hasattr(type(self), k):"},{"line_number":685,"context_line":"            raise TypeError(_(\"Invalid Argument in type initialization\"))"},{"line_number":686,"context_line":"        setattr(self, k, kwargs[k])"},{"line_number":687,"context_line":"    for k, v in self.metadata.attributes.all.items():"}],"source_content_type":"text/x-python","patch_set":20,"id":"3a961159_39e1e1d0","line":684,"updated":"2014-12-09 18:36:36.000000000","message":"raise TypeError(_(\"Invalid Argument \u0027%s\u0027 in type initialization\") % k)\n\nwill be a lot more informative","commit_id":"3aedb19f1b88200620f3572bb75087804e6e5608"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"e09c7b39f851a4bdfc51f8152e566e7a54981594","unresolved":false,"context_lines":[{"line_number":689,"context_line":"    try:"},{"line_number":690,"context_line":"        for k in kwargs:"},{"line_number":691,"context_line":"            if not hasattr(type(self), k):"},{"line_number":692,"context_line":"                raise TypeError("},{"line_number":693,"context_line":"                    _(\"Invalid Argument \u0027%s\u0027 in type initialization\") % k)"},{"line_number":694,"context_line":"            setattr(self, k, kwargs[k])"},{"line_number":695,"context_line":"        self._validate_required(self.metadata.attributes.properties)"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a930d6b_b2b896e6","line":692,"updated":"2015-01-22 13:28:47.000000000","message":"I think some specific exception should be raised here, something like \n\n raise exc.ArtifactInvalidProperty(prop\u003dk)","commit_id":"f64848925d3953847f68067a03f9be7b9c3db764"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"fead273b272fb2ac78220eef4693b253f0abab9c","unresolved":false,"context_lines":[{"line_number":689,"context_line":"    try:"},{"line_number":690,"context_line":"        for k in kwargs:"},{"line_number":691,"context_line":"            if not hasattr(type(self), k):"},{"line_number":692,"context_line":"                raise TypeError("},{"line_number":693,"context_line":"                    _(\"Invalid Argument \u0027%s\u0027 in type initialization\") % k)"},{"line_number":694,"context_line":"            setattr(self, k, kwargs[k])"},{"line_number":695,"context_line":"        self._validate_required(self.metadata.attributes.properties)"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a930d6b_5e7daf6d","line":692,"in_reply_to":"1a930d6b_b2b896e6","updated":"2015-01-22 18:47:41.000000000","message":"I don\u0027t agree. Try doing something like this in python:\n\nclass Foo(object):\n        def __init__(self, bar):\n            pass\n   \nf \u003d Foo(baz\u003d\u0027q\u0027)\n\nYou will get exactly the TypeError exception.\nThis is the same case, we just build the constructor dynamically","commit_id":"f64848925d3953847f68067a03f9be7b9c3db764"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":98,"context_line":""},{"line_number":99,"context_line":"        for validator, message in self._validators:"},{"line_number":100,"context_line":"            messages \u003d []"},{"line_number":101,"context_line":"            if not validator(value):"},{"line_number":102,"context_line":"                messages.append(message)"},{"line_number":103,"context_line":"            if messages:"},{"line_number":104,"context_line":"                raise exc.InvalidArtifactPropertyValue(name\u003dname or self.name,"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_aacf7028","line":101,"updated":"2015-02-13 23:07:58.000000000","message":"Did you mean for it to be:\n\n    messages \u003d []\n    for validator, message in self._validators:\n        if not validator(value):\n            messages.append(message)\n    if messages:\n        raise ...\n\nIf so this could be written a bit faster as\n\n    messages \u003d [message for validator, message in self._validators\n                if not vaildator(value)]\n    if messages:\n        raise ...","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":98,"context_line":""},{"line_number":99,"context_line":"        for validator, message in self._validators:"},{"line_number":100,"context_line":"            messages \u003d []"},{"line_number":101,"context_line":"            if not validator(value):"},{"line_number":102,"context_line":"                messages.append(message)"},{"line_number":103,"context_line":"            if messages:"},{"line_number":104,"context_line":"                raise exc.InvalidArtifactPropertyValue(name\u003dname or self.name,"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_623e172a","line":101,"in_reply_to":"da86d52c_aacf7028","updated":"2015-02-25 11:46:22.000000000","message":"As long as this code was processing only the first error, I\u0027ve rewritten it in a simpler way.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":106,"context_line":"                                                       msg\u003d\u0027, \u0027.join(messages))"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"# noinspection PyAttributeOutsideInit"},{"line_number":110,"context_line":"class ListAttributeDefinition(AttributeDefinition):"},{"line_number":111,"context_line":"    ALLOWED_TYPES \u003d (types.ListType,)"},{"line_number":112,"context_line":"    ALLOWED_ITEM_TYPES \u003d (AttributeDefinition, )"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_e5cb5b71","line":109,"updated":"2015-02-13 23:07:58.000000000","message":"Is this for pylint or pycharm?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":106,"context_line":"                                                       msg\u003d\u0027, \u0027.join(messages))"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"# noinspection PyAttributeOutsideInit"},{"line_number":110,"context_line":"class ListAttributeDefinition(AttributeDefinition):"},{"line_number":111,"context_line":"    ALLOWED_TYPES \u003d (types.ListType,)"},{"line_number":112,"context_line":"    ALLOWED_ITEM_TYPES \u003d (AttributeDefinition, )"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_c21423a2","line":109,"in_reply_to":"da86d52c_e5cb5b71","updated":"2015-02-25 11:46:22.000000000","message":"Removed.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":190,"context_line":"        else:"},{"line_number":191,"context_line":"            self._remove_validator(\u0027unique\u0027)"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"    # noinspection PyProtectedMember"},{"line_number":194,"context_line":"    def _set_name(self, value):"},{"line_number":195,"context_line":"        super(ListAttributeDefinition, self)._set_name(value)"},{"line_number":196,"context_line":"        if isinstance(self.item_type, types.ListType):"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_05078f1e","line":193,"updated":"2015-02-13 23:07:58.000000000","message":"Again, are these comments necessary?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":190,"context_line":"        else:"},{"line_number":191,"context_line":"            self._remove_validator(\u0027unique\u0027)"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"    # noinspection PyProtectedMember"},{"line_number":194,"context_line":"    def _set_name(self, value):"},{"line_number":195,"context_line":"        super(ListAttributeDefinition, self)._set_name(value)"},{"line_number":196,"context_line":"        if isinstance(self.item_type, types.ListType):"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_22109fa7","line":193,"in_reply_to":"da86d52c_05078f1e","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":195,"context_line":"        super(ListAttributeDefinition, self)._set_name(value)"},{"line_number":196,"context_line":"        if isinstance(self.item_type, types.ListType):"},{"line_number":197,"context_line":"            i \u003d 0"},{"line_number":198,"context_line":"            for item in self.item_type:"},{"line_number":199,"context_line":"                item._set_name(\"%s[%i]\" % (value, i))"},{"line_number":200,"context_line":"                i +\u003d 1"},{"line_number":201,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_2511f253","line":198,"updated":"2015-02-13 23:07:58.000000000","message":"Would enumerate not work here?\n\n    for i, item in enumerate(self.item_type):\n        item._set_name(\"%s[%i]\" % (value, i))","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":195,"context_line":"        super(ListAttributeDefinition, self)._set_name(value)"},{"line_number":196,"context_line":"        if isinstance(self.item_type, types.ListType):"},{"line_number":197,"context_line":"            i \u003d 0"},{"line_number":198,"context_line":"            for item in self.item_type:"},{"line_number":199,"context_line":"                item._set_name(\"%s[%i]\" % (value, i))"},{"line_number":200,"context_line":"                i +\u003d 1"},{"line_number":201,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_82e30ba3","line":198,"in_reply_to":"da86d52c_2511f253","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":205,"context_line":"        super(ListAttributeDefinition, self).validate(value, name)"},{"line_number":206,"context_line":"        if value is not None:"},{"line_number":207,"context_line":"            i \u003d 0"},{"line_number":208,"context_line":"            for item in value:"},{"line_number":209,"context_line":"                self._validate_item_at(item, i)"},{"line_number":210,"context_line":"                i +\u003d 1"},{"line_number":211,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_253812d4","line":208,"updated":"2015-02-13 23:07:58.000000000","message":"Same here as above","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":205,"context_line":"        super(ListAttributeDefinition, self).validate(value, name)"},{"line_number":206,"context_line":"        if value is not None:"},{"line_number":207,"context_line":"            i \u003d 0"},{"line_number":208,"context_line":"            for item in value:"},{"line_number":209,"context_line":"                self._validate_item_at(item, i)"},{"line_number":210,"context_line":"                i +\u003d 1"},{"line_number":211,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_a2e00f97","line":208,"in_reply_to":"da86d52c_253812d4","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":211,"context_line":""},{"line_number":212,"context_line":"    def get_item_definition_at_index(self, index):"},{"line_number":213,"context_line":"        if isinstance(self.item_type, types.ListType):"},{"line_number":214,"context_line":"            if index \u003c len(self.item_type):"},{"line_number":215,"context_line":"                return self.item_type[index]"},{"line_number":216,"context_line":"            else:"},{"line_number":217,"context_line":"                return None"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_a5e7a245","line":214,"updated":"2015-02-13 23:07:58.000000000","message":"Would it be more performant to do:\n\n    try:\n        return self.item_type[index]\n    except IndexError:\n        return None\n\nAlso, do we want to support negative indexing on this? Negative indexing isn\u0027t guaranteed by the ListType check if I remember correctly","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":211,"context_line":""},{"line_number":212,"context_line":"    def get_item_definition_at_index(self, index):"},{"line_number":213,"context_line":"        if isinstance(self.item_type, types.ListType):"},{"line_number":214,"context_line":"            if index \u003c len(self.item_type):"},{"line_number":215,"context_line":"                return self.item_type[index]"},{"line_number":216,"context_line":"            else:"},{"line_number":217,"context_line":"                return None"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_00444fb5","line":214,"in_reply_to":"da86d52c_a5e7a245","updated":"2015-02-25 11:46:22.000000000","message":"As for me, both variants are ok. Same number of lines, same expressiveness and code readability. Though the very last else is redundant.\n\nSorry, I didn\u0027t get what you meant by \"Negative indexing isn\u0027t quaranteed by ListType check\". ListType is a list and python lists support negative indexing out of the box.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":221,"context_line":"    def _validate_item_at(self, item, index):"},{"line_number":222,"context_line":"        if isinstance(self.item_type, types.ListType):"},{"line_number":223,"context_line":"            if index \u003c len(self.item_type):"},{"line_number":224,"context_line":"                item_type \u003d self.item_type[index]"},{"line_number":225,"context_line":"                if not item_type.name:"},{"line_number":226,"context_line":"                    item_type.name \u003d \"%s[%i]\" % (self.name, index)"},{"line_number":227,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_e5c8baaa","line":224,"updated":"2015-02-13 23:07:58.000000000","message":"Instead of performing this check, would it be better to use get_item_definition_at_index?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":221,"context_line":"    def _validate_item_at(self, item, index):"},{"line_number":222,"context_line":"        if isinstance(self.item_type, types.ListType):"},{"line_number":223,"context_line":"            if index \u003c len(self.item_type):"},{"line_number":224,"context_line":"                item_type \u003d self.item_type[index]"},{"line_number":225,"context_line":"                if not item_type.name:"},{"line_number":226,"context_line":"                    item_type.name \u003d \"%s[%i]\" % (self.name, index)"},{"line_number":227,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_866058a6","line":224,"in_reply_to":"da86d52c_e5c8baaa","updated":"2015-02-25 11:46:22.000000000","message":"Nice catch! Thanks.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":239,"context_line":"    ALLOWED_PROPERTY_TYPES \u003d (AttributeDefinition,)"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    def _check_prop(self, key, item):"},{"line_number":242,"context_line":"        if not isinstance(item, self.ALLOWED_PROPERTY_TYPES) or \\"},{"line_number":243,"context_line":"                (key is not None and not isinstance(key, types.StringTypes)):"},{"line_number":244,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":245,"context_line":"                _(\u0027Invalid dict property type specification\u0027))"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_253d722d","line":242,"updated":"2015-02-13 23:07:58.000000000","message":"Style nit: Can we use parentheses instead of a \\?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":239,"context_line":"    ALLOWED_PROPERTY_TYPES \u003d (AttributeDefinition,)"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    def _check_prop(self, key, item):"},{"line_number":242,"context_line":"        if not isinstance(item, self.ALLOWED_PROPERTY_TYPES) or \\"},{"line_number":243,"context_line":"                (key is not None and not isinstance(key, types.StringTypes)):"},{"line_number":244,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":245,"context_line":"                _(\u0027Invalid dict property type specification\u0027))"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_622457c5","line":242,"in_reply_to":"da86d52c_253d722d","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":254,"context_line":"                 **kwargs):"},{"line_number":255,"context_line":"        super(DictAttributeDefinition, self).__init__(**kwargs)"},{"line_number":256,"context_line":"        if isinstance(properties, types.DictionaryType):"},{"line_number":257,"context_line":"            for key, value in properties.iteritems():"},{"line_number":258,"context_line":"                self._check_prop(key, value)"},{"line_number":259,"context_line":"            # NOTE: copy the properties dict"},{"line_number":260,"context_line":"            self.properties \u003d properties.copy()"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_85729e0f","line":257,"updated":"2015-02-13 23:07:58.000000000","message":"We should be using six.iteritems(properties) here or just items","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":254,"context_line":"                 **kwargs):"},{"line_number":255,"context_line":"        super(DictAttributeDefinition, self).__init__(**kwargs)"},{"line_number":256,"context_line":"        if isinstance(properties, types.DictionaryType):"},{"line_number":257,"context_line":"            for key, value in properties.iteritems():"},{"line_number":258,"context_line":"                self._check_prop(key, value)"},{"line_number":259,"context_line":"            # NOTE: copy the properties dict"},{"line_number":260,"context_line":"            self.properties \u003d properties.copy()"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_751b2f73","line":257,"in_reply_to":"da86d52c_85729e0f","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":257,"context_line":"            for key, value in properties.iteritems():"},{"line_number":258,"context_line":"                self._check_prop(key, value)"},{"line_number":259,"context_line":"            # NOTE: copy the properties dict"},{"line_number":260,"context_line":"            self.properties \u003d properties.copy()"},{"line_number":261,"context_line":""},{"line_number":262,"context_line":"            self._add_validator(\u0027keys\u0027,"},{"line_number":263,"context_line":"                                lambda v: set(v.keys()) \u003c\u003d set("}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_05106ea7","line":260,"updated":"2015-02-13 23:07:58.000000000","message":"Probably a silly question: Will the properties dictionary have nested dictionaries or lists that we may also want to copy? If so, shouldn\u0027t we be using copy.deepcopy here?\n\nThe same could be asked about ListAttributeDefinition too","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":257,"context_line":"            for key, value in properties.iteritems():"},{"line_number":258,"context_line":"                self._check_prop(key, value)"},{"line_number":259,"context_line":"            # NOTE: copy the properties dict"},{"line_number":260,"context_line":"            self.properties \u003d properties.copy()"},{"line_number":261,"context_line":""},{"line_number":262,"context_line":"            self._add_validator(\u0027keys\u0027,"},{"line_number":263,"context_line":"                                lambda v: set(v.keys()) \u003c\u003d set("}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_0c9809bf","line":260,"in_reply_to":"da86d52c_05106ea7","updated":"2015-02-25 11:46:22.000000000","message":"ListAttributeDefinition can\u0027t have nested lists or dicts as values, only simple data types (int, string, boolean etc) are allowed.\n\nIt is possible for a DictAttributeDefinition to have properties dictionary in the form {\u0027foo\u0027: [\u0027a\u0027, \u0027list\u0027, \u0027of\u0027, \u0027simple\u0027, \u0027types\u0027]}. But as long as properties are copied only to perform keys validation (see lines 263-265) regardless of real values, I see no need for deepcopy here.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":296,"context_line":"    def _set_name(self, value):"},{"line_number":297,"context_line":"        super(DictAttributeDefinition, self)._set_name(value)"},{"line_number":298,"context_line":"        if isinstance(self.properties, types.DictionaryType):"},{"line_number":299,"context_line":"            for k, v in self.properties.iteritems():"},{"line_number":300,"context_line":"                # noinspection PyProtectedMember"},{"line_number":301,"context_line":"                v._set_name(value)"},{"line_number":302,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_a55ec277","line":299,"updated":"2015-02-13 23:07:58.000000000","message":"Same comment as above re iteritems","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":296,"context_line":"    def _set_name(self, value):"},{"line_number":297,"context_line":"        super(DictAttributeDefinition, self)._set_name(value)"},{"line_number":298,"context_line":"        if isinstance(self.properties, types.DictionaryType):"},{"line_number":299,"context_line":"            for k, v in self.properties.iteritems():"},{"line_number":300,"context_line":"                # noinspection PyProtectedMember"},{"line_number":301,"context_line":"                v._set_name(value)"},{"line_number":302,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_3598d7bf","line":299,"in_reply_to":"da86d52c_a55ec277","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":306,"context_line":"    def validate(self, value, name\u003dNone):"},{"line_number":307,"context_line":"        super(DictAttributeDefinition, self).validate(value, name)"},{"line_number":308,"context_line":"        if value is not None:"},{"line_number":309,"context_line":"            for k, v in value.iteritems():"},{"line_number":310,"context_line":"                self._validate_item_with_key(v, k)"},{"line_number":311,"context_line":""},{"line_number":312,"context_line":"    def _validate_item_with_key(self, value, key):"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_c5f1f66b","line":309,"updated":"2015-02-13 23:07:58.000000000","message":"Same comment re iteritems","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":306,"context_line":"    def validate(self, value, name\u003dNone):"},{"line_number":307,"context_line":"        super(DictAttributeDefinition, self).validate(value, name)"},{"line_number":308,"context_line":"        if value is not None:"},{"line_number":309,"context_line":"            for k, v in value.iteritems():"},{"line_number":310,"context_line":"                self._validate_item_with_key(v, k)"},{"line_number":311,"context_line":""},{"line_number":312,"context_line":"    def _validate_item_with_key(self, value, key):"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_55c38b88","line":309,"in_reply_to":"da86d52c_c5f1f66b","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":344,"context_line":"            i \u003d 0"},{"line_number":345,"context_line":"            try:"},{"line_number":346,"context_line":"                for f, m in validators:"},{"line_number":347,"context_line":"                    self._add_validator(format(\"custom_%i\" % i), f, m)"},{"line_number":348,"context_line":"                    i +\u003d 1"},{"line_number":349,"context_line":"            except Exception:"},{"line_number":350,"context_line":"                raise exc.InvalidArtifactTypePropertyDefinition("}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_483a7b35","line":347,"updated":"2015-02-13 23:07:58.000000000","message":"Why are we calling format here?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":344,"context_line":"            i \u003d 0"},{"line_number":345,"context_line":"            try:"},{"line_number":346,"context_line":"                for f, m in validators:"},{"line_number":347,"context_line":"                    self._add_validator(format(\"custom_%i\" % i), f, m)"},{"line_number":348,"context_line":"                    i +\u003d 1"},{"line_number":349,"context_line":"            except Exception:"},{"line_number":350,"context_line":"                raise exc.InvalidArtifactTypePropertyDefinition("}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_2cc94d59","line":347,"in_reply_to":"da86d52c_483a7b35","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":346,"context_line":"                for f, m in validators:"},{"line_number":347,"context_line":"                    self._add_validator(format(\"custom_%i\" % i), f, m)"},{"line_number":348,"context_line":"                    i +\u003d 1"},{"line_number":349,"context_line":"            except Exception:"},{"line_number":350,"context_line":"                raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":351,"context_line":"                    _(\"Custom validators list should contain tuples \""},{"line_number":352,"context_line":"                      \"\u0027(function, message)\u0027\"))"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_48f35b9f","line":349,"updated":"2015-02-13 23:07:58.000000000","message":"Why are we catching a generic Exception here?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":346,"context_line":"                for f, m in validators:"},{"line_number":347,"context_line":"                    self._add_validator(format(\"custom_%i\" % i), f, m)"},{"line_number":348,"context_line":"                    i +\u003d 1"},{"line_number":349,"context_line":"            except Exception:"},{"line_number":350,"context_line":"                raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":351,"context_line":"                    _(\"Custom validators list should contain tuples \""},{"line_number":352,"context_line":"                      \"\u0027(function, message)\u0027\"))"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_8c65d91f","line":349,"in_reply_to":"da86d52c_48f35b9f","updated":"2015-02-25 11:46:22.000000000","message":"This code processes user-defined validators and adds them to the property\u0027s definition. As long as the exception message notifies user of the wrong validator list format, we can possibly narrow the exception class to ValueError (in case of non-tuple format).","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":365,"context_line":"                    self.validate(allowed_value, \u0027allowed_value\u0027)"},{"line_number":366,"context_line":"            except exc.InvalidArtifactPropertyValue:"},{"line_number":367,"context_line":"                raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":368,"context_line":"                    _(\"Allowed value is invalid\"))"},{"line_number":369,"context_line":""},{"line_number":370,"context_line":"    def allowed_values(self, values):"},{"line_number":371,"context_line":"        self._allowed_values \u003d values[:]"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_a8777707","line":368,"updated":"2015-02-13 23:07:58.000000000","message":"Could this be a bit more specific maybe?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":365,"context_line":"                    self.validate(allowed_value, \u0027allowed_value\u0027)"},{"line_number":366,"context_line":"            except exc.InvalidArtifactPropertyValue:"},{"line_number":367,"context_line":"                raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":368,"context_line":"                    _(\"Allowed value is invalid\"))"},{"line_number":369,"context_line":""},{"line_number":370,"context_line":"    def allowed_values(self, values):"},{"line_number":371,"context_line":"        self._allowed_values \u003d values[:]"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_4fabd374","line":368,"in_reply_to":"da86d52c_a8777707","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":384,"context_line":"class RelationDefinition(AttributeDefinition):"},{"line_number":385,"context_line":"    def __init__(self, internal\u003dFalse, **kwargs):"},{"line_number":386,"context_line":"        self.internal \u003d internal"},{"line_number":387,"context_line":"        mutable \u003d kwargs.get(\u0027mutable\u0027)"},{"line_number":388,"context_line":"        if mutable is True:"},{"line_number":389,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":390,"context_line":"                _(\"Dependency relations cannot be mutable\"))"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_68e3bfa4","line":387,"updated":"2015-02-13 23:07:58.000000000","message":"Wouldn\u0027t the following be cleaner\n\n    kwargs.setdefault(\u0027mutable\u0027, False)\n    if kwargs[\u0027mutable\u0027] is True:\n        raise ...\n    super(RelationDefinition, self).__init__(**kwargs)","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":384,"context_line":"class RelationDefinition(AttributeDefinition):"},{"line_number":385,"context_line":"    def __init__(self, internal\u003dFalse, **kwargs):"},{"line_number":386,"context_line":"        self.internal \u003d internal"},{"line_number":387,"context_line":"        mutable \u003d kwargs.get(\u0027mutable\u0027)"},{"line_number":388,"context_line":"        if mutable is True:"},{"line_number":389,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":390,"context_line":"                _(\"Dependency relations cannot be mutable\"))"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_efeac7aa","line":387,"in_reply_to":"da86d52c_68e3bfa4","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":409,"context_line":"        self.prop \u003d prop"},{"line_number":410,"context_line":"        self.collection_wrapper_class \u003d collection_wrapper_class"},{"line_number":411,"context_line":""},{"line_number":412,"context_line":"    def __get__(self, instance, owner):"},{"line_number":413,"context_line":"        if instance is None:"},{"line_number":414,"context_line":"            return self.prop"},{"line_number":415,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_4bc99578","line":412,"updated":"2015-02-13 23:07:58.000000000","message":"Is there a protocol that uses __get__ and __set__ or are these being defined this way to take advantage of name munging or to be extra explicit about the privacy of these methods?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":409,"context_line":"        self.prop \u003d prop"},{"line_number":410,"context_line":"        self.collection_wrapper_class \u003d collection_wrapper_class"},{"line_number":411,"context_line":""},{"line_number":412,"context_line":"    def __get__(self, instance, owner):"},{"line_number":413,"context_line":"        if instance is None:"},{"line_number":414,"context_line":"            return self.prop"},{"line_number":415,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_cfb42384","line":412,"in_reply_to":"da86d52c_4bc99578","updated":"2015-02-25 11:46:22.000000000","message":"Ian, that\u0027s a common pattern for building property objects.\nMore info about descriptors can been found here: https://docs.python.org/2/howto/descriptor.html","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":423,"context_line":"                    if self.prop.readonly:"},{"line_number":424,"context_line":"                        readonly \u003d True"},{"line_number":425,"context_line":"                    elif (not self.prop.mutable"},{"line_number":426,"context_line":"                          and hasattr(instance, \u0027__is_mutable__\u0027)"},{"line_number":427,"context_line":"                          and not hasattr(instance,"},{"line_number":428,"context_line":"                                          \u0027__suspend_mutability_checks__\u0027)):"},{"line_number":429,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_2b7aa125","line":426,"updated":"2015-02-13 23:07:58.000000000","message":"Why are we checking for double-underscore attributes? Why aren\u0027t we checking for public attributes?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":423,"context_line":"                    if self.prop.readonly:"},{"line_number":424,"context_line":"                        readonly \u003d True"},{"line_number":425,"context_line":"                    elif (not self.prop.mutable"},{"line_number":426,"context_line":"                          and hasattr(instance, \u0027__is_mutable__\u0027)"},{"line_number":427,"context_line":"                          and not hasattr(instance,"},{"line_number":428,"context_line":"                                          \u0027__suspend_mutability_checks__\u0027)):"},{"line_number":429,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_86968d3d","line":426,"in_reply_to":"da86d52c_2b7aa125","updated":"2015-02-25 16:00:04.000000000","message":"mutability is part of logic that should not be revealed to end user.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":427,"context_line":"                          and not hasattr(instance,"},{"line_number":428,"context_line":"                                          \u0027__suspend_mutability_checks__\u0027)):"},{"line_number":429,"context_line":""},{"line_number":430,"context_line":"                        readonly \u003d not instance.__is_mutable__()"},{"line_number":431,"context_line":"                    else:"},{"line_number":432,"context_line":"                        readonly \u003d False"},{"line_number":433,"context_line":"                    if readonly:"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_4b90b54e","line":430,"updated":"2015-02-13 23:07:58.000000000","message":"Why are we calling double-underscore methods here?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":427,"context_line":"                          and not hasattr(instance,"},{"line_number":428,"context_line":"                                          \u0027__suspend_mutability_checks__\u0027)):"},{"line_number":429,"context_line":""},{"line_number":430,"context_line":"                        readonly \u003d not instance.__is_mutable__()"},{"line_number":431,"context_line":"                    else:"},{"line_number":432,"context_line":"                        readonly \u003d False"},{"line_number":433,"context_line":"                    if readonly:"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_9c97bc39","line":430,"in_reply_to":"da86d52c_4b90b54e","updated":"2015-02-25 16:00:04.000000000","message":"see comment above","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":431,"context_line":"                    else:"},{"line_number":432,"context_line":"                        readonly \u003d False"},{"line_number":433,"context_line":"                    if readonly:"},{"line_number":434,"context_line":"                        v \u003d v.__immutable__()"},{"line_number":435,"context_line":"                return v"},{"line_number":436,"context_line":""},{"line_number":437,"context_line":"    def __set__(self, instance, value, ignore_mutability\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_eba96991","line":434,"updated":"2015-02-13 23:07:58.000000000","message":"Why are we calling this directly here? This seems like a terrible idea.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":431,"context_line":"                    else:"},{"line_number":432,"context_line":"                        readonly \u003d False"},{"line_number":433,"context_line":"                    if readonly:"},{"line_number":434,"context_line":"                        v \u003d v.__immutable__()"},{"line_number":435,"context_line":"                return v"},{"line_number":436,"context_line":""},{"line_number":437,"context_line":"    def __set__(self, instance, value, ignore_mutability\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_5760bda4","line":434,"in_reply_to":"da86d52c_eba96991","updated":"2015-02-25 16:00:04.000000000","message":"Seems like the better name will be \u0027__make_immutable__\u0027, as long as this function wraps the given collection in ReadonlyValidated collection class.\nOtherwise I see no problem in calling internal method inside of descriptor\u0027s __get__ method.\n\nIan, what do you suggest?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":437,"context_line":"    def __set__(self, instance, value, ignore_mutability\u003dFalse):"},{"line_number":438,"context_line":"        if instance:"},{"line_number":439,"context_line":"            if self.prop.readonly:"},{"line_number":440,"context_line":"                if hasattr(instance, \u0027_\u0027 + self.prop.name):"},{"line_number":441,"context_line":"                    raise exc.InvalidArtifactPropertyValue("},{"line_number":442,"context_line":"                        _(\u0027Attempt to set readonly property\u0027))"},{"line_number":443,"context_line":"            if not self.prop.mutable:"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_eb97a938","line":440,"updated":"2015-02-13 23:07:58.000000000","message":"Why are we checking for \"protected\"/\"private\" attributes here?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":437,"context_line":"    def __set__(self, instance, value, ignore_mutability\u003dFalse):"},{"line_number":438,"context_line":"        if instance:"},{"line_number":439,"context_line":"            if self.prop.readonly:"},{"line_number":440,"context_line":"                if hasattr(instance, \u0027_\u0027 + self.prop.name):"},{"line_number":441,"context_line":"                    raise exc.InvalidArtifactPropertyValue("},{"line_number":442,"context_line":"                        _(\u0027Attempt to set readonly property\u0027))"},{"line_number":443,"context_line":"            if not self.prop.mutable:"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_9297a339","line":440,"in_reply_to":"da86d52c_eb97a938","updated":"2015-02-25 16:00:04.000000000","message":"Every user-defined property (with name \"prop\" for example) is represented by \"prop\" property and underlying \"_prop\" internal field for storing its value. \nWe expect that all properties modifications from outside will be carried out by operating with \"prop\", not \"_prop\". \nIn case of successful value validation in the descriptor\u0027s __set__ method (which is called every call like instance.prop \u003d \"value\"), the internal _prop attribute will be set to the given value.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4a50679c0498e39584d9a38402b3699fa0718110","unresolved":false,"context_lines":[{"line_number":452,"context_line":"                value \u003d self.collection_wrapper_class(value)"},{"line_number":453,"context_line":"                value.property \u003d self.prop"},{"line_number":454,"context_line":"            self.prop.validate(value)"},{"line_number":455,"context_line":"            setattr(instance, \u0027_\u0027 + self.prop.name, value)"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":""},{"line_number":458,"context_line":"class ArtifactAttributes(object):"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_4b9ef555","line":455,"updated":"2015-02-13 23:07:58.000000000","message":"Further, why are we setting them?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":452,"context_line":"                value \u003d self.collection_wrapper_class(value)"},{"line_number":453,"context_line":"                value.property \u003d self.prop"},{"line_number":454,"context_line":"            self.prop.validate(value)"},{"line_number":455,"context_line":"            setattr(instance, \u0027_\u0027 + self.prop.name, value)"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":""},{"line_number":458,"context_line":"class ArtifactAttributes(object):"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_72bdcfb6","line":455,"in_reply_to":"da86d52c_4b9ef555","updated":"2015-02-25 16:00:04.000000000","message":"see comment above","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":483,"context_line":"        if len(dict_props) \u003d\u003d 1:"},{"line_number":484,"context_line":"            return dict_props[0]"},{"line_number":485,"context_line":""},{"line_number":486,"context_line":"    @property"},{"line_number":487,"context_line":"    def tags(self):"},{"line_number":488,"context_line":"        return self.properties.get(\u0027tags\u0027)"},{"line_number":489,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_011f47b8","line":486,"updated":"2015-02-16 22:00:59.000000000","message":"Does this need to be a property?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":483,"context_line":"        if len(dict_props) \u003d\u003d 1:"},{"line_number":484,"context_line":"            return dict_props[0]"},{"line_number":485,"context_line":""},{"line_number":486,"context_line":"    @property"},{"line_number":487,"context_line":"    def tags(self):"},{"line_number":488,"context_line":"        return self.properties.get(\u0027tags\u0027)"},{"line_number":489,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_a9ce0f2c","line":486,"in_reply_to":"da86d52c_011f47b8","updated":"2015-02-25 11:46:22.000000000","message":"Ian, do you suggest to call obj.properties.get(\u0027tags\u0027) all the time?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":526,"context_line":""},{"line_number":527,"context_line":"    @property"},{"line_number":528,"context_line":"    def type_name(self):"},{"line_number":529,"context_line":"        return self._type_name"},{"line_number":530,"context_line":""},{"line_number":531,"context_line":"    @property"},{"line_number":532,"context_line":"    def type_display_name(self):"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_217b6bbf","line":529,"updated":"2015-02-16 22:00:59.000000000","message":"Why are we creating properties for these? Is this an attempt to prevent something or someone from modifying the values? Who are we protecting against exactly? Why? They can still change _type_name or _type_display_name or any of the attributes they want by using the value that stores the data.\n\nIf you want to really prevent people from setting attributes (which I don\u0027t see the point of) you need to properly override __setattr__.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":526,"context_line":""},{"line_number":527,"context_line":"    @property"},{"line_number":528,"context_line":"    def type_name(self):"},{"line_number":529,"context_line":"        return self._type_name"},{"line_number":530,"context_line":""},{"line_number":531,"context_line":"    @property"},{"line_number":532,"context_line":"    def type_display_name(self):"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_d2559b50","line":529,"in_reply_to":"da86d52c_217b6bbf","updated":"2015-02-25 16:00:04.000000000","message":"I\u0027ve already mentioned prop/_prop issues in the comment above. \nIf someone would like to shoot himself in the foot - they may override _type_name_/_endpoint/_whatsoever to their own pleasure - it\u0027s up to them. \n\nBut as I\u0027ve already mentioned, there is a convention of public methods/attributes usage and we suggest to cling to it.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":580,"context_line":"    attributes_to_wrap \u003d {}"},{"line_number":581,"context_line":""},{"line_number":582,"context_line":"    for base in cls.__mro__:"},{"line_number":583,"context_line":"        for name, value in vars(base).items():"},{"line_number":584,"context_line":"            if name \u003d\u003d \u0027__type_name__\u0027:"},{"line_number":585,"context_line":"                if not type_name:"},{"line_number":586,"context_line":"                    type_name \u003d cls.__type_name__"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_dc1fd6b6","line":583,"updated":"2015-02-16 22:00:59.000000000","message":"Why not use six.iteritems?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":580,"context_line":"    attributes_to_wrap \u003d {}"},{"line_number":581,"context_line":""},{"line_number":582,"context_line":"    for base in cls.__mro__:"},{"line_number":583,"context_line":"        for name, value in vars(base).items():"},{"line_number":584,"context_line":"            if name \u003d\u003d \u0027__type_name__\u0027:"},{"line_number":585,"context_line":"                if not type_name:"},{"line_number":586,"context_line":"                    type_name \u003d cls.__type_name__"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_2f24dfc3","line":583,"in_reply_to":"da86d52c_dc1fd6b6","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":581,"context_line":""},{"line_number":582,"context_line":"    for base in cls.__mro__:"},{"line_number":583,"context_line":"        for name, value in vars(base).items():"},{"line_number":584,"context_line":"            if name \u003d\u003d \u0027__type_name__\u0027:"},{"line_number":585,"context_line":"                if not type_name:"},{"line_number":586,"context_line":"                    type_name \u003d cls.__type_name__"},{"line_number":587,"context_line":"            elif name \u003d\u003d \u0027__type_version__\u0027:"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_9c28fe34","line":584,"updated":"2015-02-16 22:00:59.000000000","message":"I think this would be far simpler if you instead had something like:\n\n    metadata_dict \u003d {\n        \u0027__type_display_name__\u0027: None,\n        \u0027__type_name__\u0027: None,\n        \u0027__type_version__\u0027: None,\n        \u0027__type_description__\u0027: None,\n        \u0027__endpoint__\u0027: None,\n    }\n\n    for base in cls.__mro__:\n        for name, value in vars(base).items():\n            if name in metadata_dict and metadata_dict[name] is None:\n                 metadata_dict[name] \u003d getattr(cls, name)\n            elif (base is not cls and name not in attrs and\n                  name not in attributes_to_wrap):\n                # etc.\n\n     # ...\n     metadata_dict.setdefault(\u0027__type_name__\u0027, cls.__name__)\n     kwargs \u003d dict((k.strip(\u0027__\u0027), v) for k, v in metadata_dict.items())\n     meta \u003d ArtifactTypeMetadata(**kwargs)\n\nPersonally, I think it\u0027d be awesome if you weren\u0027t calling vars on base too but I guess defining a class level attribute that people have to maintain is too much work.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":581,"context_line":""},{"line_number":582,"context_line":"    for base in cls.__mro__:"},{"line_number":583,"context_line":"        for name, value in vars(base).items():"},{"line_number":584,"context_line":"            if name \u003d\u003d \u0027__type_name__\u0027:"},{"line_number":585,"context_line":"                if not type_name:"},{"line_number":586,"context_line":"                    type_name \u003d cls.__type_name__"},{"line_number":587,"context_line":"            elif name \u003d\u003d \u0027__type_version__\u0027:"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_a96a8feb","line":584,"in_reply_to":"da86d52c_9c28fe34","updated":"2015-02-25 11:46:22.000000000","message":"Wow, I\u0027ve done exactly the same refactor while adding custom logic support :)\nThis will be fixed in a different commit https://review.openstack.org/#/c/157099/","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":596,"context_line":"            elif name \u003d\u003d \u0027__type_display_name__\u0027:"},{"line_number":597,"context_line":"                if not type_display_name:"},{"line_number":598,"context_line":"                    type_display_name \u003d cls.__type_display_name__"},{"line_number":599,"context_line":"            elif base is not cls and name not in attrs \\"},{"line_number":600,"context_line":"                    and name not in attributes_to_wrap:"},{"line_number":601,"context_line":"                if isinstance(value, AttributeDefinition):"},{"line_number":602,"context_line":"                    attributes_to_wrap[name] \u003d value"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_5c84c65c","line":599,"updated":"2015-02-16 22:00:59.000000000","message":"Please wrap this conditional in parentheses to avoid needing a \\.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":596,"context_line":"            elif name \u003d\u003d \u0027__type_display_name__\u0027:"},{"line_number":597,"context_line":"                if not type_display_name:"},{"line_number":598,"context_line":"                    type_display_name \u003d cls.__type_display_name__"},{"line_number":599,"context_line":"            elif base is not cls and name not in attrs \\"},{"line_number":600,"context_line":"                    and name not in attributes_to_wrap:"},{"line_number":601,"context_line":"                if isinstance(value, AttributeDefinition):"},{"line_number":602,"context_line":"                    attributes_to_wrap[name] \u003d value"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_c96b43ef","line":599,"in_reply_to":"da86d52c_5c84c65c","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":603,"context_line":"                elif isinstance(value, ArtifactPropertyDescriptor):"},{"line_number":604,"context_line":"                    attributes_to_wrap[name] \u003d value.prop"},{"line_number":605,"context_line":""},{"line_number":606,"context_line":"    for k, v in attributes_to_wrap.items():"},{"line_number":607,"context_line":"        attrs[k] \u003d v"},{"line_number":608,"context_line":""},{"line_number":609,"context_line":"    meta \u003d ArtifactTypeMetadata(type_name\u003dtype_name or cls.__name__,"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_1c432eb0","line":606,"updated":"2015-02-16 22:00:59.000000000","message":"Is there a reason to use a loop here instead of simply calling\n\n     attrs.update(attributes_to_wrap)","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":603,"context_line":"                elif isinstance(value, ArtifactPropertyDescriptor):"},{"line_number":604,"context_line":"                    attributes_to_wrap[name] \u003d value.prop"},{"line_number":605,"context_line":""},{"line_number":606,"context_line":"    for k, v in attributes_to_wrap.items():"},{"line_number":607,"context_line":"        attrs[k] \u003d v"},{"line_number":608,"context_line":""},{"line_number":609,"context_line":"    meta \u003d ArtifactTypeMetadata(type_name\u003dtype_name or cls.__name__,"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_697c17b6","line":606,"in_reply_to":"da86d52c_1c432eb0","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":619,"context_line":"                  \"\u0027metadata\u0027\"))"},{"line_number":620,"context_line":"        if isinstance(v, AttributeDefinition):"},{"line_number":621,"context_line":"            # noinspection PyProtectedMember"},{"line_number":622,"context_line":"            v._set_name(k)"},{"line_number":623,"context_line":"            wrapper_class \u003d None"},{"line_number":624,"context_line":"            if isinstance(v, ListAttributeDefinition):"},{"line_number":625,"context_line":"                wrapper_class \u003d type(\"ValidatedList\", (list,), {})"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_fc757afa","line":622,"updated":"2015-02-16 22:00:59.000000000","message":"Again, why are we using protected/private methods on something that isn\u0027t self?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":619,"context_line":"                  \"\u0027metadata\u0027\"))"},{"line_number":620,"context_line":"        if isinstance(v, AttributeDefinition):"},{"line_number":621,"context_line":"            # noinspection PyProtectedMember"},{"line_number":622,"context_line":"            v._set_name(k)"},{"line_number":623,"context_line":"            wrapper_class \u003d None"},{"line_number":624,"context_line":"            if isinstance(v, ListAttributeDefinition):"},{"line_number":625,"context_line":"                wrapper_class \u003d type(\"ValidatedList\", (list,), {})"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_60b25a4d","line":622,"in_reply_to":"da86d52c_fc757afa","updated":"2015-02-25 16:00:04.000000000","message":"Sorry, I didn\u0027t get it - with what exactly do you see trouble here? Could you be more explicit with \"something that isn\u0027t self\" part?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":625,"context_line":"                wrapper_class \u003d type(\"ValidatedList\", (list,), {})"},{"line_number":626,"context_line":"                _add_validation_to_list(wrapper_class)"},{"line_number":627,"context_line":"            if isinstance(v, DictAttributeDefinition):"},{"line_number":628,"context_line":"                wrapper_class \u003d type(\"ValidatedDict\", (dict,), {})"},{"line_number":629,"context_line":"                _add_validation_to_dict(wrapper_class)"},{"line_number":630,"context_line":"            prop_descr \u003d ArtifactPropertyDescriptor(v, wrapper_class)"},{"line_number":631,"context_line":"            setattr(cls, k, prop_descr)"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_dc4d16c7","line":628,"updated":"2015-02-16 22:00:59.000000000","message":"Why are these types being created dynamically? Perhaps a better question is why do they *need* to be created dynamically?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":625,"context_line":"                wrapper_class \u003d type(\"ValidatedList\", (list,), {})"},{"line_number":626,"context_line":"                _add_validation_to_list(wrapper_class)"},{"line_number":627,"context_line":"            if isinstance(v, DictAttributeDefinition):"},{"line_number":628,"context_line":"                wrapper_class \u003d type(\"ValidatedDict\", (dict,), {})"},{"line_number":629,"context_line":"                _add_validation_to_dict(wrapper_class)"},{"line_number":630,"context_line":"            prop_descr \u003d ArtifactPropertyDescriptor(v, wrapper_class)"},{"line_number":631,"context_line":"            setattr(cls, k, prop_descr)"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_0396083f","line":628,"in_reply_to":"da86d52c_dc4d16c7","updated":"2015-02-25 16:00:04.000000000","message":"See comment below about \"wrappers simplicity\"","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":632,"context_line":"            meta.attributes.add(v)"},{"line_number":633,"context_line":""},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"def _validating_method(method, clazz):"},{"line_number":636,"context_line":"    def wrapper(self, *args, **kwargs):"},{"line_number":637,"context_line":"        list_copy \u003d clazz(self)"},{"line_number":638,"context_line":"        method(list_copy, *args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_9c6f1efc","line":635,"updated":"2015-02-16 22:00:59.000000000","message":"Convention is to use klass or cls","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":632,"context_line":"            meta.attributes.add(v)"},{"line_number":633,"context_line":""},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"def _validating_method(method, clazz):"},{"line_number":636,"context_line":"    def wrapper(self, *args, **kwargs):"},{"line_number":637,"context_line":"        list_copy \u003d clazz(self)"},{"line_number":638,"context_line":"        method(list_copy, *args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_7a3933a3","line":635,"in_reply_to":"da86d52c_9c6f1efc","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":633,"context_line":""},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"def _validating_method(method, clazz):"},{"line_number":636,"context_line":"    def wrapper(self, *args, **kwargs):"},{"line_number":637,"context_line":"        list_copy \u003d clazz(self)"},{"line_number":638,"context_line":"        method(list_copy, *args, **kwargs)"},{"line_number":639,"context_line":"        self.property.validate(list_copy)"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_fc565a29","line":636,"updated":"2015-02-16 22:00:59.000000000","message":"Why is this called \"list_copy\"? Isn\u0027t it more generically, \"instance_copy\"?","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":633,"context_line":""},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"def _validating_method(method, clazz):"},{"line_number":636,"context_line":"    def wrapper(self, *args, **kwargs):"},{"line_number":637,"context_line":"        list_copy \u003d clazz(self)"},{"line_number":638,"context_line":"        method(list_copy, *args, **kwargs)"},{"line_number":639,"context_line":"        self.property.validate(list_copy)"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_7a2e9344","line":636,"in_reply_to":"da86d52c_fc565a29","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":658,"context_line":"            setattr(class_to_add, method_name, _immutable_method(method))"},{"line_number":659,"context_line":""},{"line_number":660,"context_line":""},{"line_number":661,"context_line":"def _add_validation_wrappers(class_to_validate, base_class, validated_methods):"},{"line_number":662,"context_line":"    for method_name in validated_methods:"},{"line_number":663,"context_line":"        method \u003d getattr(class_to_validate, method_name, None)"},{"line_number":664,"context_line":"        if method:"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_17b3094e","line":661,"updated":"2015-02-16 22:00:59.000000000","message":"I\u0027m very confident this and the related dynamic list/dictionary class wrappers can be vastly simplified. We should probably discuss this more via the ML.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":658,"context_line":"            setattr(class_to_add, method_name, _immutable_method(method))"},{"line_number":659,"context_line":""},{"line_number":660,"context_line":""},{"line_number":661,"context_line":"def _add_validation_wrappers(class_to_validate, base_class, validated_methods):"},{"line_number":662,"context_line":"    for method_name in validated_methods:"},{"line_number":663,"context_line":"        method \u003d getattr(class_to_validate, method_name, None)"},{"line_number":664,"context_line":"        if method:"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_2326ac68","line":661,"in_reply_to":"da86d52c_17b3094e","updated":"2015-02-25 16:00:04.000000000","message":"Yes, most probably it can be made simpler, however I\u0027d prefer to land it as is (unless it has some logical errors or other critical issues) and do the optimization later as independent tasks. The discussions (especially ML) tend to take time, and if we try to discuss, debate and optimize  each and every solution in this chain of commits it make take forever or even longer.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":688,"context_line":""},{"line_number":689,"context_line":""},{"line_number":690,"context_line":"def _kwarg_init_constructor(self, **kwargs):"},{"line_number":691,"context_line":"    self.__suspend_mutability_checks__ \u003d True"},{"line_number":692,"context_line":"    try:"},{"line_number":693,"context_line":"        for k in kwargs:"},{"line_number":694,"context_line":"            if not hasattr(type(self), k):"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_1770693f","line":691,"updated":"2015-02-16 22:00:59.000000000","message":"If this is a temporary implementation detail, I\u0027m not sure why it can\u0027t be named something else preferably without using double-underscores to surround the name.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"5dad106c868c69e0bf4473b8f687230fefe853ee","unresolved":false,"context_lines":[{"line_number":688,"context_line":""},{"line_number":689,"context_line":""},{"line_number":690,"context_line":"def _kwarg_init_constructor(self, **kwargs):"},{"line_number":691,"context_line":"    self.__suspend_mutability_checks__ \u003d True"},{"line_number":692,"context_line":"    try:"},{"line_number":693,"context_line":"        for k in kwargs:"},{"line_number":694,"context_line":"            if not hasattr(type(self), k):"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_e34d749b","line":691,"in_reply_to":"da86d52c_1770693f","updated":"2015-02-25 16:00:04.000000000","message":"It\u0027s a flag that corresponds to internal logic of values\u0027 validation. I\u0027d leave it the way it is now.","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":701,"context_line":""},{"line_number":702,"context_line":"def _validate_required(self, attribute_dict):"},{"line_number":703,"context_line":"    for k, v in six.iteritems(attribute_dict):"},{"line_number":704,"context_line":"        if v.required:"},{"line_number":705,"context_line":"            if not hasattr(self, k) or getattr(self, k) is None:"},{"line_number":706,"context_line":"                raise exc.InvalidArtifactPropertyValue(name\u003dk, val\u003dNone,"},{"line_number":707,"context_line":"                                                       msg\u003d_("}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_1771490c","line":704,"updated":"2015-02-16 22:00:59.000000000","message":"Why not collapse this if and the next into one? It would reduce the indentation level of the raise statement","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":701,"context_line":""},{"line_number":702,"context_line":"def _validate_required(self, attribute_dict):"},{"line_number":703,"context_line":"    for k, v in six.iteritems(attribute_dict):"},{"line_number":704,"context_line":"        if v.required:"},{"line_number":705,"context_line":"            if not hasattr(self, k) or getattr(self, k) is None:"},{"line_number":706,"context_line":"                raise exc.InvalidArtifactPropertyValue(name\u003dk, val\u003dNone,"},{"line_number":707,"context_line":"                                                       msg\u003d_("}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_5a462f50","line":704,"in_reply_to":"da86d52c_1771490c","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"4c9830d75e25c4cd7239e46a2d5eb1fdddac5cc1","unresolved":false,"context_lines":[{"line_number":703,"context_line":"    for k, v in six.iteritems(attribute_dict):"},{"line_number":704,"context_line":"        if v.required:"},{"line_number":705,"context_line":"            if not hasattr(self, k) or getattr(self, k) is None:"},{"line_number":706,"context_line":"                raise exc.InvalidArtifactPropertyValue(name\u003dk, val\u003dNone,"},{"line_number":707,"context_line":"                                                       msg\u003d_("},{"line_number":708,"context_line":"                                                           \u0027Value is \u0027"},{"line_number":709,"context_line":"                                                           \u0027required\u0027))"}],"source_content_type":"text/x-python","patch_set":48,"id":"da86d52c_77d0c5c9","line":706,"updated":"2015-02-16 22:00:59.000000000","message":"Further, why not put all of the parameters on the next line, e.g.,\n\n    raise exc.InvalidArtifactPropertyValue(\n        name\u003dk, val\u003dNone, msg\u003d_(\u0027Value is required\u0027))","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"d46a12c3639da2cb14624d5a1c5e704d249089ad","unresolved":false,"context_lines":[{"line_number":703,"context_line":"    for k, v in six.iteritems(attribute_dict):"},{"line_number":704,"context_line":"        if v.required:"},{"line_number":705,"context_line":"            if not hasattr(self, k) or getattr(self, k) is None:"},{"line_number":706,"context_line":"                raise exc.InvalidArtifactPropertyValue(name\u003dk, val\u003dNone,"},{"line_number":707,"context_line":"                                                       msg\u003d_("},{"line_number":708,"context_line":"                                                           \u0027Value is \u0027"},{"line_number":709,"context_line":"                                                           \u0027required\u0027))"}],"source_content_type":"text/x-python","patch_set":48,"id":"ba7be1f8_3a497b60","line":706,"in_reply_to":"da86d52c_77d0c5c9","updated":"2015-02-25 11:46:22.000000000","message":"Done","commit_id":"cc8d5f27568b5921252a1d5097e52df401a1d9d8"},{"author":{"_account_id":12000,"name":"Ian Cordasco","email":"sigmavirus24@gmail.com","username":"sigmavirus24"},"change_message_id":"65c22ec03e1ef9e691daec8710190bbdcb2143a4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":49,"id":"da86d52c_574ca19d","updated":"2015-02-16 22:01:58.000000000","message":"I\u0027m not going to reiterate all 36 of my prior review comments so please see them here: https://review.openstack.org/#/c/119174/48/glance/common/artifacts/declarative.py","commit_id":"6074cd20d8d4c539d706b7630fd85165fc40972e"},{"author":{"_account_id":11391,"name":"Mikhail Fedosin","email":"mfedosin@redhat.com","username":"fedosinme"},"change_message_id":"2894a348d3bf1e757b787644de72b49d23774375","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":49,"id":"da86d52c_2d2b5a34","in_reply_to":"da86d52c_574ca19d","updated":"2015-02-16 23:00:23.000000000","message":"Hey Ian! Thank you for review!\n\nDon\u0027t pay attention - it was my rebase after I had added pagination on api layer.\n\nYour comments will necessarily be taken into account.","commit_id":"6074cd20d8d4c539d706b7630fd85165fc40972e"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2014 Mirantis, Inc."},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_2243d2af","line":1,"updated":"2015-03-10 12:50:38.000000000","message":"2015","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2014 Mirantis, Inc."},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_586784b7","line":1,"in_reply_to":"9a80dd14_2243d2af","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":114,"context_line":"                _(\u0027Invalid item type specification\u0027))"},{"line_number":115,"context_line":"        if item.default is not None:"},{"line_number":116,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":117,"context_line":"                _(\u0027List definitions may hot have defaults\u0027))"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def __init__(self, item_type, min_size\u003d0, max_size\u003dNone, unique\u003dFalse,"},{"line_number":120,"context_line":"                 **kwargs):"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_e2937aa0","line":117,"updated":"2015-03-10 12:50:38.000000000","message":"\"may not have\"","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":114,"context_line":"                _(\u0027Invalid item type specification\u0027))"},{"line_number":115,"context_line":"        if item.default is not None:"},{"line_number":116,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":117,"context_line":"                _(\u0027List definitions may hot have defaults\u0027))"},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def __init__(self, item_type, min_size\u003d0, max_size\u003dNone, unique\u003dFalse,"},{"line_number":120,"context_line":"                 **kwargs):"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_98081cdb","line":117,"in_reply_to":"9a80dd14_e2937aa0","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":124,"context_line":"            for it in item_type:"},{"line_number":125,"context_line":"                self._check_item_type(it)"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"            # NOTE: copy the item_type collection"},{"line_number":128,"context_line":"            self.item_type \u003d item_type[:]"},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"            if min_size !\u003d 0:"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_c24116aa","line":127,"updated":"2015-03-10 12:50:38.000000000","message":"NOTE, TODO or just a comment?","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":124,"context_line":"            for it in item_type:"},{"line_number":125,"context_line":"                self._check_item_type(it)"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"            # NOTE: copy the item_type collection"},{"line_number":128,"context_line":"            self.item_type \u003d item_type[:]"},{"line_number":129,"context_line":""},{"line_number":130,"context_line":"            if min_size !\u003d 0:"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_18c98c79","line":127,"in_reply_to":"9a80dd14_c24116aa","updated":"2015-03-11 21:38:17.000000000","message":"Just a comment. Removed the NOTE, thanks","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":159,"context_line":"        if value is not None:"},{"line_number":160,"context_line":"            self._add_validator(\u0027min_size\u0027,"},{"line_number":161,"context_line":"                                lambda v: len(v) \u003e\u003d self._min_size,"},{"line_number":162,"context_line":"                                _(\u0027List size is less then minimum\u0027))"},{"line_number":163,"context_line":"        else:"},{"line_number":164,"context_line":"            self._remove_validator(\u0027min_size\u0027)"},{"line_number":165,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_a25a62ef","line":162,"updated":"2015-03-10 12:50:38.000000000","message":"\"less than\"","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":159,"context_line":"        if value is not None:"},{"line_number":160,"context_line":"            self._add_validator(\u0027min_size\u0027,"},{"line_number":161,"context_line":"                                lambda v: len(v) \u003e\u003d self._min_size,"},{"line_number":162,"context_line":"                                _(\u0027List size is less then minimum\u0027))"},{"line_number":163,"context_line":"        else:"},{"line_number":164,"context_line":"            self._remove_validator(\u0027min_size\u0027)"},{"line_number":165,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_7888c822","line":162,"in_reply_to":"9a80dd14_a25a62ef","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":168,"context_line":"        if value is not None:"},{"line_number":169,"context_line":"            self._add_validator(\u0027max_size\u0027,"},{"line_number":170,"context_line":"                                lambda v: len(v) \u003c\u003d self._max_size,"},{"line_number":171,"context_line":"                                _(\u0027List size is greater then maximum\u0027))"},{"line_number":172,"context_line":"        else:"},{"line_number":173,"context_line":"            self._remove_validator(\u0027max_size\u0027)"},{"line_number":174,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_e26ffa8f","line":171,"updated":"2015-03-10 12:50:38.000000000","message":"\"greater than\"","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":168,"context_line":"        if value is not None:"},{"line_number":169,"context_line":"            self._add_validator(\u0027max_size\u0027,"},{"line_number":170,"context_line":"                                lambda v: len(v) \u003c\u003d self._max_size,"},{"line_number":171,"context_line":"                                _(\u0027List size is greater then maximum\u0027))"},{"line_number":172,"context_line":"        else:"},{"line_number":173,"context_line":"            self._remove_validator(\u0027max_size\u0027)"},{"line_number":174,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_988bbc1d","line":171,"in_reply_to":"9a80dd14_e26ffa8f","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":241,"context_line":"        if isinstance(properties, types.DictionaryType):"},{"line_number":242,"context_line":"            for key, value in six.iteritems(properties):"},{"line_number":243,"context_line":"                self._check_prop(key, value)"},{"line_number":244,"context_line":"            # NOTE: copy the properties dict"},{"line_number":245,"context_line":"            self.properties \u003d properties.copy()"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"            self._add_validator(\u0027keys\u0027,"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_22ecb2ba","line":244,"updated":"2015-03-10 12:50:38.000000000","message":"NOTE, TODO or just a comment?","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":241,"context_line":"        if isinstance(properties, types.DictionaryType):"},{"line_number":242,"context_line":"            for key, value in six.iteritems(properties):"},{"line_number":243,"context_line":"                self._check_prop(key, value)"},{"line_number":244,"context_line":"            # NOTE: copy the properties dict"},{"line_number":245,"context_line":"            self.properties \u003d properties.copy()"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"            self._add_validator(\u0027keys\u0027,"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_3876503f","line":244,"in_reply_to":"9a80dd14_22ecb2ba","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":263,"context_line":"        if value is not None:"},{"line_number":264,"context_line":"            self._add_validator(\u0027min_properties\u0027,"},{"line_number":265,"context_line":"                                lambda v: len(v) \u003e\u003d self._min_properties,"},{"line_number":266,"context_line":"                                _(\u0027Dictionary size is less then \u0027"},{"line_number":267,"context_line":"                                  \u0027minimum\u0027))"},{"line_number":268,"context_line":"        else:"},{"line_number":269,"context_line":"            self._remove_validator(\u0027min_properties\u0027)"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_6c43fc6b","line":266,"updated":"2015-03-10 12:50:38.000000000","message":"\u0027less than\u0027","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":263,"context_line":"        if value is not None:"},{"line_number":264,"context_line":"            self._add_validator(\u0027min_properties\u0027,"},{"line_number":265,"context_line":"                                lambda v: len(v) \u003e\u003d self._min_properties,"},{"line_number":266,"context_line":"                                _(\u0027Dictionary size is less then \u0027"},{"line_number":267,"context_line":"                                  \u0027minimum\u0027))"},{"line_number":268,"context_line":"        else:"},{"line_number":269,"context_line":"            self._remove_validator(\u0027min_properties\u0027)"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_189eec54","line":266,"in_reply_to":"9a80dd14_6c43fc6b","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":274,"context_line":"            self._add_validator(\u0027max_properties\u0027,"},{"line_number":275,"context_line":"                                lambda v: len(v) \u003c\u003d self._max_properties,"},{"line_number":276,"context_line":"                                _(\u0027Dictionary size is \u0027"},{"line_number":277,"context_line":"                                  \u0027greater then maximum\u0027))"},{"line_number":278,"context_line":"        else:"},{"line_number":279,"context_line":"            self._remove_validator(\u0027max_properties\u0027)"},{"line_number":280,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_ec560c29","line":277,"updated":"2015-03-10 12:50:38.000000000","message":"\u0027greater than\u0027","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":274,"context_line":"            self._add_validator(\u0027max_properties\u0027,"},{"line_number":275,"context_line":"                                lambda v: len(v) \u003c\u003d self._max_properties,"},{"line_number":276,"context_line":"                                _(\u0027Dictionary size is \u0027"},{"line_number":277,"context_line":"                                  \u0027greater then maximum\u0027))"},{"line_number":278,"context_line":"        else:"},{"line_number":279,"context_line":"            self._remove_validator(\u0027max_properties\u0027)"},{"line_number":280,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_38ad7089","line":277,"in_reply_to":"9a80dd14_ec560c29","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":322,"context_line":"        self.internal \u003d internal"},{"line_number":323,"context_line":"        self._allowed_values \u003d None"},{"line_number":324,"context_line":""},{"line_number":325,"context_line":"        if validators:"},{"line_number":326,"context_line":"            try:"},{"line_number":327,"context_line":"                for i, (f, m) in enumerate(validators):"},{"line_number":328,"context_line":"                    self._add_validator(\"custom_%i\" % i, f, m)"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_c2d3d601","line":325,"updated":"2015-03-10 12:50:38.000000000","message":"\u0027is not None\u0027?","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":322,"context_line":"        self.internal \u003d internal"},{"line_number":323,"context_line":"        self._allowed_values \u003d None"},{"line_number":324,"context_line":""},{"line_number":325,"context_line":"        if validators:"},{"line_number":326,"context_line":"            try:"},{"line_number":327,"context_line":"                for i, (f, m) in enumerate(validators):"},{"line_number":328,"context_line":"                    self._add_validator(\"custom_%i\" % i, f, m)"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_58bf84aa","line":325,"in_reply_to":"9a80dd14_c2d3d601","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":332,"context_line":"                      \"\u0027(function, message)\u0027\"))"},{"line_number":333,"context_line":""},{"line_number":334,"context_line":"        if allowed_values is not None:"},{"line_number":335,"context_line":"            # NOTE: copy the allowed_values, as this is going to create a"},{"line_number":336,"context_line":"            # closure, and we need to make sure that external modification of"},{"line_number":337,"context_line":"            # this list does not affect the created validator"},{"line_number":338,"context_line":"            self.allowed_values(allowed_values)"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_02da4e16","line":335,"updated":"2015-03-10 12:50:38.000000000","message":"\u0027NOTE(ativelkov):\u0027","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":332,"context_line":"                      \"\u0027(function, message)\u0027\"))"},{"line_number":333,"context_line":""},{"line_number":334,"context_line":"        if allowed_values is not None:"},{"line_number":335,"context_line":"            # NOTE: copy the allowed_values, as this is going to create a"},{"line_number":336,"context_line":"            # closure, and we need to make sure that external modification of"},{"line_number":337,"context_line":"            # this list does not affect the created validator"},{"line_number":338,"context_line":"            self.allowed_values(allowed_values)"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_78dd2814","line":335,"in_reply_to":"9a80dd14_02da4e16","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":404,"context_line":"                if v is not None and self.collection_wrapper_class:"},{"line_number":405,"context_line":"                    if self.prop.readonly:"},{"line_number":406,"context_line":"                        readonly \u003d True"},{"line_number":407,"context_line":"                    elif (not self.prop.mutable"},{"line_number":408,"context_line":"                          and hasattr(instance, \u0027__is_mutable__\u0027)"},{"line_number":409,"context_line":"                          and not hasattr(instance,"},{"line_number":410,"context_line":"                                          \u0027__suspend_mutability_checks__\u0027)):"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_0a450042","line":407,"updated":"2015-03-10 12:50:38.000000000","message":"For consistency, would you mind moving the ands to the end of previous line?","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":404,"context_line":"                if v is not None and self.collection_wrapper_class:"},{"line_number":405,"context_line":"                    if self.prop.readonly:"},{"line_number":406,"context_line":"                        readonly \u003d True"},{"line_number":407,"context_line":"                    elif (not self.prop.mutable"},{"line_number":408,"context_line":"                          and hasattr(instance, \u0027__is_mutable__\u0027)"},{"line_number":409,"context_line":"                          and not hasattr(instance,"},{"line_number":410,"context_line":"                                          \u0027__suspend_mutability_checks__\u0027)):"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_38f2d09a","line":407,"in_reply_to":"9a80dd14_0a450042","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":485,"context_line":""},{"line_number":486,"context_line":"        self.attributes \u003d ArtifactAttributes()"},{"line_number":487,"context_line":""},{"line_number":488,"context_line":"        # Note(ativelkov): these are going to be defined by third-party plugin"},{"line_number":489,"context_line":"        # developers, so we need to do some validations on these values and"},{"line_number":490,"context_line":"        # raise InvalidArtifactTypeDefinition if they are violated"},{"line_number":491,"context_line":"        self._type_name \u003d type_name"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_ccf5c883","line":488,"updated":"2015-03-10 12:50:38.000000000","message":"\u0027NOTE(\u0027","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":485,"context_line":""},{"line_number":486,"context_line":"        self.attributes \u003d ArtifactAttributes()"},{"line_number":487,"context_line":""},{"line_number":488,"context_line":"        # Note(ativelkov): these are going to be defined by third-party plugin"},{"line_number":489,"context_line":"        # developers, so we need to do some validations on these values and"},{"line_number":490,"context_line":"        # raise InvalidArtifactTypeDefinition if they are violated"},{"line_number":491,"context_line":"        self._type_name \u003d type_name"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_f83e7828","line":488,"in_reply_to":"9a80dd14_ccf5c883","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":524,"context_line":""},{"line_number":525,"context_line":"    @property"},{"line_number":526,"context_line":"    def endpoint(self):"},{"line_number":527,"context_line":"        return self._endpoint"},{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    @staticmethod"},{"line_number":530,"context_line":"    def _validate_string(value, name, min_length\u003d0, max_length\u003dNone,"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_0c48c0b1","line":527,"updated":"2015-03-10 12:50:38.000000000","message":"Is there a reason for these @properties rather than naming the variables just without leading _. Not really a pythonic approach.","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":524,"context_line":""},{"line_number":525,"context_line":"    @property"},{"line_number":526,"context_line":"    def endpoint(self):"},{"line_number":527,"context_line":"        return self._endpoint"},{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    @staticmethod"},{"line_number":530,"context_line":"    def _validate_string(value, name, min_length\u003d0, max_length\u003dNone,"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_382010f7","line":527,"in_reply_to":"9a80dd14_0c48c0b1","updated":"2015-03-11 21:38:17.000000000","message":"That\u0027s my Java background sometimes waking up. Thanks, fixed.","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":540,"context_line":"                message\u003d_(\"%(attribute)s have to be string\"), attribute\u003dname)"},{"line_number":541,"context_line":"        if max_length and len(value) \u003e max_length:"},{"line_number":542,"context_line":"            raise exc.InvalidArtifactTypeDefinition("},{"line_number":543,"context_line":"                message\u003d_(\"%(attribute)s may not be longer then %(length)i\"),"},{"line_number":544,"context_line":"                attribute\u003dname, length\u003dmax_length)"},{"line_number":545,"context_line":"        if min_length and len(value) \u003c min_length:"},{"line_number":546,"context_line":"            raise exc.InvalidArtifactTypeDefinition("}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_8cb83076","line":543,"updated":"2015-03-10 12:50:38.000000000","message":"\u0027longer than\u0027","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":540,"context_line":"                message\u003d_(\"%(attribute)s have to be string\"), attribute\u003dname)"},{"line_number":541,"context_line":"        if max_length and len(value) \u003e max_length:"},{"line_number":542,"context_line":"            raise exc.InvalidArtifactTypeDefinition("},{"line_number":543,"context_line":"                message\u003d_(\"%(attribute)s may not be longer then %(length)i\"),"},{"line_number":544,"context_line":"                attribute\u003dname, length\u003dmax_length)"},{"line_number":545,"context_line":"        if min_length and len(value) \u003c min_length:"},{"line_number":546,"context_line":"            raise exc.InvalidArtifactTypeDefinition("}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_b8d160cf","line":543,"in_reply_to":"9a80dd14_8cb83076","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":544,"context_line":"                attribute\u003dname, length\u003dmax_length)"},{"line_number":545,"context_line":"        if min_length and len(value) \u003c min_length:"},{"line_number":546,"context_line":"            raise exc.InvalidArtifactTypeDefinition("},{"line_number":547,"context_line":"                message\u003d_(\"%(attribute)s may not be shorter then %(length)i\"),"},{"line_number":548,"context_line":"                attribute\u003dname, length\u003dmin_length)"},{"line_number":549,"context_line":"        if pattern and not re.match(pattern, value):"},{"line_number":550,"context_line":"            raise exc.InvalidArtifactTypeDefinition("}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_2c66642a","line":547,"updated":"2015-03-10 12:50:38.000000000","message":"\u0027shorter than\u0027","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":544,"context_line":"                attribute\u003dname, length\u003dmax_length)"},{"line_number":545,"context_line":"        if min_length and len(value) \u003c min_length:"},{"line_number":546,"context_line":"            raise exc.InvalidArtifactTypeDefinition("},{"line_number":547,"context_line":"                message\u003d_(\"%(attribute)s may not be shorter then %(length)i\"),"},{"line_number":548,"context_line":"                attribute\u003dname, length\u003dmin_length)"},{"line_number":549,"context_line":"        if pattern and not re.match(pattern, value):"},{"line_number":550,"context_line":"            raise exc.InvalidArtifactTypeDefinition("}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_d8d454bf","line":547,"in_reply_to":"9a80dd14_2c66642a","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"d93abcc4f7a7b6ad844cb001806950326a173a6e","unresolved":false,"context_lines":[{"line_number":493,"context_line":"        \"\"\"Returns the default dependency relation for an artifact type\"\"\""},{"line_number":494,"context_line":"        if len(self.dependencies) \u003d\u003d 1:"},{"line_number":495,"context_line":"            return self.dependencies.values()[0]"},{"line_number":496,"context_line":"        else:"},{"line_number":497,"context_line":"            return None"},{"line_number":498,"context_line":""},{"line_number":499,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":68,"id":"1a6ced46_4fbcb706","line":496,"updated":"2015-03-26 11:53:02.000000000","message":"no need of else block and return None, IMO it will return None by default.","commit_id":"2fce16c1c5ffdfb4df18e84c51c4ab9e922c1117"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"39cac25c3b3e0ef90425fe46f42f9cbf85c9beee","unresolved":false,"context_lines":[{"line_number":493,"context_line":"        \"\"\"Returns the default dependency relation for an artifact type\"\"\""},{"line_number":494,"context_line":"        if len(self.dependencies) \u003d\u003d 1:"},{"line_number":495,"context_line":"            return self.dependencies.values()[0]"},{"line_number":496,"context_line":"        else:"},{"line_number":497,"context_line":"            return None"},{"line_number":498,"context_line":""},{"line_number":499,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":68,"id":"fa963961_ee6c640a","line":496,"in_reply_to":"1a6ced46_4fbcb706","updated":"2015-03-26 19:06:47.000000000","message":"Done","commit_id":"2fce16c1c5ffdfb4df18e84c51c4ab9e922c1117"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"d93abcc4f7a7b6ad844cb001806950326a173a6e","unresolved":false,"context_lines":[{"line_number":501,"context_line":"        \"\"\"Returns the default blob object for an artifact type\"\"\""},{"line_number":502,"context_line":"        if len(self.blobs) \u003d\u003d 1:"},{"line_number":503,"context_line":"            return self.blobs.values()[0]"},{"line_number":504,"context_line":"        else:"},{"line_number":505,"context_line":"            return None"},{"line_number":506,"context_line":""},{"line_number":507,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":68,"id":"1a6ced46_cf3fc785","line":504,"updated":"2015-03-26 11:53:02.000000000","message":"ditto","commit_id":"2fce16c1c5ffdfb4df18e84c51c4ab9e922c1117"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"39cac25c3b3e0ef90425fe46f42f9cbf85c9beee","unresolved":false,"context_lines":[{"line_number":501,"context_line":"        \"\"\"Returns the default blob object for an artifact type\"\"\""},{"line_number":502,"context_line":"        if len(self.blobs) \u003d\u003d 1:"},{"line_number":503,"context_line":"            return self.blobs.values()[0]"},{"line_number":504,"context_line":"        else:"},{"line_number":505,"context_line":"            return None"},{"line_number":506,"context_line":""},{"line_number":507,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":68,"id":"fa963961_ce71a0e2","line":504,"in_reply_to":"1a6ced46_cf3fc785","updated":"2015-03-26 19:06:47.000000000","message":"Done","commit_id":"2fce16c1c5ffdfb4df18e84c51c4ab9e922c1117"}],"glance/common/artifacts/definitions.py":[{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"bccb3f83e6dd4a1dbac4d78b33e72de11a771b07","unresolved":false,"context_lines":[{"line_number":75,"context_line":"class String(Text):"},{"line_number":76,"context_line":"    def __init__(self, max_length\u003d255, min_length\u003d0, pattern\u003dNone, **kwargs):"},{"line_number":77,"context_line":"        super(String, self).__init__(**kwargs)"},{"line_number":78,"context_line":"        if max_length \u003e 255:"},{"line_number":79,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":80,"context_line":"                _(\u0027Max string length may not exceed 255 characters\u0027))"},{"line_number":81,"context_line":"        if min_length \u003c 0:"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_67d84cf0","line":78,"updated":"2014-10-31 11:45:56.000000000","message":"I suggest making attribute\u0027s additional constraints (like max_length or pattern, for example) accessible via class object, as this data is vital for things like Json Schema representation.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"6111b01ab05de3149dceb35617a4460513f53cb3","unresolved":false,"context_lines":[{"line_number":75,"context_line":"class String(Text):"},{"line_number":76,"context_line":"    def __init__(self, max_length\u003d255, min_length\u003d0, pattern\u003dNone, **kwargs):"},{"line_number":77,"context_line":"        super(String, self).__init__(**kwargs)"},{"line_number":78,"context_line":"        if max_length \u003e 255:"},{"line_number":79,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":80,"context_line":"                _(\u0027Max string length may not exceed 255 characters\u0027))"},{"line_number":81,"context_line":"        if min_length \u003c 0:"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_7c1aa26f","line":78,"in_reply_to":"7a8c0949_67d84cf0","updated":"2014-10-31 13:30:13.000000000","message":"Thanks, will do it.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"ccc009df3ea7afcbdd47567874677f8b2646b4ea","unresolved":false,"context_lines":[{"line_number":137,"context_line":"        self._post_init()"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"class Numeric(PropertyDefinition):"},{"line_number":141,"context_line":"    ALLOWED_TYPES \u003d numbers.Number"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def __init__(self, min_value\u003dNone, max_value\u003dNone, **kwargs):"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_f9bb0470","line":140,"updated":"2014-10-31 12:48:33.000000000","message":"class Numeric seems to share a lot of code with Integer class. What\u0027s the difference between these 2 types (I can think only of traditional integer vs long long int differences)?","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"6111b01ab05de3149dceb35617a4460513f53cb3","unresolved":false,"context_lines":[{"line_number":137,"context_line":"        self._post_init()"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"class Numeric(PropertyDefinition):"},{"line_number":141,"context_line":"    ALLOWED_TYPES \u003d numbers.Number"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def __init__(self, min_value\u003dNone, max_value\u003dNone, **kwargs):"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_8f746e9d","line":140,"in_reply_to":"7a8c0949_f9bb0470","updated":"2014-10-31 13:30:13.000000000","message":"This is designed to be similar to json-schema\u0027s \"Number\" type, which may accept both integer and floating-point numbers. \nProbably numeric is not the best name and it rather should be named \"Number\" instead","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":9712,"name":"Dougal Matthews","email":"dougal.matthews@canonical.com","username":"dougal"},"change_message_id":"bc4de9e502e13aad58dacacc30f2b63569a2c66d","unresolved":false,"context_lines":[{"line_number":235,"context_line":""},{"line_number":236,"context_line":"    def __init__(self, type_name\u003dNone, type_version\u003dNone, **kwargs):"},{"line_number":237,"context_line":"        super(ArtifactReference, self).__init__(**kwargs)"},{"line_number":238,"context_line":"        if type_name is not None:"},{"line_number":239,"context_line":"            if isinstance(type_name, types.ListType):"},{"line_number":240,"context_line":"                type_names \u003d list(type_name)"},{"line_number":241,"context_line":"                if type_version is not None:"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a8c0949_efe7803e","line":238,"updated":"2014-11-05 14:58:33.000000000","message":"This check is redundant as if it is None it will never be a types.ListType.","commit_id":"d4dce8550564e3ac13def727dcce0e87dfddfb0d"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"feebb34f32ebfe0ad941d717271a037b8fd8a4b7","unresolved":false,"context_lines":[{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class PropertyDefinition(declarative.AttributeDefinition):"},{"line_number":29,"context_line":"    def __init__(self,"},{"line_number":30,"context_line":"                 internal\u003dFalse,"},{"line_number":31,"context_line":"                 allowed_values\u003dNone,"},{"line_number":32,"context_line":"                 validators\u003dNone,"},{"line_number":33,"context_line":"                 **kwargs):"}],"source_content_type":"text/x-python","patch_set":11,"id":"5a890539_27a01390","line":30,"updated":"2014-11-10 16:20:21.000000000","message":"Can\u0027t figure out: what semantics does \u0027internal\u0027 have?","commit_id":"07fb8626cbe596c67e34f0160c8a067713ae4c2f"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"0fc0d351ff658485dfce7e9cdd41eb784d7bddb9","unresolved":false,"context_lines":[{"line_number":122,"context_line":""},{"line_number":123,"context_line":""},{"line_number":124,"context_line":"class DateTime(PropertyDefinition):"},{"line_number":125,"context_line":"    ALLOWED_TYPES \u003d datetime.datetime"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    def __init__(self, min_value\u003dNone, max_value\u003dNone, **kwargs):"},{"line_number":128,"context_line":"        super(DateTime, self).__init__(**kwargs)"}],"source_content_type":"text/x-python","patch_set":12,"id":"5a890539_3dc52d8e","line":125,"updated":"2014-11-13 12:41:42.000000000","message":"why are some ALLOWED_TYPES defined as a tuple (ex. Integer -\u003e (int, long, )), while others are a single type (like Datetime -\u003e datetime here)?","commit_id":"504fbc971bd4deac356bc7db402ba0ea4912e747"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"0fc0d351ff658485dfce7e9cdd41eb784d7bddb9","unresolved":false,"context_lines":[{"line_number":138,"context_line":""},{"line_number":139,"context_line":""},{"line_number":140,"context_line":"class Numeric(PropertyDefinition):"},{"line_number":141,"context_line":"    ALLOWED_TYPES \u003d numbers.Number"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def __init__(self, min_value\u003dNone, max_value\u003dNone, **kwargs):"},{"line_number":144,"context_line":"        super(Numeric, self).__init__(**kwargs)"}],"source_content_type":"text/x-python","patch_set":12,"id":"5a890539_dd3b499a","line":141,"updated":"2014-11-13 12:41:42.000000000","message":"same thing here","commit_id":"504fbc971bd4deac356bc7db402ba0ea4912e747"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"0fc0d351ff658485dfce7e9cdd41eb784d7bddb9","unresolved":false,"context_lines":[{"line_number":154,"context_line":""},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"class Boolean(PropertyDefinition):"},{"line_number":157,"context_line":"    ALLOWED_TYPES \u003d types.BooleanType"},{"line_number":158,"context_line":""},{"line_number":159,"context_line":""},{"line_number":160,"context_line":"class Array(declarative.ListAttributeDefinition, PropertyDefinition, list):"}],"source_content_type":"text/x-python","patch_set":12,"id":"5a890539_1d46b123","line":157,"updated":"2014-11-13 12:41:42.000000000","message":"and here","commit_id":"504fbc971bd4deac356bc7db402ba0ea4912e747"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"58444c53497d73c2e117e049540624b37e3bc5fb","unresolved":false,"context_lines":[{"line_number":217,"context_line":"    ALLOWED_ITEM_TYPES \u003d (declarative.PropertyDefinition,)"},{"line_number":218,"context_line":""},{"line_number":219,"context_line":"    def __init__(self, item_type\u003dString(), min_size\u003d0, max_size\u003dNone,"},{"line_number":220,"context_line":"                 unique\u003dFalse, extra_items\u003dTrue, **kwargs):"},{"line_number":221,"context_line":"        declarative.ListAttributeDefinition.__init__(self,"},{"line_number":222,"context_line":"                                                     item_type\u003ditem_type,"},{"line_number":223,"context_line":"                                                     min_size\u003dmin_size,"}],"source_content_type":"text/x-python","patch_set":20,"id":"5a890539_ba0c1aee","line":220,"updated":"2014-12-05 16:53:07.000000000","message":"I could not find any other usages of extra_items. Is it obsolete?","commit_id":"3aedb19f1b88200620f3572bb75087804e6e5608"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2014 Mirantis, Inc."},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_4f054a0f","line":1,"updated":"2015-03-10 12:50:38.000000000","message":"2015","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2014 Mirantis, Inc."},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_38fc903e","line":1,"in_reply_to":"9a80dd14_4f054a0f","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"}],"glance/common/artifacts/serialization.py":[{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"90688aeca62af87dfd14fdb80b5d96e3111c8a62","unresolved":false,"context_lines":[{"line_number":42,"context_line":"def serialize_for_db(artifact):"},{"line_number":43,"context_line":"    result \u003d {}"},{"line_number":44,"context_line":"    custom_properties \u003d {}"},{"line_number":45,"context_line":"    for prop in artifact.metadata.attributes.properties.values():"},{"line_number":46,"context_line":"        if prop.name in COMMON_ARTIFACT_PROPERTIES:"},{"line_number":47,"context_line":"            result[prop.name] \u003d prop.get_value(artifact)"},{"line_number":48,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":20,"id":"3a961159_d9761d3e","line":45,"updated":"2014-12-09 18:36:36.000000000","message":"Not all properties listed in COMMON_ARTIFACT_PROPERTIES can be retrieved from artifact.metadata.attributes.properties.\n\nFor an artifact with 2 user-specific properties prop1 and prop2 you\u0027ll have:\n\n[\u0027version\u0027, \u0027description\u0027, \u0027tags\u0027, \u0027created_at\u0027, \u0027type_name\u0027, \u0027updated_at\u0027, \u0027visibility\u0027, \u0027type_version\u0027, \u0027published_at\u0027, \u0027state\u0027, \u0027prop1\u0027, \u0027prop2\u0027, \u0027deleted_at\u0027, \u0027name\u0027]\n\nat least \u0027owner\u0027 should be added, as it is needed later on artifact creation  in glance/db/sqlalchemy/artifacts.py:_create_or_update","commit_id":"3aedb19f1b88200620f3572bb75087804e6e5608"},{"author":{"_account_id":13717,"name":"Inessa Vasilevskaya","email":"ivasilevskaya@mirantis.com","username":"ivasilevskaya"},"change_message_id":"06f61568ced0f899e3bc20c777d4d1e65d63b1c4","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            if isinstance(prop, declarative.ListAttributeDefinition):"},{"line_number":50,"context_line":"                serialized_value \u003d []"},{"line_number":51,"context_line":"                i \u003d 0"},{"line_number":52,"context_line":"                for val in prop.get_value(artifact):"},{"line_number":53,"context_line":"                    db_type \u003d prop.get_item_definition_at_index(i).DB_TYPE"},{"line_number":54,"context_line":"                    if db_type is None:"},{"line_number":55,"context_line":"                        continue"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a930d6b_314adbc5","line":52,"updated":"2015-01-22 17:33:23.000000000","message":"it should be something like:\n\n\"for val in prop.get_value(artifact) or []\"\n\nOtherwise prop.get_value(artifact) returns None and will receive TypeError: \u0027NoneType\u0027 object is not iterable","commit_id":"f64848925d3953847f68067a03f9be7b9c3db764"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"fead273b272fb2ac78220eef4693b253f0abab9c","unresolved":false,"context_lines":[{"line_number":49,"context_line":"            if isinstance(prop, declarative.ListAttributeDefinition):"},{"line_number":50,"context_line":"                serialized_value \u003d []"},{"line_number":51,"context_line":"                i \u003d 0"},{"line_number":52,"context_line":"                for val in prop.get_value(artifact):"},{"line_number":53,"context_line":"                    db_type \u003d prop.get_item_definition_at_index(i).DB_TYPE"},{"line_number":54,"context_line":"                    if db_type is None:"},{"line_number":55,"context_line":"                        continue"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a930d6b_7e5b4b2e","line":52,"in_reply_to":"1a930d6b_314adbc5","updated":"2015-01-22 18:47:41.000000000","message":"Done","commit_id":"f64848925d3953847f68067a03f9be7b9c3db764"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2014 Mirantis, Inc."},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_6f812efa","line":1,"updated":"2015-03-10 12:50:38.000000000","message":"2015","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright (c) 2014 Mirantis, Inc."},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_789528e3","line":1,"in_reply_to":"9a80dd14_6f812efa","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"def _serialize_list_prop(prop, values):"},{"line_number":42,"context_line":"    \"\"\""},{"line_number":43,"context_line":"    A helper func called to correctly serialize an Array property."},{"line_number":44,"context_line":"    Returns a dict {\u0027type\u0027: some_supported_db_type, \u0027value\u0027: serialized_data}"},{"line_number":45,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_6f984e6a","line":42,"updated":"2015-03-10 12:50:38.000000000","message":"DocString should not start with empty line: http://docs.openstack.org/developer/hacking/#docstrings","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":39,"context_line":""},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"def _serialize_list_prop(prop, values):"},{"line_number":42,"context_line":"    \"\"\""},{"line_number":43,"context_line":"    A helper func called to correctly serialize an Array property."},{"line_number":44,"context_line":"    Returns a dict {\u0027type\u0027: some_supported_db_type, \u0027value\u0027: serialized_data}"},{"line_number":45,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_588ea4d1","line":42,"in_reply_to":"9a80dd14_6f984e6a","updated":"2015-03-11 21:38:17.000000000","message":"Done","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":5202,"name":"Erno Kuvaja","email":"jokke@usr.fi","username":"jokke"},"change_message_id":"dc5fe72b2a5c4141f28ba94b07bbd7c8cc64fc57","unresolved":false,"context_lines":[{"line_number":144,"context_line":"            _save_prop(prop.name, \u0027array\u0027, serialized_value)"},{"line_number":145,"context_line":"        elif isinstance(prop, declarative.DictAttributeDefinition):"},{"line_number":146,"context_line":"            fields_to_set \u003d prop.get_value(artifact) or {}"},{"line_number":147,"context_line":"            # (ivasilevskaya) if some keys are not present"},{"line_number":148,"context_line":"            # (like in prop \u003d\u003d {}), then have to set their values to None."},{"line_number":149,"context_line":"            # XXX FIXME prop.properties may be a dict ({\u0027foo\u0027: \u0027\u0027, \u0027bar\u0027: \u0027\u0027})"},{"line_number":150,"context_line":"            # or String\\Integer\\whatsoever, limiting the possible dict values."}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_4f18ead2","line":147,"updated":"2015-03-10 12:50:38.000000000","message":"\u0027NOTE(\u0027 ?","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"4398ff678b6d1123f32ca11f5e074013c9046d83","unresolved":false,"context_lines":[{"line_number":144,"context_line":"            _save_prop(prop.name, \u0027array\u0027, serialized_value)"},{"line_number":145,"context_line":"        elif isinstance(prop, declarative.DictAttributeDefinition):"},{"line_number":146,"context_line":"            fields_to_set \u003d prop.get_value(artifact) or {}"},{"line_number":147,"context_line":"            # (ivasilevskaya) if some keys are not present"},{"line_number":148,"context_line":"            # (like in prop \u003d\u003d {}), then have to set their values to None."},{"line_number":149,"context_line":"            # XXX FIXME prop.properties may be a dict ({\u0027foo\u0027: \u0027\u0027, \u0027bar\u0027: \u0027\u0027})"},{"line_number":150,"context_line":"            # or String\\Integer\\whatsoever, limiting the possible dict values."}],"source_content_type":"text/x-python","patch_set":60,"id":"9a80dd14_d8b9b47a","line":147,"in_reply_to":"9a80dd14_4f18ead2","updated":"2015-03-11 21:38:17.000000000","message":"no, just a comment. Fixed.","commit_id":"7da8cb9397c4602ecf118f470fea850dd953fe0d"}],"glance/db/sqlalchemy/artifacts/definitions.py":[{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"09db5359ed2f9ade05b64c59a362b656d16fa682","unresolved":false,"context_lines":[{"line_number":19,"context_line":"import types"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"import glance.common.exception as exc"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class PropertyDefinition(object):"},{"line_number":25,"context_line":"    def __init__(self, mutable\u003dTrue, required\u003dFalse, internal\u003dFalse,"}],"source_content_type":"text/x-python","patch_set":2,"id":"fa98f980_c249b933","line":22,"updated":"2014-09-19 00:33:00.000000000","message":"I don\u0027t understand why this is in the db/sqlachemy package.  This seems more like it should be in some new location.","commit_id":"e580f6fc3b912eeb4e68a2e8b1fb08bfd9f3af27"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"a09bc83961799493f24d6594593f327247df195b","unresolved":false,"context_lines":[{"line_number":19,"context_line":"import types"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"import glance.common.exception as exc"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class PropertyDefinition(object):"},{"line_number":25,"context_line":"    def __init__(self, mutable\u003dTrue, required\u003dFalse, internal\u003dFalse,"}],"source_content_type":"text/x-python","patch_set":2,"id":"fa98f980_23a8b9da","line":22,"in_reply_to":"fa98f980_c249b933","updated":"2014-10-09 14:45:58.000000000","message":"You are right. I just could not pick an appropriate place. \n\nMove this to common/artifacts","commit_id":"e580f6fc3b912eeb4e68a2e8b1fb08bfd9f3af27"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"09db5359ed2f9ade05b64c59a362b656d16fa682","unresolved":false,"context_lines":[{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class PropertyDefinition(object):"},{"line_number":25,"context_line":"    def __init__(self, mutable\u003dTrue, required\u003dFalse, internal\u003dFalse,"},{"line_number":26,"context_line":"                 default\u003dNone):"},{"line_number":27,"context_line":"        self.name \u003d None"},{"line_number":28,"context_line":"        self.mutable \u003d mutable"},{"line_number":29,"context_line":"        self.required \u003d required"}],"source_content_type":"text/x-python","patch_set":2,"id":"fa98f980_cd748f38","line":26,"updated":"2014-09-19 00:33:00.000000000","message":"You could allow a list of custom validators to come through as well in the constructor.\n\nAlso, what is the description of this property?  what is the display name?  Think of how this would be used in the UI.","commit_id":"e580f6fc3b912eeb4e68a2e8b1fb08bfd9f3af27"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"a09bc83961799493f24d6594593f327247df195b","unresolved":false,"context_lines":[{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class PropertyDefinition(object):"},{"line_number":25,"context_line":"    def __init__(self, mutable\u003dTrue, required\u003dFalse, internal\u003dFalse,"},{"line_number":26,"context_line":"                 default\u003dNone):"},{"line_number":27,"context_line":"        self.name \u003d None"},{"line_number":28,"context_line":"        self.mutable \u003d mutable"},{"line_number":29,"context_line":"        self.required \u003d required"}],"source_content_type":"text/x-python","patch_set":2,"id":"fa98f980_a3b3c94b","line":26,"in_reply_to":"fa98f980_cd748f38","updated":"2014-10-09 14:45:58.000000000","message":"Thanks!\nDone.","commit_id":"e580f6fc3b912eeb4e68a2e8b1fb08bfd9f3af27"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"09db5359ed2f9ade05b64c59a362b656d16fa682","unresolved":false,"context_lines":[{"line_number":51,"context_line":"            if not validator(value):"},{"line_number":52,"context_line":"                raise exc.InvalidArtifactPropertyValue(name\u003dself.name,"},{"line_number":53,"context_line":"                                                       val\u003dvalue,"},{"line_number":54,"context_line":"                                                       msg\u003dmessage)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"class String(PropertyDefinition):"}],"source_content_type":"text/x-python","patch_set":2,"id":"fa98f980_2d07dbca","line":54,"updated":"2014-09-19 00:33:00.000000000","message":"This could check all the validators and report back all the reasons it is invalid rather than forcing one by one correction.  However, usually just failing on first is how systems work.","commit_id":"e580f6fc3b912eeb4e68a2e8b1fb08bfd9f3af27"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"a09bc83961799493f24d6594593f327247df195b","unresolved":false,"context_lines":[{"line_number":51,"context_line":"            if not validator(value):"},{"line_number":52,"context_line":"                raise exc.InvalidArtifactPropertyValue(name\u003dself.name,"},{"line_number":53,"context_line":"                                                       val\u003dvalue,"},{"line_number":54,"context_line":"                                                       msg\u003dmessage)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"class String(PropertyDefinition):"}],"source_content_type":"text/x-python","patch_set":2,"id":"baa201ad_43f848c3","line":54,"in_reply_to":"fa98f980_2d07dbca","updated":"2014-10-09 14:45:58.000000000","message":"Done","commit_id":"e580f6fc3b912eeb4e68a2e8b1fb08bfd9f3af27"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"09db5359ed2f9ade05b64c59a362b656d16fa682","unresolved":false,"context_lines":[{"line_number":122,"context_line":"class Set(PropertyDefinition):"},{"line_number":123,"context_line":"    def __init__(self, item_type\u003dString, min_size\u003d0, max_size\u003dNone,"},{"line_number":124,"context_line":"                 allowed_values\u003dNone, **kwargs):"},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"        if not item_type in [String, Text, Numeric, Integer, Boolean]:"},{"line_number":127,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":128,"context_line":"                _(\u0027Invalid item type specification\u0027))"}],"source_content_type":"text/x-python","patch_set":2,"id":"fa98f980_5fc92624","line":125,"updated":"2014-09-19 00:33:00.000000000","message":"Set feels like the array type of json schema, but missing a few things like \n\nadditionalItems (values not in the allowed_values can be set)\nuniqueItems \u003d (value may only exist once in the set vs values can repeat - perhaps implied by the \"set\" word).\n\nI also assume that in json, the value of this type of property would be in a list even if there were a single value:\n\nfoo \u003d [\u0027bar\u0027]\nvs\nfoo \u003d \u0027bar\u0027\n\nWhich is why in json schema, any given type supports an \"enum\" of allowed values.  Meaning that value is of type string.\n\nI\u0027d rename this type of property definition to Array to make compatible with the metadata definitions which are in json schema format and already has type \"array\".","commit_id":"e580f6fc3b912eeb4e68a2e8b1fb08bfd9f3af27"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"a09bc83961799493f24d6594593f327247df195b","unresolved":false,"context_lines":[{"line_number":122,"context_line":"class Set(PropertyDefinition):"},{"line_number":123,"context_line":"    def __init__(self, item_type\u003dString, min_size\u003d0, max_size\u003dNone,"},{"line_number":124,"context_line":"                 allowed_values\u003dNone, **kwargs):"},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"        if not item_type in [String, Text, Numeric, Integer, Boolean]:"},{"line_number":127,"context_line":"            raise exc.InvalidArtifactTypePropertyDefinition("},{"line_number":128,"context_line":"                _(\u0027Invalid item type specification\u0027))"}],"source_content_type":"text/x-python","patch_set":2,"id":"baa201ad_062ace2b","line":125,"in_reply_to":"fa98f980_5fc92624","updated":"2014-10-09 14:45:58.000000000","message":"Thanks. Done","commit_id":"e580f6fc3b912eeb4e68a2e8b1fb08bfd9f3af27"}]}
