222 object.__setattr__(self, key, value) |
222 object.__setattr__(self, key, value) |
223 else: |
223 else: |
224 raise ValidationError('Class \'%s\' does not have attribute \'%s\'' |
224 raise ValidationError('Class \'%s\' does not have attribute \'%s\'' |
225 % (self.__class__, key)) |
225 % (self.__class__, key)) |
226 |
226 |
227 def __eq__(self, other): |
|
228 """Comparison operator.""" |
|
229 if isinstance(other, type(self)): |
|
230 for attribute in self.ATTRIBUTES: |
|
231 if getattr(self, attribute) != getattr(other, attribute): |
|
232 return False |
|
233 return True |
|
234 else: |
|
235 return False |
|
236 |
|
237 def __str__(self): |
227 def __str__(self): |
238 """Formatted view of validated object and nested values.""" |
228 """Formatted view of validated object and nested values.""" |
239 return repr(self) |
229 return repr(self) |
240 |
230 |
241 def __repr__(self): |
231 def __repr__(self): |
676 raise ValidationError('Value \'%s\' does not match expression \'%s\'' |
666 raise ValidationError('Value \'%s\' does not match expression \'%s\'' |
677 % (value, self.re.pattern)) |
667 % (value, self.re.pattern)) |
678 return cast_value |
668 return cast_value |
679 |
669 |
680 |
670 |
|
671 class _RegexStrValue(object): |
|
672 """Simulates the regex object to support recomplation when necessary. |
|
673 |
|
674 Used by the RegexStr class to dynamically build and recompile regular |
|
675 expression attributes of a validated object. This object replaces the normal |
|
676 object returned from re.compile which is immutable. |
|
677 |
|
678 When the value of this object is a string, that string is simply used as the |
|
679 regular expression when recompilation is needed. If the state of this object |
|
680 is a list of strings, the strings are joined in to a single 'or' expression. |
|
681 """ |
|
682 |
|
683 def __init__(self, attribute, value): |
|
684 """Initialize recompilable regex value. |
|
685 |
|
686 Args: |
|
687 attribute: Attribute validator associated with this regex value. |
|
688 value: Initial underlying python value for regex string. Either a single |
|
689 regex string or a list of regex strings. |
|
690 """ |
|
691 self.__attribute = attribute |
|
692 self.__value = value |
|
693 self.__regex = None |
|
694 |
|
695 def __AsString(self, value): |
|
696 """Convert a value to appropriate string. |
|
697 |
|
698 Returns: |
|
699 String version of value with all carriage returns and line feeds removed. |
|
700 """ |
|
701 if issubclass(self.__attribute.expected_type, str): |
|
702 cast_value = TYPE_STR(value) |
|
703 else: |
|
704 cast_value = TYPE_UNICODE(value) |
|
705 |
|
706 cast_value = cast_value.replace('\n', '') |
|
707 cast_value = cast_value.replace('\r', '') |
|
708 return cast_value |
|
709 |
|
710 def __BuildRegex(self): |
|
711 """Build regex string from state. |
|
712 |
|
713 Returns: |
|
714 String version of regular expression. Sequence objects are constructed |
|
715 as larger regular expression where each regex in the list is joined with |
|
716 all the others as single 'or' expression. |
|
717 """ |
|
718 if isinstance(self.__value, list): |
|
719 value_list = self.__value |
|
720 sequence = True |
|
721 else: |
|
722 value_list = [self.__value] |
|
723 sequence = False |
|
724 |
|
725 regex_list = [] |
|
726 for item in value_list: |
|
727 regex_list.append(self.__AsString(item)) |
|
728 |
|
729 if sequence: |
|
730 return '|'.join('(?:%s)' % item for item in regex_list) |
|
731 else: |
|
732 return regex_list[0] |
|
733 |
|
734 def __Compile(self): |
|
735 """Build regular expression object from state. |
|
736 |
|
737 Returns: |
|
738 Compiled regular expression based on internal value. |
|
739 """ |
|
740 regex = self.__BuildRegex() |
|
741 try: |
|
742 return re.compile(regex) |
|
743 except re.error, e: |
|
744 raise ValidationError('Value \'%s\' does not compile: %s' % (regex, e), e) |
|
745 |
|
746 @property |
|
747 def regex(self): |
|
748 """Compiled regular expression as described by underlying value.""" |
|
749 return self.__Compile() |
|
750 |
|
751 def match(self, value): |
|
752 """Match against internal regular expression. |
|
753 |
|
754 Returns: |
|
755 Regular expression object built from underlying value. |
|
756 """ |
|
757 return re.match(self.__BuildRegex(), value) |
|
758 |
|
759 def Validate(self): |
|
760 """Ensure that regex string compiles.""" |
|
761 self.__Compile() |
|
762 |
|
763 def __str__(self): |
|
764 """Regular expression string as described by underlying value.""" |
|
765 return self.__BuildRegex() |
|
766 |
|
767 def __eq__(self, other): |
|
768 """Comparison against other regular expression string values.""" |
|
769 if isinstance(other, _RegexStrValue): |
|
770 return self.__BuildRegex() == other.__BuildRegex() |
|
771 return str(self) == other |
|
772 |
|
773 def __ne__(self, other): |
|
774 """Inequality operator for regular expression string value.""" |
|
775 return not self.__eq__(other) |
|
776 |
|
777 |
681 class RegexStr(Validator): |
778 class RegexStr(Validator): |
682 """Validates that a string can compile as a regex without errors. |
779 """Validates that a string can compile as a regex without errors. |
683 |
780 |
684 Use this validator when the value of a field should be a regex. That |
781 Use this validator when the value of a field should be a regex. That |
685 means that the value must be a string that can be compiled by re.compile(). |
782 means that the value must be a string that can be compiled by re.compile(). |
691 |
788 |
692 Raises: |
789 Raises: |
693 AttributeDefinitionError if string_type is not a kind of string. |
790 AttributeDefinitionError if string_type is not a kind of string. |
694 """ |
791 """ |
695 if default is not None: |
792 if default is not None: |
696 default = re.compile(default) |
793 default = _RegexStrValue(self, default) |
|
794 re.compile(str(default)) |
697 super(RegexStr, self).__init__(default) |
795 super(RegexStr, self).__init__(default) |
698 if (not issubclass(string_type, basestring) or |
796 if (not issubclass(string_type, basestring) or |
699 string_type is basestring): |
797 string_type is basestring): |
700 raise AttributeDefinitionError( |
798 raise AttributeDefinitionError( |
701 'RegexStr fields must be a string type not %s.' % str(string_type)) |
799 'RegexStr fields must be a string type not %s.' % str(string_type)) |
713 |
811 |
714 Raises: |
812 Raises: |
715 ValueError when value does not compile as a regular expression. TypeError |
813 ValueError when value does not compile as a regular expression. TypeError |
716 when value does not match provided string type. |
814 when value does not match provided string type. |
717 """ |
815 """ |
718 if issubclass(self.expected_type, str): |
816 if isinstance(value, _RegexStrValue): |
719 cast_value = TYPE_STR(value) |
817 return value |
720 else: |
818 value = _RegexStrValue(self, value) |
721 cast_value = TYPE_UNICODE(value) |
819 value.Validate() |
722 |
820 return value |
723 cast_value = cast_value.replace('\n', '') |
|
724 cast_value = cast_value.replace('\r', '') |
|
725 try: |
|
726 compiled = re.compile(cast_value) |
|
727 except re.error, e: |
|
728 raise ValidationError('Value \'%s\' does not compile: %s' % (value, e), e) |
|
729 return compiled |
|
730 |
821 |
731 def ToValue(self, value): |
822 def ToValue(self, value): |
732 """Returns the RE pattern for this validator.""" |
823 """Returns the RE pattern for this validator.""" |
733 return value.pattern |
824 return str(value) |
734 |
825 |
735 |
826 |
736 class Range(Validator): |
827 class Range(Validator): |
737 """Validates that numbers fall within the correct range. |
828 """Validates that numbers fall within the correct range. |
738 |
829 |