)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ff7a4749266563f3c7180f7ca5abe2e4ad3b9498","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This introduce a concept of validation, which allows to check the values"},{"line_number":10,"context_line":"of objects\u0027 fields when they are assigned."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"A new FiledType subclass called ValidatableType is introduced. It adds"},{"line_number":13,"context_line":"a list of validators (functions of appropariate signature) and a"},{"line_number":14,"context_line":"\u0027validate\u0027 method which iterates over the list of validators and checks"},{"line_number":15,"context_line":"if the given value satifies the conditions defined by those validators."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ba3cc151_5d7c85eb","line":12,"range":{"start_line":12,"start_character":6,"end_line":12,"end_character":15},"updated":"2015-07-02 18:34:40.000000000","message":"FieldType","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"45dfc297c19801759818ec5f6805600d8382714c","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This introduce a concept of validation, which allows to check the values"},{"line_number":10,"context_line":"of objects\u0027 fields when they are assigned."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"A new FiledType subclass called ValidatableType is introduced. It adds"},{"line_number":13,"context_line":"a list of validators (functions of appropariate signature) and a"},{"line_number":14,"context_line":"\u0027validate\u0027 method which iterates over the list of validators and checks"},{"line_number":15,"context_line":"if the given value satifies the conditions defined by those validators."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ba3cc151_700f0a37","line":12,"in_reply_to":"ba3cc151_5d7c85eb","updated":"2015-07-03 12:41:31.000000000","message":"Done","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ff7a4749266563f3c7180f7ca5abe2e4ad3b9498","unresolved":false,"context_lines":[{"line_number":10,"context_line":"of objects\u0027 fields when they are assigned."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"A new FiledType subclass called ValidatableType is introduced. It adds"},{"line_number":13,"context_line":"a list of validators (functions of appropariate signature) and a"},{"line_number":14,"context_line":"\u0027validate\u0027 method which iterates over the list of validators and checks"},{"line_number":15,"context_line":"if the given value satifies the conditions defined by those validators."},{"line_number":16,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ba3cc151_9d768d04","line":13,"range":{"start_line":13,"start_character":35,"end_line":13,"end_character":47},"updated":"2015-07-02 18:34:40.000000000","message":"appropriate","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"45dfc297c19801759818ec5f6805600d8382714c","unresolved":false,"context_lines":[{"line_number":10,"context_line":"of objects\u0027 fields when they are assigned."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"A new FiledType subclass called ValidatableType is introduced. It adds"},{"line_number":13,"context_line":"a list of validators (functions of appropariate signature) and a"},{"line_number":14,"context_line":"\u0027validate\u0027 method which iterates over the list of validators and checks"},{"line_number":15,"context_line":"if the given value satifies the conditions defined by those validators."},{"line_number":16,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ba3cc151_900ace24","line":13,"in_reply_to":"ba3cc151_9d768d04","updated":"2015-07-03 12:41:31.000000000","message":"Done","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ff7a4749266563f3c7180f7ca5abe2e4ad3b9498","unresolved":false,"context_lines":[{"line_number":14,"context_line":"\u0027validate\u0027 method which iterates over the list of validators and checks"},{"line_number":15,"context_line":"if the given value satifies the conditions defined by those validators."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"A validator is a function which aacepts object, attribute name and a"},{"line_number":18,"context_line":"value as paramters. It should either return a boolen (\u0027True\u0027 stands for"},{"line_number":19,"context_line":"a valid value, \u0027False - for invalid), or a tuple of a boolean and a"},{"line_number":20,"context_line":"string, where string should contain a message to be included into"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ba3cc151_3d5c217c","line":17,"range":{"start_line":17,"start_character":32,"end_line":17,"end_character":39},"updated":"2015-07-02 18:34:40.000000000","message":"accepts an","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"45dfc297c19801759818ec5f6805600d8382714c","unresolved":false,"context_lines":[{"line_number":14,"context_line":"\u0027validate\u0027 method which iterates over the list of validators and checks"},{"line_number":15,"context_line":"if the given value satifies the conditions defined by those validators."},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"A validator is a function which aacepts object, attribute name and a"},{"line_number":18,"context_line":"value as paramters. It should either return a boolen (\u0027True\u0027 stands for"},{"line_number":19,"context_line":"a valid value, \u0027False - for invalid), or a tuple of a boolean and a"},{"line_number":20,"context_line":"string, where string should contain a message to be included into"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ba3cc151_2b3357f7","line":17,"in_reply_to":"ba3cc151_3d5c217c","updated":"2015-07-03 12:41:31.000000000","message":"Done","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ff7a4749266563f3c7180f7ca5abe2e4ad3b9498","unresolved":false,"context_lines":[{"line_number":61,"context_line":"\u0027ValidatableAutoTypedField\u0027 class is added. It it similar to old"},{"line_number":62,"context_line":"\u0027AutoTypedField\u0027 but defines its field type not an an instance, but as a"},{"line_number":63,"context_line":"class, which gets instantiated in field\u0027s __init__, so each field type"},{"line_number":64,"context_line":"may be parametrized with appropriate constraints."},{"line_number":65,"context_line":"Appropriate field types (StringField, IntegerField, FloatField) are"},{"line_number":66,"context_line":"inherited from this new type, while the old AutoTypedField is left"},{"line_number":67,"context_line":"intact for backwards compatibility."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ba3cc151_9dfbed46","line":64,"range":{"start_line":64,"start_character":7,"end_line":64,"end_character":19},"updated":"2015-07-02 18:34:40.000000000","message":"parameterized","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"45dfc297c19801759818ec5f6805600d8382714c","unresolved":false,"context_lines":[{"line_number":61,"context_line":"\u0027ValidatableAutoTypedField\u0027 class is added. It it similar to old"},{"line_number":62,"context_line":"\u0027AutoTypedField\u0027 but defines its field type not an an instance, but as a"},{"line_number":63,"context_line":"class, which gets instantiated in field\u0027s __init__, so each field type"},{"line_number":64,"context_line":"may be parametrized with appropriate constraints."},{"line_number":65,"context_line":"Appropriate field types (StringField, IntegerField, FloatField) are"},{"line_number":66,"context_line":"inherited from this new type, while the old AutoTypedField is left"},{"line_number":67,"context_line":"intact for backwards compatibility."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ba3cc151_ab5687cb","line":64,"in_reply_to":"ba3cc151_9dfbed46","updated":"2015-07-03 12:41:31.000000000","message":"Done","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"}],"oslo_versionedobjects/fields.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ff7a4749266563f3c7180f7ca5abe2e4ad3b9498","unresolved":false,"context_lines":[{"line_number":143,"context_line":"                if error is not None:"},{"line_number":144,"context_line":"                    errors.append(error)"},{"line_number":145,"context_line":"                else:"},{"line_number":146,"context_line":"                    generic_validation_error \u003d True"},{"line_number":147,"context_line":"        if generic_validation_error:"},{"line_number":148,"context_line":"            errors.append(_(\"validation error\"))"},{"line_number":149,"context_line":"        if errors:"}],"source_content_type":"text/x-python","patch_set":3,"id":"ba3cc151_5d4d6598","line":146,"range":{"start_line":146,"start_character":20,"end_line":146,"end_character":51},"updated":"2015-07-02 18:34:40.000000000","message":"Why not just always require the validators to return the tuple? I think that would be better UX for the developers, and simplify this code a bit.","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"45dfc297c19801759818ec5f6805600d8382714c","unresolved":false,"context_lines":[{"line_number":143,"context_line":"                if error is not None:"},{"line_number":144,"context_line":"                    errors.append(error)"},{"line_number":145,"context_line":"                else:"},{"line_number":146,"context_line":"                    generic_validation_error \u003d True"},{"line_number":147,"context_line":"        if generic_validation_error:"},{"line_number":148,"context_line":"            errors.append(_(\"validation error\"))"},{"line_number":149,"context_line":"        if errors:"}],"source_content_type":"text/x-python","patch_set":3,"id":"ba3cc151_504d2dc2","line":146,"in_reply_to":"ba3cc151_5d4d6598","updated":"2015-07-03 12:41:31.000000000","message":"Agree. Done.","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"ff7a4749266563f3c7180f7ca5abe2e4ad3b9498","unresolved":false,"context_lines":[{"line_number":213,"context_line":"            return self._null(obj, attr)"},{"line_number":214,"context_line":"        else:"},{"line_number":215,"context_line":"            value \u003d self._type.coerce(obj, attr, value)"},{"line_number":216,"context_line":"            if isinstance(self._type, ValidatableType):"},{"line_number":217,"context_line":"                self._type.validate(obj, attr, value)"},{"line_number":218,"context_line":"            return value"},{"line_number":219,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"ba3cc151_e0b2904b","line":216,"updated":"2015-07-02 18:34:40.000000000","message":"How about we either:\n\n1. Define validate on the normal base object to be a no-op\n2. Use hasattr() here so we\u0027re not so strict about inheritance\n3. Make all types validatable\n\nIs there any reason not to do #3? Like, just make validators be present and empty for all field types and avoid having the other inheritance hierarchy. Why not?","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"45dfc297c19801759818ec5f6805600d8382714c","unresolved":false,"context_lines":[{"line_number":213,"context_line":"            return self._null(obj, attr)"},{"line_number":214,"context_line":"        else:"},{"line_number":215,"context_line":"            value \u003d self._type.coerce(obj, attr, value)"},{"line_number":216,"context_line":"            if isinstance(self._type, ValidatableType):"},{"line_number":217,"context_line":"                self._type.validate(obj, attr, value)"},{"line_number":218,"context_line":"            return value"},{"line_number":219,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"ba3cc151_bfb24504","line":216,"in_reply_to":"ba3cc151_e0b2904b","updated":"2015-07-03 12:41:31.000000000","message":"This sounds reasonable.\nHowever, this will require to add a constructor to FieldType, which will init the validators field to an empty value.\n\nThis will require all the inheritors of FieldType to call super().__init__ in their initializers, which may break backwards compatibility in some projects which already use the lib.\n\nSo, I\u0027ll do it but I still have to add \"hasAttr\" check at the validate call anyway.","commit_id":"ce64e4541a68bcf427bac697926cc6edadcf283d"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e06678c54055f76a5fb74c14c19c01a77e509fbd","unresolved":false,"context_lines":[{"line_number":113,"context_line":"        self.validators \u003d validators or []"},{"line_number":114,"context_line":"        super(FieldType, self).__init__(**kwargs)"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def _get_standard_validators(self):"},{"line_number":117,"context_line":"        # NOTE (ativelkov): an alternative to having this method would be to"},{"line_number":118,"context_line":"        # add appropriate check methods to the validators attribute in the"},{"line_number":119,"context_line":"        # constructor."}],"source_content_type":"text/x-python","patch_set":11,"id":"9a41bdd9_b77333e7","line":116,"range":{"start_line":116,"start_character":13,"end_line":116,"end_character":22},"updated":"2015-07-16 17:53:40.000000000","message":"Can we call this just \"_get_validators\"?\n\nWith \"standard\" in the name, it sounds like it won\u0027t be override-able, but it is and you do.","commit_id":"3cab8f6c4445f000063db644ef753e9f50234cbf"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"ea5ed210c8f821aa4ff01642af2ab13aaeef0bd9","unresolved":false,"context_lines":[{"line_number":113,"context_line":"        self.validators \u003d validators or []"},{"line_number":114,"context_line":"        super(FieldType, self).__init__(**kwargs)"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def _get_standard_validators(self):"},{"line_number":117,"context_line":"        # NOTE (ativelkov): an alternative to having this method would be to"},{"line_number":118,"context_line":"        # add appropriate check methods to the validators attribute in the"},{"line_number":119,"context_line":"        # constructor."}],"source_content_type":"text/x-python","patch_set":11,"id":"3a50d1a3_8e39e043","line":116,"in_reply_to":"9a41bdd9_b77333e7","updated":"2015-07-21 15:42:02.000000000","message":"Sure. The idea is that \"standard\" are the ones made on the constraints, while there are \"custom\" ones brought by the \"validators\" parameter.\n\nBut I\u0027ll rename that, no problems.","commit_id":"3cab8f6c4445f000063db644ef753e9f50234cbf"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e06678c54055f76a5fb74c14c19c01a77e509fbd","unresolved":false,"context_lines":[{"line_number":121,"context_line":"        # method is needed."},{"line_number":122,"context_line":"        return [self._check_allowed]"},{"line_number":123,"context_line":""},{"line_number":124,"context_line":"    def _check_allowed(self, obj, attr, value):"},{"line_number":125,"context_line":"        if self._allowed_values is not None:"},{"line_number":126,"context_line":"            return value in self._allowed_values, _(\"value is not allowed\")"},{"line_number":127,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"9a41bdd9_b2ab41d6","line":124,"updated":"2015-07-16 17:53:40.000000000","message":"So, this kinda overlaps with Enum. If we\u0027re going to put this into the base class, I think we should name the parameter the same (valid_values) and make Enum use the same constructs.\n\nI\u0027m not sure I see actual uses for valid_values of integer and float values, but that\u0027s probably just my lack of imagination I guess.","commit_id":"3cab8f6c4445f000063db644ef753e9f50234cbf"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"ea5ed210c8f821aa4ff01642af2ab13aaeef0bd9","unresolved":false,"context_lines":[{"line_number":121,"context_line":"        # method is needed."},{"line_number":122,"context_line":"        return [self._check_allowed]"},{"line_number":123,"context_line":""},{"line_number":124,"context_line":"    def _check_allowed(self, obj, attr, value):"},{"line_number":125,"context_line":"        if self._allowed_values is not None:"},{"line_number":126,"context_line":"            return value in self._allowed_values, _(\"value is not allowed\")"},{"line_number":127,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"3a50d1a3_e9e89e12","line":124,"in_reply_to":"9a41bdd9_b2ab41d6","updated":"2015-07-21 15:42:02.000000000","message":"Yep, I was thinking about that. Didn\u0027t want to touch anything which may be potential in use in some tricky way. But I\u0027ll try to wrap it carefully.\n\nRegarding the usage: lot\u0027s of enums are mapped to integers rather then strings. Also, various multipliers and coefficients often have restricted set of values.","commit_id":"3cab8f6c4445f000063db644ef753e9f50234cbf"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"e06678c54055f76a5fb74c14c19c01a77e509fbd","unresolved":false,"context_lines":[{"line_number":354,"context_line":"    \"\"\"Base class for validatable fields which should have min/max checks\"\"\""},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"    def __init__(self, minimum\u003dNone, maximum\u003dNone,"},{"line_number":357,"context_line":"                 exclusive_minimum\u003dFalse, exclusive_maximum\u003dFalse,"},{"line_number":358,"context_line":"                 *args, **kwargs):"},{"line_number":359,"context_line":"        # NOTE(ativelkov): coercing the min/max constraints themselves"},{"line_number":360,"context_line":"        if minimum is not None:"}],"source_content_type":"text/x-python","patch_set":11,"id":"9a41bdd9_37cba320","line":357,"range":{"start_line":357,"start_character":17,"end_line":357,"end_character":66},"updated":"2015-07-16 17:53:40.000000000","message":"So, the word \"maximum\" means \"the maximum value\" to me, and thus implies inclusive. I think that in almost all cases, people will want inclusive values here. Since fields should never be defined programmatically, I think that it\u0027s fine to make this always inclusive and drop the complexity of checking these flags.\n\nIs there some really compelling reason to have them?","commit_id":"3cab8f6c4445f000063db644ef753e9f50234cbf"},{"author":{"_account_id":8127,"name":"Alexander Tivelkov","email":"locher@yandex.ru","username":"ativelkov"},"change_message_id":"ea5ed210c8f821aa4ff01642af2ab13aaeef0bd9","unresolved":false,"context_lines":[{"line_number":354,"context_line":"    \"\"\"Base class for validatable fields which should have min/max checks\"\"\""},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"    def __init__(self, minimum\u003dNone, maximum\u003dNone,"},{"line_number":357,"context_line":"                 exclusive_minimum\u003dFalse, exclusive_maximum\u003dFalse,"},{"line_number":358,"context_line":"                 *args, **kwargs):"},{"line_number":359,"context_line":"        # NOTE(ativelkov): coercing the min/max constraints themselves"},{"line_number":360,"context_line":"        if minimum is not None:"}],"source_content_type":"text/x-python","patch_set":11,"id":"3a50d1a3_2e7e8c19","line":357,"in_reply_to":"9a41bdd9_37cba320","updated":"2015-07-21 15:42:02.000000000","message":"I used jsonschema for the inspiration here: http://json-schema.org/latest/json-schema-validation.html#anchor17\n\nThus are the names of the constraints and the presence of exclusive_* fields. \n\nThat\u0027s the only reason, I  don\u0027t have any strong use-case for this options, so I may drop it if you wish.","commit_id":"3cab8f6c4445f000063db644ef753e9f50234cbf"}]}
