123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- #Copyright ReportLab Europe Ltd. 2000-2017
- #see license.txt for license details
- #history https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/lib/validators.py
- __version__='3.5.33'
- __doc__="""Standard verifying functions used by attrmap."""
- import sys, codecs
- from reportlab.lib.utils import isSeq, isBytes, isStr
- from reportlab.lib import colors
- class Percentage(float):
- pass
- class Validator:
- "base validator class"
- def __call__(self,x):
- return self.test(x)
- def __str__(self):
- return getattr(self,'_str',self.__class__.__name__)
- def normalize(self,x):
- return x
- def normalizeTest(self,x):
- try:
- self.normalize(x)
- return True
- except:
- return False
- class _isAnything(Validator):
- def test(self,x):
- return True
- class _isNothing(Validator):
- def test(self,x):
- return False
- class _isBoolean(Validator):
- def test(self,x):
- if isinstance(int,bool): return x in (0,1)
- return self.normalizeTest(x)
- def normalize(self,x):
- if x in (0,1): return x
- try:
- S = x.upper()
- except:
- raise ValueError('Must be boolean not %s' % ascii(s))
- if S in ('YES','TRUE'): return True
- if S in ('NO','FALSE',None): return False
- raise ValueError('Must be boolean not %s' % ascii(s))
- class _isString(Validator):
- def test(self,x):
- return isStr(x)
- class _isCodec(Validator):
- def test(self,x):
- if not isStr(x):
- return False
- try:
- a,b,c,d = codecs.lookup(x)
- return True
- except LookupError:
- return False
- class _isNumber(Validator):
- def test(self,x):
- if isinstance(x,(float,int)): return True
- return self.normalizeTest(x)
- def normalize(self,x):
- try:
- return float(x)
- except:
- return int(x)
- class _isInt(Validator):
- def test(self,x):
- if not isinstance(x,int) and not isStr(x): return False
- return self.normalizeTest(x)
- def normalize(self,x):
- return int(x.decode('utf8') if isBytes(x) else x)
- class _isNumberOrNone(_isNumber):
- def test(self,x):
- return x is None or isNumber(x)
- def normalize(self,x):
- if x is None: return x
- return _isNumber.normalize(x)
- class _isListOfNumbersOrNone(Validator):
- "ListOfNumbersOrNone validator class."
- def test(self, x):
- if x is None: return True
- return isListOfNumbers(x)
- class isNumberInRange(_isNumber):
- def __init__(self, min, max):
- self.min = min
- self.max = max
- def test(self, x):
- try:
- n = self.normalize(x)
- if self.min <= n <= self.max:
- return True
- except ValueError:
- pass
- return False
- class _isListOfShapes(Validator):
- "ListOfShapes validator class."
- def test(self, x):
- from reportlab.graphics.shapes import Shape
- if isSeq(x):
- answer = 1
- for e in x:
- if not isinstance(e, Shape):
- answer = 0
- return answer
- else:
- return False
- class _isListOfStringsOrNone(Validator):
- "ListOfStringsOrNone validator class."
- def test(self, x):
- if x is None: return True
- return isListOfStrings(x)
- class _isTransform(Validator):
- "Transform validator class."
- def test(self, x):
- if isSeq(x):
- if len(x) == 6:
- for element in x:
- if not isNumber(element):
- return False
- return True
- else:
- return False
- else:
- return False
- class _isColor(Validator):
- "Color validator class."
- def test(self, x):
- return isinstance(x, colors.Color)
- class _isColorOrNone(Validator):
- "ColorOrNone validator class."
- def test(self, x):
- if x is None: return True
- return isColor(x)
- from reportlab.lib.normalDate import NormalDate
- class _isNormalDate(Validator):
- def test(self,x):
- if isinstance(x,NormalDate):
- return True
- return x is not None and self.normalizeTest(x)
- def normalize(self,x):
- return NormalDate(x)
- class _isValidChild(Validator):
- "ValidChild validator class."
- def test(self, x):
- """Is this child allowed in a drawing or group?
- I.e. does it descend from Shape or UserNode?
- """
- from reportlab.graphics.shapes import UserNode, Shape
- return isinstance(x, UserNode) or isinstance(x, Shape)
- class _isValidChildOrNone(_isValidChild):
- def test(self,x):
- return _isValidChild.test(self,x) or x is None
- class _isCallable(Validator):
- def test(self, x):
- return hasattr(x,'__call__')
- class OneOf(Validator):
- """Make validator functions for list of choices.
- Usage:
- f = reportlab.lib.validators.OneOf('happy','sad')
- or
- f = reportlab.lib.validators.OneOf(('happy','sad'))
- f('sad'),f('happy'), f('grumpy')
- (1,1,0)
- """
- def __init__(self, enum,*args):
- if isSeq(enum):
- if args!=():
- raise ValueError("Either all singleton args or a single sequence argument")
- self._enum = tuple(enum)+args
- else:
- self._enum = (enum,)+args
- def test(self, x):
- return x in self._enum
- class SequenceOf(Validator):
- def __init__(self,elemTest,name=None,emptyOK=1, NoneOK=0, lo=0,hi=0x7fffffff):
- self._elemTest = elemTest
- self._emptyOK = emptyOK
- self._NoneOK = NoneOK
- self._lo, self._hi = lo, hi
- if name: self._str = name
- def test(self, x):
- if not isSeq(x):
- if x is None: return self._NoneOK
- return False
- if x==[] or x==():
- return self._emptyOK
- elif not self._lo<=len(x)<=self._hi: return False
- for e in x:
- if not self._elemTest(e): return False
- return True
- class EitherOr(Validator):
- def __init__(self,tests,name=None):
- if not isSeq(tests): tests = (tests,)
- self._tests = tests
- if name: self._str = name
- def test(self, x):
- for t in self._tests:
- if t(x): return True
- return False
- class NoneOr(Validator):
- def __init__(self,elemTest,name=None):
- self._elemTest = elemTest
- if name: self._str = name
- def test(self, x):
- if x is None: return True
- return self._elemTest(x)
- class NotSetOr(NoneOr):
- _not_set = object()
- def test(self, x):
- if x is NotSetOr._not_set: return True
- return self._elemTest(x)
- @staticmethod
- def conditionalValue(v,a):
- return a if v is NotSetOr._not_set else v
- class _isNotSet(Validator):
- def test(self,x):
- return x is NotSetOr._not_set
- class Auto(Validator):
- def __init__(self,**kw):
- self.__dict__.update(kw)
- def test(self,x):
- return x is self.__class__ or isinstance(x,self.__class__)
- class AutoOr(NoneOr):
- def test(self,x):
- return isAuto(x) or self._elemTest(x)
- class isInstanceOf(Validator):
- def __init__(self,klass=None):
- self._klass = klass
- def test(self,x):
- return isinstance(x,self._klass)
- class isSubclassOf(Validator):
- def __init__(self,klass=None):
- self._klass = klass
- def test(self,x):
- return issubclass(x,self._klass)
- class matchesPattern(Validator):
- """Matches value, or its string representation, against regex"""
- def __init__(self, pattern):
- self._pattern = re.compile(pattern)
- def test(self,x):
- x = str(x)
- print('testing %s against %s' % (x, self._pattern))
- return (self._pattern.match(x) != None)
- class DerivedValue:
- """This is used for magic values which work themselves out.
- An example would be an "inherit" property, so that one can have
- drawing.chart.categoryAxis.labels.fontName = inherit
- and pick up the value from the top of the drawing.
- Validators will permit this provided that a value can be pulled
- in which satisfies it. And the renderer will have special
- knowledge of these so they can evaluate themselves.
- """
- def getValue(self, renderer, attr):
- """Override this. The renderers will pass the renderer,
- and the attribute name. Algorithms can then backtrack up
- through all the stuff the renderer provides, including
- a correct stack of parent nodes."""
- return None
- class Inherit(DerivedValue):
- def __repr__(self):
- return "inherit"
- def getValue(self, renderer, attr):
- return renderer.getStateValue(attr)
- inherit = Inherit()
- class NumericAlign(str):
- '''for creating the numeric string value for anchors etc etc
- dp is the character to align on (the last occurrence will be used)
- dpLen is the length of characters after the dp
- '''
- def __new__(cls,dp='.',dpLen=0):
- self = str.__new__(cls,'numeric')
- self._dp=dp
- self._dpLen = dpLen
- return self
- isAuto = Auto()
- isBoolean = _isBoolean()
- isString = _isString()
- isCodec = _isCodec()
- isNumber = _isNumber()
- isInt = _isInt()
- isNoneOrInt = NoneOr(isInt,'isNoneOrInt')
- isNumberOrNone = _isNumberOrNone()
- isTextAnchor = OneOf('start','middle','end','boxauto')
- isListOfNumbers = SequenceOf(isNumber,'isListOfNumbers')
- isListOfNoneOrNumber = SequenceOf(isNumberOrNone,'isListOfNoneOrNumber')
- isListOfListOfNoneOrNumber = SequenceOf(isListOfNoneOrNumber,'isListOfListOfNoneOrNumber')
- isListOfNumbersOrNone = _isListOfNumbersOrNone()
- isListOfShapes = _isListOfShapes()
- isListOfStrings = SequenceOf(isString,'isListOfStrings')
- isListOfStringsOrNone = _isListOfStringsOrNone()
- isTransform = _isTransform()
- isColor = _isColor()
- isListOfColors = SequenceOf(isColor,'isListOfColors')
- isColorOrNone = _isColorOrNone()
- isShape = isValidChild = _isValidChild()
- isNoneOrShape = isValidChildOrNone = _isValidChildOrNone()
- isAnything = _isAnything()
- isNothing = _isNothing()
- isXYCoord = SequenceOf(isNumber,lo=2,hi=2,emptyOK=0)
- isBoxAnchor = OneOf('nw','n','ne','w','c','e','sw','s','se', 'autox', 'autoy')
- isNoneOrString = NoneOr(isString,'NoneOrString')
- isNoneOrListOfNoneOrStrings=SequenceOf(isNoneOrString,'isNoneOrListOfNoneOrStrings',NoneOK=1)
- isListOfNoneOrString=SequenceOf(isNoneOrString,'isListOfNoneOrString',NoneOK=0)
- isNoneOrListOfNoneOrNumbers=SequenceOf(isNumberOrNone,'isNoneOrListOfNoneOrNumbers',NoneOK=1)
- isCallable = _isCallable()
- isNoneOrCallable = NoneOr(isCallable)
- isStringOrCallable=EitherOr((isString,isCallable),'isStringOrCallable')
- isStringOrCallableOrNone=NoneOr(isStringOrCallable,'isStringOrCallableNone')
- isStringOrNone=NoneOr(isString,'isStringOrNone')
- isNormalDate=_isNormalDate()
- isNotSet=_isNotSet()
|