Permalink
Browse files

make decorators a function again

The use of a class implementing __call__ cases problems when
a depending on inspect and thelike. Also, self will not be passed here.
  • Loading branch information...
1 parent 83e6ff1 commit f1ad137bc261f45656e8fba4ebaa45c1894bc560 @doncatnip committed Jun 22, 2011
Showing with 119 additions and 138 deletions.
  1. +38 −98 src/require/adapter/native.py
  2. +79 −36 src/require/adapter/tx.py
  3. +2 −4 src/require/validator/web.py
@@ -1,4 +1,3 @@
-from ..validator.schema import Schema, ForEach
from ..error import Invalid
from ..util import varargs2kwargs, getArgSpec, getParameterNames
from decorator import decorator
@@ -7,129 +6,70 @@
log = logging.getLogger(__name__)
-class ValidateDecorator:
+def validateDecorator( validator, method, include, exclude, onInvalid ):
- def __init__( self, validator, method, include, exclude, onInvalid ):
- if include and exclude:
- raise SyntaxError("'include' and 'exclude' cannot be used at the same time")
+ if include and exclude:
+ raise SyntaxError("'include' and 'exclude' cannot be used at the same time")
- self.__name__ = method.__name__
- self.validator = validator
- self.method = method
- self.onInvalid = onInvalid
+ spec = getArgSpec( method )
+ hasVarargs = spec.varargs is not None
+ varargs = spec.varargs or '*varargs'
+ keywords = spec.keywords or False
- spec = getArgSpec( method )
- hasVarargs = spec.varargs is not None
- varargs = spec.varargs or '*varargs'
- keywords = spec.keywords or False
+ methodParameterNames = getParameterNames( method, skipSelf=False )
- self.methodParameterNames = getParameterNames( method, skipSelf=False )
+ skip = ()
+ if exclude:
+ skip = exclude
+ if include:
+ skip = set(methodParameterNames) - set(include)
- self.skip = ()
- if exclude:
- self.skip = exclude
- if include:
- self.skip = set(methodParameterNames) - set(include)
+ varargs = varargs
- self.varargs = varargs
+ hasVarargs = spec.varargs not in skip and hasVarargs
- self.hasVarargs = spec.varargs not in self.skip and hasVarargs
- self.keywords = keywords not in self.skip and keywords
+ keywords = keywords not in skip and keywords
- def __call__( self, *fargs, **fkwargs):
+ def __wrap( *fargs, **fkwargs):
- (fargs, fkwargs, shifted ) = varargs2kwargs( self.method, fargs, fkwargs, skipSelf=False )
+ log.debug( ('preshift',fargs,fkwargs) )
+ (fargs, fkwargs, shifted ) = varargs2kwargs( method, fargs, fkwargs, skipSelf=False )
+ log.debug( ('postshft',fargs,fkwargs,shifted) )
origKwargs = dict(fkwargs)
- if self.keywords is not False:
+ if keywords is not False:
restKwargs = dict(\
( key, fkwargs.pop(key))\
- for key in fkwargs.keys() if key not in self.methodParameterNames
+ for key in fkwargs.keys() if key not in methodParameterNames
)
- fkwargs[ self.keywords ] = restKwargs
+ fkwargs[ keywords ] = restKwargs
- if fargs or self.hasVarargs:
- fkwargs[ self.varargs ] = list(fargs)
+ if fargs or hasVarargs:
+ fkwargs[ varargs ] = list(fargs)
try:
- resultKwargs = self.validator.context\
- ( dict( ( key, fkwargs[ key] ) for key in fkwargs if key not in self.skip ) ).result
+ resultKwargs =validator.context\
+ ( dict( ( key, fkwargs[ key] ) for key in fkwargs if key not in skip ) ).result
except Invalid as e:
- if self.onInvalid is not None:
- return self.onInvalid( e )
+ if onInvalid is not None:
+ return onInvalid( e )
else:
raise
origKwargs.update( resultKwargs )
- resultKwargs = origKwargs
- resultArgs = resultKwargs.pop( self.varargs, fargs )
- resultArgs = [ resultKwargs.pop(key) for key in shifted ] + resultArgs
+ resultArgs = origKwargs.pop( varargs, fargs )
+ resultArgs = [ origKwargs.pop(key) for key in shifted ] + resultArgs
- if self.keywords is not False:
- resultKwargs.update( resultKwargs.pop( self.keywords ) )
+ if keywords is not False:
+ origKwargs.update( origKwargs.pop( keywords ) )
- return self.method( *resultArgs, **resultKwargs )
+ return method( *resultArgs, **origKwargs )
+ return __wrap
def validate( validator, include=None, exclude=None, onInvalid=None ):
- def __validateDecorator( method ):
- return ValidateDecorator( validator, method, include, exclude, onInvalid)
- return __validateDecorator
+ def __createDecorator( method ):
+ return validateDecorator( validator, method, include, exclude, onInvalid)
+ return __createDecorator
-"""
-def validate( validator, *paramNames, **kwargs ):
-
- def __validateDecorator( f ):
- spec = getArgSpec( f )
-
- onInvalid = kwargs.pop( 'onInvalid', None)
-
- hasVarargs = spec.varargs is not None
-
- varargs = spec.varargs or '*varargs'
- keywords = spec.keywords or None
-
- methodParameterNames = spec.args
-
- def __validateArgs( *fargs, **fkwargs):
- paramNames = paramNames or methodParameterNames
-
- keywords = keywords in paramNames and keywords
- hasVarargs = varargs in paramNames and hasVarargs
-
- (fargs, fkwargs, shifted ) = varargs2kwargs( f, fargs, fkwargs )
-
- if keywords is not False:
- restKwargs = dict(\
- ( key, fkwargs.pop(key))\
- for key in fkwargs.keys() if key not in methodParameterNames
- )
- fkwargs[ keywords ] = restKwargs
-
- if fargs or hasVarargs:
- fkwargs[ varargs ] = list(fargs)
-
- try:
- resultKwargs = validator.context\
- ( dict( ( key, fkwargs[ key] ) for key in paramNames ) ).result
- except Invalid as e:
- if onInvalid is not None:
- return onInvalid( e )
- else:
- raise
-
- resultArgs = resultKwargs.pop( varargs, fargs )
- resultArgs = [ resultKwargs.pop(key) for key in shifted ] + resultArgs
-
- if keywords is not False:
- resultKwargs.update( resultKwargs.pop( keywords ) )
- else:
- resultKwargs.update( restKwargs )
-
- return f( *resultArgs, **resultKwargs )
-
- return __validateArgs
-
- return __validateDecorator
-"""
View
@@ -2,6 +2,8 @@
from twisted.python.failure import Failure
from twisted.internet import defer
+from ..lib import Invalid
+from ..util import varargs2kwargs
import logging
log = logging.getLogger( __name__ )
@@ -11,19 +13,19 @@
# and get rid of the monkey
def monkeyPatch( ):
+ if getattr( monkeyPatch,'_isMonkeyPatched',False):
+ return
"""
Patches require so that any validation returns a Deferred, thus
one can write asynchronous validators using Twisted's non-blocking API.
Schema and ForEach fields are validated concurrently.
"""
- from ..lib import Context, PASS, MISSING, Invalid
+ from ..lib import Context, PASS, MISSING
from ..validator.core import Tag, Compose, Tmp, Item, Not, And, Or, Call
from ..validator.check import Match
from ..validator.schema import Schema, ForEach, Field
- from .native import ValidateDecorator
- from ..util import varargs2kwargs
@defer.inlineCallbacks
def context_validate( self ):
@@ -715,56 +717,97 @@ def field_validate(self, context, value):
defer.returnValue( value )
+
+ Context.validate = context_validate
+ Tag.validate = tag_validate
+ Compose.valdate = compose_validate
+ Tmp.validate = tmp_validate
+ Item.validate = item_validate
+ Not.validate = not_validate
+ And.validate = and_validate
+ Or.validate = or_validate
+ Call.validate = call_validate
+ Match.on_value = match_on_value
+ Schema._on_value = schema__on_value
+ Schema._createContextChilds_on_value = schema__createContextChilds_on_value
+ ForEach._on_value = forEach__on_value
+ ForEach._createContextChilds_on_value = forEach__createContextChilds_on_value
+ Field.validate = field_validate
+
+ monkeyPatch._isMonkeyPatched = True
+
+from ..util import varargs2kwargs, getArgSpec, getParameterNames
+from decorator import decorator
+
+import logging, types
+
+log = logging.getLogger(__name__)
+
+def validateDecorator( validator, method, include, exclude, onInvalid ):
+
+ if include and exclude:
+ raise SyntaxError("'include' and 'exclude' cannot be used at the same time")
+
+ spec = getArgSpec( method )
+ hasVarargs = spec.varargs is not None
+ varargs = spec.varargs or '*varargs'
+ keywords = spec.keywords or False
+
+ methodParameterNames = getParameterNames( method, skipSelf=False )
+
+ skip = ()
+ if exclude:
+ skip = exclude
+ if include:
+ skip = set(methodParameterNames) - set(include)
+
+ varargs = varargs
+
+ hasVarargs = spec.varargs not in skip and hasVarargs
+
+ keywords = keywords not in skip and keywords
+
@defer.inlineCallbacks
- def validateDecorator___call__( self, *fargs, **fkwargs):
- (fargs, fkwargs, shifted ) = varargs2kwargs( self.method, fargs, fkwargs, skipSelf=False )
+ def __wrap( *fargs, **fkwargs):
+
+ log.debug( ('preshift',fargs,fkwargs) )
+ (fargs, fkwargs, shifted ) = varargs2kwargs( method, fargs, fkwargs, skipSelf=False )
+ log.debug( ('postshft',fargs,fkwargs,shifted) )
origKwargs = dict(fkwargs)
- if self.keywords is not False:
+ if keywords is not False:
restKwargs = dict(\
( key, fkwargs.pop(key))\
- for key in fkwargs.keys() if key not in self.methodParameterNames
+ for key in fkwargs.keys() if key not in methodParameterNames
)
- fkwargs[ self.keywords ] = restKwargs
+ fkwargs[ keywords ] = restKwargs
- if fargs or self.hasVarargs:
- fkwargs[ self.varargs ] = list(fargs)
+ if fargs or hasVarargs:
+ fkwargs[ varargs ] = list(fargs)
try:
- resultKwargs = yield self.validator.context\
- ( dict( ( key, fkwargs[ key] ) for key in fkwargs if key not in self.skip ) ).result
+ resultKwargs = yield validator.context\
+ ( dict( ( key, fkwargs[ key] ) for key in fkwargs if key not in skip ) ).result
except Invalid as e:
- if self.onInvalid is not None:
- defer.returnValue( self.onInvalid( e ) )
+ if onInvalid is not None:
+ defer.returnValue( onInvalid( e ) )
else:
raise
origKwargs.update( resultKwargs )
- resultKwargs = origKwargs
- resultArgs = resultKwargs.pop( self.varargs, fargs )
- resultArgs = [ resultKwargs.pop(key) for key in shifted ] + resultArgs
+ resultArgs = origKwargs.pop( varargs, fargs )
+ resultArgs = [ origKwargs.pop(key) for key in shifted ] + resultArgs
- if self.keywords is not False:
- resultKwargs.update( resultKwargs.pop( self.keywords ) )
+ if keywords is not False:
+ origKwargs.update( origKwargs.pop( keywords ) )
- defer.returnValue( self.method( *resultArgs, **resultKwargs ) )
+ defer.returnValue( method( *resultArgs, **origKwargs ) )
+ return __wrap
- Context.validate = context_validate
- Tag.validate = tag_validate
- Compose.valdate = compose_validate
- Tmp.validate = tmp_validate
- Item.validate = item_validate
- Not.validate = not_validate
- And.validate = and_validate
- Or.validate = or_validate
- Call.validate = call_validate
- Match.on_value = match_on_value
- Schema._on_value = schema__on_value
- Schema._createContextChilds_on_value = schema__createContextChilds_on_value
- ForEach._on_value = forEach__on_value
- ForEach._createContextChilds_on_value = forEach__createContextChilds_on_value
- Field.validate = field_validate
- ValidateDecorator.__call__ = validateDecorator___call__
+def validate( validator, include=None, exclude=None, onInvalid=None ):
+ def __createDecorator( method ):
+ return validateDecorator( validator, method, include, exclude, onInvalid)
+ return __createDecorator
@@ -53,8 +53,8 @@ def on_value( self, context, value ):
)
)
).tag('punycode')
- & Len(min=2, max=63).tag('length')
- & Match(re.compile(r'^((([a-z][0-9])|([0-9][a-z])|([a-z0-9][a-z0-9\-]{1,2}[a-z0-9])|([a-z0-9][a-z0-9\-](([a-z0-9\-][a-z0-9])|([a-z0-9][a-z0-9\-]))[a-z0-9\-]*[a-z0-9]))|([a-z0-9]{2})|(xn\-\-[\-a-z0-9]*[a-z0-9]))$')).tag('validSymbols')
+ & Len(max=63).tag('length')
+ & Match(re.compile(r'^((([a-z][0-9])|([0-9][a-z])|([a-z0-9][a-z0-9\-]{1,2}[a-z0-9])|([a-z0-9][a-z0-9\-](([a-z0-9\-][a-z0-9])|([a-z0-9][a-z0-9\-]))[a-z0-9\-]*[a-z0-9]))|([a-z0-9]{1,2})|(xn\-\-[\-a-z0-9]*[a-z0-9]))$')).tag('validSymbols')
& cache.Get('domainLabel').tag('returnNonPuny', False)
).paramAlias\
( convertToString='string_convert'
@@ -66,14 +66,12 @@ def on_value( self, context, value ):
).messageAlias\
( type='string_type'
, tooLong='length_max'
- , tooShort='length_min'
, invalidSymbols='validSymbols_fail'
, blank=("toLower_blank","string_blank","encodePuny_blank","length_blank")
, missing="string_missing"
).messages\
( blank='Please provide a value'
, tooLong='A domain label can have max %(max)i characters'
- , tooShort='A domain label must have at least %(min)i characters'
, invalidSymbols='The domain name contains invalid symbols'
)

0 comments on commit f1ad137

Please sign in to comment.