<s> import tempfile <EOL> import cgi <EOL> from . base import Cleaver <EOL> from . compat import urlencode , parse_qsl <EOL> from . backend import CleaverBackend <EOL> from . identity import CleaverIdentityProvider <EOL> class SplitMiddleware ( object ) : <EOL> def __init__ ( self , app , identity , backend , environ_key = '<STR_LIT>' , <EOL> allow_override = False , count_humans_only = False , <EOL> human_callback_token = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> self . app = app <EOL> if not isinstance ( identity , CleaverIdentityProvider ) and not callable ( identity ) : <EOL> raise RuntimeError ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' % identity <EOL> ) <EOL> if not isinstance ( backend , CleaverBackend ) : <EOL> raise RuntimeError ( <EOL> '<STR_LIT>' % backend <EOL> ) <EOL> self . _identity = identity <EOL> self . _backend = backend <EOL> self . environ_key = environ_key <EOL> self . allow_override = allow_override <EOL> self . count_humans_only = count_humans_only <EOL> self . human_callback_token = human_callback_token <EOL> def __call__ ( self , environ , start_response ) : <EOL> cleaver = Cleaver ( <EOL> environ , <EOL> self . _identity , <EOL> self . _backend , <EOL> count_humans_only = self . count_humans_only <EOL> ) <EOL> environ [ self . environ_key ] = cleaver <EOL> if self . allow_override : <EOL> self . _handle_variant_overrides ( environ ) <EOL> if self . count_humans_only and environ . get ( '<STR_LIT>' , '<STR_LIT>' ) == '<STR_LIT:POST>' and self . human_callback_token in environ . get ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> fp , length = SplitMiddleware . _copy_body_to_tempfile ( environ ) <EOL> environ . setdefault ( '<STR_LIT>' , length ) <EOL> fs = cgi . FieldStorage ( <EOL> fp = fp , <EOL> environ = environ , <EOL> keep_blank_values = True <EOL> ) <EOL> try : <EOL> try : <EOL> x = int ( fs . getlist ( '<STR_LIT:x>' ) [ <NUM_LIT:0> ] ) <EOL> except ( IndexError , ValueError ) : <EOL> x = <NUM_LIT:0> <EOL> try : <EOL> y = int ( fs . getlist ( '<STR_LIT:y>' ) [ <NUM_LIT:0> ] ) <EOL> except ( IndexError , ValueError ) : <EOL> y = <NUM_LIT:0> <EOL> try : <EOL> z = int ( fs . getlist ( '<STR_LIT:z>' ) [ <NUM_LIT:0> ] ) <EOL> except ( IndexError , ValueError ) : <EOL> z = <NUM_LIT:0> <EOL> if x and y and z and x + y == z : <EOL> self . _backend . mark_human ( cleaver . identity ) <EOL> for e in self . _backend . all_experiments ( ) : <EOL> variant = self . _backend . get_variant ( <EOL> cleaver . identity , <EOL> e . name <EOL> ) <EOL> if variant : <EOL> self . _backend . mark_participant ( e . name , variant ) <EOL> start_response ( <EOL> '<STR_LIT>' , <EOL> [ ( '<STR_LIT:Content-Type>' , '<STR_LIT>' ) ] <EOL> ) <EOL> return [ ] <EOL> except ( KeyError , ValueError ) : <EOL> pass <EOL> start_response ( <EOL> '<STR_LIT>' , <EOL> [ ( '<STR_LIT:Content-Type>' , '<STR_LIT>' ) ] <EOL> ) <EOL> return [ ] <EOL> return self . app ( environ , start_response ) <EOL> def _handle_variant_overrides ( self , environ ) : <EOL> parsed = dict ( parse_qsl ( environ . get ( '<STR_LIT>' , '<STR_LIT>' ) ) ) <EOL> qs = parsed . copy ( ) <EOL> for k in parsed : <EOL> if k . startswith ( '<STR_LIT>' ) : <EOL> environ . setdefault ( '<STR_LIT>' , { } ) [ <EOL> k . split ( '<STR_LIT>' ) [ <NUM_LIT:1> ] <EOL> ] = qs . pop ( k ) <EOL> if '<STR_LIT>' in environ : <EOL> environ [ '<STR_LIT>' ] = urlencode ( qs ) <EOL> @ classmethod <EOL> def _copy_body_to_tempfile ( cls , environ ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> length = int ( environ . get ( '<STR_LIT>' , <NUM_LIT:0> ) ) <EOL> except ValueError : <EOL> length = <NUM_LIT:0> <EOL> try : <EOL> fileobj = tempfile . SpooledTemporaryFile ( <NUM_LIT> * <NUM_LIT> ) <EOL> except AttributeError : <EOL> fileobj = tempfile . TemporaryFile ( ) <EOL> if length : <EOL> remaining = length <EOL> while remaining > <NUM_LIT:0> : <EOL> data = environ [ '<STR_LIT>' ] . read ( min ( remaining , <NUM_LIT> ) ) <EOL> if not data : <EOL> raise IOError ( <EOL> "<STR_LIT>" <EOL> % remaining <EOL> ) <EOL> fileobj . write ( data ) <EOL> remaining -= len ( data ) <EOL> fileobj . seek ( <NUM_LIT:0> ) <EOL> environ [ '<STR_LIT>' ] = fileobj <EOL> return fileobj , length </s>
