def toPyModel(model_ptr):
	"""
	toPyModel(model_ptr) -> svm_model

	Convert a ctypes POINTER(svm_model) to a Python svm_model
	"""
	if bool(model_ptr) == False:
		raise ValueError("Null pointer")
	m = model_ptr.contents
	m.__createfrom__ = 'C'
	return m

def
toPyModel
(
model_ptr
)
:
if
bool
(
model_ptr
)
==
False
:
raise
ValueError
(
"Null pointer"
)
m
=
model_ptr
.
contents
m
.
__createfrom__
=
'C'
return
m


svm_read_problem ( data_file_name ) - > [ y x ]

def svm_read_problem(data_file_name):
	"""
	svm_read_problem(data_file_name) -> [y, x]

	Read LIBSVM-format data from data_file_name and return labels y
	and data instances x.
	"""
	prob_y = []
	prob_x = []
	for line in open(data_file_name):
		line = line.split(None, 1)
		# In case an instance with all zero features
		if len(line) == 1: line += ['']
		label, features = line
		xi = {}
		for e in features.split():
			ind, val = e.split(":")
			xi[int(ind)] = float(val)
		prob_y += [float(label)]
		prob_x += [xi]
	return (prob_y, prob_x)


svm_load_model ( model_file_name ) - > model

def svm_load_model(model_file_name):
	"""
	svm_load_model(model_file_name) -> model

	Load a LIBSVM model from model_file_name and return.
	"""
	model = libsvm.svm_load_model(model_file_name.encode())
	if not model:
		print("can't open model file %s" % model_file_name)
		return None
	model = toPyModel(model)
	return model

def
svm_load_model
(
model_file_name
)
:
model
=
libsvm
.
svm_load_model
(
model_file_name
.
encode
(
)
)
if
not
model
:
print
(
"can't open model file %s"
%
model_file_name
)
return
model
=
toPyModel
(
model
)
return
model


svm_save_model ( model_file_name model ) - > None

def svm_save_model(model_file_name, model):
	"""
	svm_save_model(model_file_name, model) -> None

	Save a LIBSVM model to the file model_file_name.
	"""
	libsvm.svm_save_model(model_file_name.encode(), model)

def svm_save_model ( model_file_name , model ) : libsvm . svm_save_model ( model_file_name . encode ( ) , model )


evaluations ( ty pv ) - > ( ACC MSE SCC )

def evaluations(ty, pv):
	"""
	evaluations(ty, pv) -> (ACC, MSE, SCC)

	Calculate accuracy, mean squared error and squared correlation coefficient
	using the true values (ty) and predicted values (pv).
	"""
	if len(ty) != len(pv):
		raise ValueError("len(ty) must equal to len(pv)")
	total_correct = total_error = 0
	sumv = sumy = sumvv = sumyy = sumvy = 0
	for v, y in zip(pv, ty):
		if y == v:
			total_correct += 1
		total_error += (v-y)*(v-y)
		sumv += v
		sumy += y
		sumvv += v*v
		sumyy += y*y
		sumvy += v*y
	l = len(ty)
	ACC = 100.0*total_correct/l
	MSE = total_error/l
	try:
		SCC = ((l*sumvy-sumv*sumy)*(l*sumvy-sumv*sumy))/((l*sumvv-sumv*sumv)*(l*sumyy-sumy*sumy))
	except:
		SCC = float('nan')
	return (ACC, MSE, SCC)

def
evaluations
(
ty
,
pv
)
:
if
len
(
ty
)
!=
len
(
pv
)
:
raise
ValueError
(
"len(ty) must equal to len(pv)"
)
total_correct
=
total_error
=
0
sumv
=
sumy
=
sumvv
=
sumyy
=
sumvy
=
0
for
v
,
y
in
zip
(
pv
,
ty
)
:
if
y
==
v
:
total_correct
+=
1
total_error
+=
(
v
y
)
*
(
v
y
)
sumv
+=
v
sumy
+=
y
sumvv
+=
v
*
v
sumyy
+=
y
*
y
sumvy
+=
v
*
y
l
=
len
(
ty
)
ACC
=
100.0
*
total_correct
/
l
MSE
=
total_error
/
l
try
:
SCC
=
(
(
l
*
sumvy
sumv
*
sumy
)
*
(
l
*
sumvy
sumv
*
sumy
)
)
/
(
(
l
*
sumvv
sumv
*
sumv
)
*
(
l
*
sumyy
sumy
*
sumy
)
)
except
:
SCC
=
float
(
'nan'
)
return
(
ACC
,
MSE
,
SCC
)


svm_train ( y x [ options ] ) - > model | ACC | MSE svm_train ( prob [ options ] ) - > model | ACC | MSE svm_train ( prob param ) - > model | ACC| MSE

def svm_train(arg1, arg2=None, arg3=None):
	"""
	svm_train(y, x [, options]) -> model | ACC | MSE
	svm_train(prob [, options]) -> model | ACC | MSE
	svm_train(prob, param) -> model | ACC| MSE

	Train an SVM model from data (y, x) or an svm_problem prob using
	'options' or an svm_parameter param.
	If '-v' is specified in 'options' (i.e., cross validation)
	either accuracy (ACC) or mean-squared error (MSE) is returned.
	options:
	    -s svm_type : set type of SVM (default 0)
	        0 -- C-SVC		(multi-class classification)
	        1 -- nu-SVC		(multi-class classification)
	        2 -- one-class SVM
	        3 -- epsilon-SVR	(regression)
	        4 -- nu-SVR		(regression)
	    -t kernel_type : set type of kernel function (default 2)
	        0 -- linear: u'*v
	        1 -- polynomial: (gamma*u'*v + coef0)^degree
	        2 -- radial basis function: exp(-gamma*|u-v|^2)
	        3 -- sigmoid: tanh(gamma*u'*v + coef0)
	        4 -- precomputed kernel (kernel values in training_set_file)
	    -d degree : set degree in kernel function (default 3)
	    -g gamma : set gamma in kernel function (default 1/num_features)
	    -r coef0 : set coef0 in kernel function (default 0)
	    -c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
	    -n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
	    -p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
	    -m cachesize : set cache memory size in MB (default 100)
	    -e epsilon : set tolerance of termination criterion (default 0.001)
	    -h shrinking : whether to use the shrinking heuristics, 0 or 1 (default 1)
	    -b probability_estimates : whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)
	    -wi weight : set the parameter C of class i to weight*C, for C-SVC (default 1)
	    -v n: n-fold cross validation mode
	    -q : quiet mode (no outputs)
	"""
	prob, param = None, None
	if isinstance(arg1, (list, tuple)):
		assert isinstance(arg2, (list, tuple))
		y, x, options = arg1, arg2, arg3
		param = svm_parameter(options)
		prob = svm_problem(y, x, isKernel=(param.kernel_type == PRECOMPUTED))
	elif isinstance(arg1, svm_problem):
		prob = arg1
		if isinstance(arg2, svm_parameter):
			param = arg2
		else:
			param = svm_parameter(arg2)
	if prob == None or param == None:
		raise TypeError("Wrong types for the arguments")

	if param.kernel_type == PRECOMPUTED:
		for xi in prob.x_space:
			idx, val = xi[0].index, xi[0].value
			if xi[0].index != 0:
				raise ValueError('Wrong input format: first column must be 0:sample_serial_number')
			if val <= 0 or val > prob.n:
				raise ValueError('Wrong input format: sample_serial_number out of range')

	if param.gamma == 0 and prob.n > 0:
		param.gamma = 1.0 / prob.n
	libsvm.svm_set_print_string_function(param.print_func)
	err_msg = libsvm.svm_check_parameter(prob, param)
	if err_msg:
		raise ValueError('Error: %s' % err_msg)

	if param.cross_validation:
		l, nr_fold = prob.l, param.nr_fold
		target = (c_double * l)()
		libsvm.svm_cross_validation(prob, param, nr_fold, target)
		ACC, MSE, SCC = evaluations(prob.y[:l], target[:l])
		if param.svm_type in [EPSILON_SVR, NU_SVR]:
			print("Cross Validation Mean squared error = %g" % MSE)
			print("Cross Validation Squared correlation coefficient = %g" % SCC)
			return MSE
		else:
			print("Cross Validation Accuracy = %g%%" % ACC)
			return ACC
	else:
		m = libsvm.svm_train(prob, param)
		m = toPyModel(m)

		# If prob is destroyed, data including SVs pointed by m can remain.
		m.x_space = prob.x_space
		return m


svm_predict ( y x m [ options ] ) - > ( p_labels p_acc p_vals )

def svm_predict(y, x, m, options=""):
	"""
	svm_predict(y, x, m [, options]) -> (p_labels, p_acc, p_vals)

	Predict data (y, x) with the SVM model m.
	options:
	    -b probability_estimates: whether to predict probability estimates,
	        0 or 1 (default 0); for one-class SVM only 0 is supported.
	    -q : quiet mode (no outputs).

	The return tuple contains
	p_labels: a list of predicted labels
	p_acc: a tuple including  accuracy (for classification), mean-squared
	       error, and squared correlation coefficient (for regression).
	p_vals: a list of decision values or probability estimates (if '-b 1'
	        is specified). If k is the number of classes, for decision values,
	        each element includes results of predicting k(k-1)/2 binary-class
	        SVMs. For probabilities, each element contains k values indicating
	        the probability that the testing instance is in each class.
	        Note that the order of classes here is the same as 'model.label'
	        field in the model structure.
	"""

	def info(s):
		print(s)

	predict_probability = 0
	argv = options.split()
	i = 0
	while i < len(argv):
		if argv[i] == '-b':
			i += 1
			predict_probability = int(argv[i])
		elif argv[i] == '-q':
			info = print_null
		else:
			raise ValueError("Wrong options")
		i+=1

	svm_type = m.get_svm_type()
	is_prob_model = m.is_probability_model()
	nr_class = m.get_nr_class()
	pred_labels = []
	pred_values = []

	if predict_probability:
		if not is_prob_model:
			raise ValueError("Model does not support probabiliy estimates")

		if svm_type in [NU_SVR, EPSILON_SVR]:
			info("Prob. model for test data: target value = predicted value + z,\n"
			"z: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma=%g" % m.get_svr_probability());
			nr_class = 0

		prob_estimates = (c_double * nr_class)()
		for xi in x:
			xi, idx = gen_svm_nodearray(xi, isKernel=(m.param.kernel_type == PRECOMPUTED))
			label = libsvm.svm_predict_probability(m, xi, prob_estimates)
			values = prob_estimates[:nr_class]
			pred_labels += [label]
			pred_values += [values]
	else:
		if is_prob_model:
			info("Model supports probability estimates, but disabled in predicton.")
		if svm_type in (ONE_CLASS, EPSILON_SVR, NU_SVC):
			nr_classifier = 1
		else:
			nr_classifier = nr_class*(nr_class-1)//2
		dec_values = (c_double * nr_classifier)()
		for xi in x:
			xi, idx = gen_svm_nodearray(xi, isKernel=(m.param.kernel_type == PRECOMPUTED))
			label = libsvm.svm_predict_values(m, xi, dec_values)
			if(nr_class == 1):
				values = [1]
			else:
				values = dec_values[:nr_classifier]
			pred_labels += [label]
			pred_values += [values]

	ACC, MSE, SCC = evaluations(y, pred_labels)
	l = len(y)
	if svm_type in [EPSILON_SVR, NU_SVR]:
		info("Mean squared error = %g (regression)" % MSE)
		info("Squared correlation coefficient = %g (regression)" % SCC)
	else:
		info("Accuracy = %g%% (%d/%d) (classification)" % (ACC, int(l*ACC/100), l))

	return pred_labels, (ACC, MSE, SCC), pred_values


Show a newly generated CAPTCHA of the given class . Default is the first class name given in Tests . __all__

def test(req, name=Tests.__all__[0]):
    """Show a newly generated CAPTCHA of the given class.
       Default is the first class name given in Tests.__all__
       """
    test = _getFactory(req).new(getattr(Tests, name))

    # Make a list of tests other than the one we're using
    others = []
    for t in Tests.__all__:
        if t != name:
            others.append('
%s
' % (t,t))
    others = "\n".join(others)

    return """

<title>PyCAPTCHA Example</title>

PyCAPTCHA Example (for mod_python)

  %s:
  %s

  <form action="solution" method="get">
    Enter the word shown:
    <input type="text" name="word"/>
    <input type="hidden" name="id" value="%s"/>
  </form>

Or try...

%s

""" % (test.__class__.__name__, test.__doc__, test.id, test.id, others)


def image(req, id):
    """Generate an image for the CAPTCHA with the given ID string"""
    test = _getFactory(req).get(id)
    if not test:
        raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
    req.content_type = "image/jpeg"
    test.render().save(req, "JPEG")
    return apache.OK

def image ( req , id ) : test = _getFactory ( req ) . get ( id ) if not test : raise apache . SERVER_RETURN , apache . HTTP_NOT_FOUND req . content_type = "image/jpeg" test . render ( ) . save ( req , "JPEG" ) return apache . OK


def solution(req, id, word):
    """Grade a CAPTCHA given a solution word"""
    test = _getFactory(req).get(id)
    if not test:
        raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND

    if not test.valid:
        # Invalid tests will always return False, to prevent
        # random trial-and-error attacks. This could be confusing to a user...
        result = "Test invalidated, try another test"
    elif test.testSolutions([word]):
        result = "Correct"
    else:
        result = "Incorrect"

    return """

<title>PyCAPTCHA Example</title>

PyCAPTCHA Example

%s

%s

You guessed: %s

Possible solutions: %s

Try again

""" % (test.__class__.__name__, test.id, result, word, ", ".join(test.solutions))


def read(self):
        """Read words from disk"""
        f = open(os.path.join(File.dataDir, "words", self.fileName))

        self.words = []
        for line in f.xreadlines():
            line = line.strip()
            if not line:
                continue
            if line[0] == '#':
                continue
            for word in line.split():
                if self.minLength is not None and len(word) < self.minLength:
                    continue
                if self.maxLength is not None and len(word) > self.maxLength:
                    continue
                self.words.append(word)

def read ( self ) : f = open ( os . path . join ( File . dataDir , "words" , self . fileName ) ) self . words = [ ] for line in f . xreadlines ( ) : line = line . strip ( ) if not line : continue if line [ 0 ] == '#' : continue for word in line . split ( ) : if self . minLength is not None and len ( word ) < self . minLength : continue if self . maxLength is not None and len ( word ) > self . maxLength : continue self . words . append ( word )


Pick a random word from the list reading it in if necessary

def pick(self):
        """Pick a random word from the list, reading it in if necessary"""
        if self.words is None:
            self.read()
        return random.choice(self.words)

def pick ( self ) : if self . words is None : self . read ( ) return random . choice ( self . words )


Test whether the given solutions are sufficient for this CAPTCHA . A given CAPTCHA can only be tested once after that it is invalid and always returns False . This makes random guessing much less effective .

def testSolutions(self, solutions):
        """Test whether the given solutions are sufficient for this CAPTCHA.
           A given CAPTCHA can only be tested once, after that it is invalid
           and always returns False. This makes random guessing much less effective.
           """
        if not self.valid:
            return False
        self.valid = False

        numCorrect = 0
        numIncorrect = 0

        for solution in solutions:
            if solution in self.solutions:
                numCorrect += 1
            else:
                numIncorrect += 1

        return numCorrect >= self.minCorrectSolutions and \
               numIncorrect <= self.maxIncorrectSolutions

def testSolutions ( self , solutions ) : if not self . valid : return False self . valid = False numCorrect = 0 numIncorrect = 0 for solution in solutions : if solution in self . solutions : numCorrect += 1 else : numIncorrect += 1 return numCorrect >= self . minCorrectSolutions and numIncorrect <= self . maxIncorrectSolutions


Create a new instance of our assigned BaseCaptcha subclass passing it any extra arguments we re given . This stores the result for later testing .

def new(self, cls, *args, **kwargs):
        """Create a new instance of our assigned BaseCaptcha subclass, passing
           it any extra arguments we're given. This stores the result for
           later testing.
           """
        self.clean()
        inst = cls(*args, **kwargs)
        self.storedInstances[inst.id] = inst
        return inst

def new ( self , cls , * args , * * kwargs ) : self . clean ( ) inst = cls ( * args , * * kwargs ) self . storedInstances [ inst . id ] = inst return inst


Retrieve the CAPTCHA with the given ID . If it s expired already this will return None . A typical web application will need to new () a CAPTCHA when generating an html page then get () it later when its images or sounds must be rendered .

def get(self, id):
        """Retrieve the CAPTCHA with the given ID. If it's expired already,
           this will return None. A typical web application will need to
           new() a CAPTCHA when generating an html page, then get() it later
           when its images or sounds must be rendered.
           """
        return self.storedInstances.get(id)

def get ( self , id ) : return self . storedInstances . get ( id )


def clean(self):
        """Removed expired tests"""
        expiredIds = []
        now = time.time()
        for inst in self.storedInstances.itervalues():
            if inst.creationTime + self.lifetime < now:
                expiredIds.append(inst.id)
        for id in expiredIds:
            del self.storedInstances[id]

def clean ( self ) : expiredIds = [ ] now = time . time ( ) for inst in self . storedInstances . itervalues ( ) : if inst . creationTime + self . lifetime < now : expiredIds . append ( inst . id ) for id in expiredIds : del self . storedInstances [ id ]


Test the given list of solutions against the BaseCaptcha instance created earlier with the given id . Returns True if the test passed False on failure . In either case the test is invalidated . Returns False in the case of an invalid id .

def test(self, id, solutions):
        """Test the given list of solutions against the BaseCaptcha instance
           created earlier with the given id. Returns True if the test passed,
           False on failure. In either case, the test is invalidated. Returns
           False in the case of an invalid id.
           """
        self.clean()
        inst = self.storedInstances.get(id)
        if not inst:
            return False
        result = inst.testSolutions(solutions)
        return result

def test ( self , id , solutions ) : self . clean ( ) inst = self . storedInstances . get ( id ) if not inst : return False result = inst . testSolutions ( solutions ) return result


def _checkExtension(self, name):
        """Check the file against our given list of extensions"""
        for ext in self.extensions:
            if name.endswith(ext):
                return True
        return False

def _checkExtension ( self , name ) : for ext in self . extensions : if name . endswith ( ext ) : return True return False


From our given file list find a list of full paths to files

def _findFullPaths(self):
        """From our given file list, find a list of full paths to files"""
        paths = []
        for name in self.fileList:
            path = os.path.join(dataDir, self.basePath, name)
            if os.path.isdir(path):
                for content in os.listdir(path):
                    if self._checkExtension(content):
                        paths.append(os.path.join(path, content))
            else:
                paths.append(path)
        return paths

def _findFullPaths ( self ) : paths = [ ] for name in self . fileList : path = os . path . join ( dataDir , self . basePath , name ) if os . path . isdir ( path ) : for content in os . listdir ( path ) : if self . _checkExtension ( content ) : paths . append ( os . path . join ( path , content ) ) else : paths . append ( path ) return paths


Get a PIL image representing this CAPTCHA test creating it if necessary

def getImage(self):
        """Get a PIL image representing this CAPTCHA test, creating it if necessary"""
        if not self._image:
            self._image = self.render()
        return self._image

def getImage ( self ) : if not self . _image : self . _image = self . render ( ) return self . _image


Subclasses must override this to return a list of Layer instances to render . Lists within the list of layers are recursively rendered .

def getLayers(self):
        """Subclasses must override this to return a list of Layer instances to render.
           Lists within the list of layers are recursively rendered.
           """
        return []


Render this CAPTCHA returning a PIL image

def render(self, size=None):
        """Render this CAPTCHA, returning a PIL image"""
        if size is None:
            size = self.defaultSize
        img = Image.new("RGB", size)
        return self._renderList(self._layers, Image.new("RGB", size))

def render ( self , size = None ) : if size is None : size = self . defaultSize img = Image . new ( "RGB" , size ) return self . _renderList ( self . _layers , Image . new ( "RGB" , size ) )


Returns a ( fileName size ) tuple that can be passed to ImageFont . truetype ()

def pick(self):
        """Returns a (fileName, size) tuple that can be passed to ImageFont.truetype()"""
        fileName = File.RandomFileFactory.pick(self)
        size = int(random.uniform(self.minSize, self.maxSize) + 0.5)
        return (fileName, size)

def pick ( self ) : fileName = File . RandomFileFactory . pick ( self ) size = int ( random . uniform ( self . minSize , self . maxSize ) + 0.5 ) return ( fileName , size )


Return a transformation function subclasses should override this

def getTransform(self, image):
        """Return a transformation function, subclasses should override this"""
        return lambda x, y: (x, y)

def getTransform ( self , image ) : return lambda x , y : ( x , y )


Print msg to stdout if the global DEBUG ( taken from the DISTUTILS_DEBUG environment variable ) flag is true .

def debug_print (self, msg):
        """Print 'msg' to stdout if the global DEBUG (taken from the
        DISTUTILS_DEBUG environment variable) flag is true.
        """
        from distutils.core import DEBUG
        if DEBUG:
            print msg

def debug_print ( self , msg ) : from distutils . core import DEBUG if DEBUG : print msg


def finalize(self):
        """ complete the files list by processing the given template """
        if self.finalized:
            return
        if self.files == None:
            self.files = []
        if self.template != None:
            if type(self.template) == StringType:
                self.template = string.split(self.template,";")
            filelist = FileList(self.warn,self.debug_print)
            for line in self.template:
                filelist.process_template_line(string.strip(line))
            filelist.sort()
            filelist.remove_duplicates()
            self.files.extend(filelist.files)
        self.finalized = 1

def finalize ( self ) : if self . finalized : return if self . files == None : self . files = [ ] if self . template != None : if type ( self . template ) == StringType : self . template = string . split ( self . template , ";" ) filelist = FileList ( self . warn , self . debug_print ) for line in self . template : filelist . process_template_line ( string . strip ( line ) ) filelist . sort ( ) filelist . remove_duplicates ( ) self . files . extend ( filelist . files ) self . finalized = 1


check if data are in new format if not create a suitable object . returns finalized data object

def check_data(self,d):
        """ check if data are in new format, if not create a suitable object.
            returns finalized data object
        """
        if not isinstance(d, Data_Files):
            self.warn(("old-style data files list found "
                        "-- please convert to Data_Files instance"))
            if type(d) is TupleType:
                if len(d) != 2 or  not (type(d[1]) is ListType):
                        raise DistutilsSetupError, \
                          ("each element of 'data_files' option must be an "
                            "Data File instance, a string or 2-tuple (string,[strings])")
                d = Data_Files(copy_to=d[0],files=d[1])
            else:
                if not (type(d) is StringType):
                        raise DistutilsSetupError, \
                          ("each element of 'data_files' option must be an "
                           "Data File instance, a string or 2-tuple (string,[strings])")
                d = Data_Files(files=[d])
        d.finalize()
        return d


Returns a string which should be placed as a hidden field on a web form . This string identifies a particular challenge and is needed later for : - retrieving the image file for viewing the challenge via call to getImageData () - testing a response to the challenge via call to testSolution ()

def getChallenge():
    """
    Returns a string, which should be placed as a hidden field
    on a web form. This string identifies a particular challenge,
    and is needed later for:
        - retrieving the image file for viewing the challenge, via
          call to getImageData()
        - testing a response to the challenge, via call to testSolution()

    The format of the string is::

        base64(id+":"+expirytime+":"+sha1(id, answer, expirytime, secret))

    Where:
        - id is a pseudo-random id identifying this challenge instance, and
          used to locate the temporary file under which the image is stored
        - expirytime is unixtime in hex
        - answer is the plaintext string of the word on the challenge picture
        - secret is the secret signing key 'captchaSecretKey
    """
    # get a CAPTCHA object
    g = PseudoGimpy()

    # retrieve text solution
    answer = g.solutions[0]

    # generate a unique id under which to save it
    id = _generateId(answer)

    # save the image to disk, so it can be delivered from the
    # browser's next request
    i = g.render()
    path = _getImagePath(id)
    f = file(path, "wb")
    i.save(f, "jpeg")
    f.close()

    # compute 'key'
    key = _encodeKey(id, answer)
    return key


def testSolution(key, guess):
    """
    Tests if guess is a correct solution
    """
    try:
        id, expiry, sig = _decodeKey(key)

        # test for timeout
        if time.time() > expiry:
            # sorry, timed out, too late
            _delImage(id)
            return False

        # test for past usage of this key

        path = _getImagePath(id)
        if not os.path.isfile(path):
            # no such key, fail out
            return False

        # test for correct word
        if _signChallenge(id, guess, expiry) != sig:
            # sorry, wrong word
            return False

        # successful
        _delImage(id) # image no longer needed
        return True
    except:
        #traceback.print_exc()
        return False

def
testSolution
(
key
,
guess
)
:
try
:
id
,
expiry
,
sig
=
_decodeKey
(
key
)
# test for timeout
if
time
.
time
(
)
>
expiry
:
# sorry, timed out, too late
_delImage
(
id
)
return
False
# test for past usage of this key
path
=
_getImagePath
(
id
)
if
not
os
.
path
.
isfile
(
path
)
:
# no such key, fail out
return
False
# test for correct word
if
_signChallenge
(
id
,
guess
,
expiry
)
!=
sig
:
# sorry, wrong word
return
False
# successful
_delImage
(
id
)
# image no longer needed
return
True
except
:
#traceback.print_exc()
return
False


def _encodeKey(id, answer):
    """
    Encodes the challenge ID and the answer into a string which is safe
    to give to a potentially hostile client

    The key is base64-encoding of 'id:expirytime:answer'
    """
    expiryTime = int(time.time() + captchaTimeout)
    sig = _signChallenge(id, answer, expiryTime)
    raw = "%s:%x:%s" % (id, expiryTime, sig)
    key = base64.encodestring(raw).replace("\n", "")
    return key

def _encodeKey ( id , answer ) : expiryTime = int ( time . time ( ) + captchaTimeout ) sig = _signChallenge ( id , answer , expiryTime ) raw = "%s:%x:%s" % ( id , expiryTime , sig ) key = base64 . encodestring ( raw ) . replace ( "\n" , "" ) return key


decodes a given key returns id expiry time and signature

def _decodeKey(key):
    """
    decodes a given key, returns id, expiry time and signature
    """
    raw = base64.decodestring(key)
    id, expiry, sig = raw.split(":", 2)
    expiry = int(expiry, 16)
    return id, expiry, sig

def _decodeKey ( key ) : raw = base64 . decodestring ( key ) id , expiry , sig = raw . split ( ":" , 2 ) expiry = int ( expiry , 16 ) return id , expiry , sig


returns a pseudo - random id under which picture gets stored

def _generateId(solution):
    """
    returns a pseudo-random id under which picture
    gets stored
    """
    return sha.new(
        "%s%s%s" % (
            captchaSecretKey, solution, random.random())).hexdigest()[:10]

def _generateId ( solution ) : return sha . new ( "%s%s%s" % ( captchaSecretKey , solution , random . random ( ) ) ) . hexdigest ( ) [ : 10 ]


deletes image from tmp dir no longer wanted

def _delImage(id):
    """
    deletes image from tmp dir, no longer wanted
    """
    try:
        imgPath = _getImagePath(id)
        if os.path.isfile(imgPath):
            os.unlink(imgPath)
    except:
        traceback.print_exc()
        pass

def _delImage ( id ) : try : imgPath = _getImagePath ( id ) if os . path . isfile ( imgPath ) : os . unlink ( imgPath ) except : traceback . print_exc ( ) pass


Presents a demo of this captcha module . If you run this file as a CGI in your web server you ll see the demo in action

def _demo():
    """
    Presents a demo of this captcha module.

    If you run this file as a CGI in your web server, you'll see the demo
    in action
    """
    import cgi
    fields = cgi.FieldStorage()
    cmd = fields.getvalue("cmd", "")

    if not cmd:
        # first view
        key = getChallenge()
        print """Content-Type: text/html

  <title>ezcaptcha demo</title>

ezcaptcha demo

  <form method="POST">
   <input type="hidden" name="cmd" value="answerCaptcha">
   <input type="hidden" name="captchaKey" value="%s">

   Please type in the word you see in the image above:

   <input type="text" name="captchaAnswer">

   <input type="submit" value="Submit">
  </form>

""" % (key, key)

    elif cmd == 'showCaptchaImg':
        # answer browser request for the CAPTCHA challenge image
        key = fields.getvalue("captchaKey")
        bindata = getImageData(key)
        print "Content-Type: image/jpeg"
        print
        print bindata

    elif cmd == 'answerCaptcha':
        # user has posted in an answer
        key = fields.getvalue("captchaKey")
        guess = fields.getvalue("captchaAnswer")

        # test user's answer
        if testSolution(key, guess) == True:
            # successful
            print """Content-Type: text/html

  <title>ezcaptcha demo</title>

ezcaptcha demo

  Successful!

  Click here for another demo

"""

        else:
            # failed
            print """Content-Type: text/html

  <title>ezcaptcha demo</title>

ezcaptcha demo

  Sorry - that was wrong!
  <form method="POST">
   <input type="hidden" name="cmd" value="answerCaptcha">
   <input type="hidden" name="captchaKey" value="%s">

   Please type in the word you see in the image above:

   <input type="text" name="captchaAnswer">

   <input type="submit" value="Submit">
  </form>

""" % (key, key)


def read(self):
        """Read words from disk"""
        f = open(os.path.join(File.dataDir, "words", self.fileName))

        self.words = []
        for line in f.xreadlines():
            line = line.strip()
            if not line:
                continue
            if line[0] == '#':
                continue
            for word in line.split():
                if self.minLength is not None and len(word) < self.minLength:
                    continue
                if self.maxLength is not None and len(word) > self.maxLength:
                    continue
                self.words.append(word)

def read ( self ) : f = open ( os . path . join ( File . dataDir , "words" , self . fileName ) ) self . words = [ ] for line in f . xreadlines ( ) : line = line . strip ( ) if not line : continue if line [ 0 ] == '#' : continue for word in line . split ( ) : if self . minLength is not None and len ( word ) < self . minLength : continue if self . maxLength is not None and len ( word ) > self . maxLength : continue self . words . append ( word )


Pick a random word from the list reading it in if necessary

def pick(self):
        """Pick a random word from the list, reading it in if necessary"""
        if self.words is None:
            self.read()
        return random.choice(self.words)

def pick ( self ) : if self . words is None : self . read ( ) return random . choice ( self . words )


Test whether the given solutions are sufficient for this CAPTCHA . A given CAPTCHA can only be tested once after that it is invalid and always returns False . This makes random guessing much less effective .

def testSolutions(self, solutions):
        """Test whether the given solutions are sufficient for this CAPTCHA.
           A given CAPTCHA can only be tested once, after that it is invalid
           and always returns False. This makes random guessing much less effective.
           """
        if not self.valid:
            return False
        self.valid = False

        numCorrect = 0
        numIncorrect = 0

        for solution in solutions:
            if solution in self.solutions:
                numCorrect += 1
            else:
                numIncorrect += 1

        return numCorrect >= self.minCorrectSolutions and \
               numIncorrect <= self.maxIncorrectSolutions

def testSolutions ( self , solutions ) : if not self . valid : return False self . valid = False numCorrect = 0 numIncorrect = 0 for solution in solutions : if solution in self . solutions : numCorrect += 1 else : numIncorrect += 1 return numCorrect >= self . minCorrectSolutions and numIncorrect <= self . maxIncorrectSolutions


Create a new instance of our assigned BaseCaptcha subclass passing it any extra arguments we re given . This stores the result for later testing .

def new(self, cls, *args, **kwargs):
        """Create a new instance of our assigned BaseCaptcha subclass, passing
           it any extra arguments we're given. This stores the result for
           later testing.
           """
        self.clean()
        inst = cls(*args, **kwargs)
        self.storedInstances[inst.id] = inst
        return inst

def new ( self , cls , * args , * * kwargs ) : self . clean ( ) inst = cls ( * args , * * kwargs ) self . storedInstances [ inst . id ] = inst return inst


Retrieve the CAPTCHA with the given ID . If it s expired already this will return None . A typical web application will need to new () a CAPTCHA when generating an html page then get () it later when its images or sounds must be rendered .

def get(self, id):
        """Retrieve the CAPTCHA with the given ID. If it's expired already,
           this will return None. A typical web application will need to
           new() a CAPTCHA when generating an html page, then get() it later
           when its images or sounds must be rendered.
           """
        return self.storedInstances.get(id)

def get ( self , id ) : return self . storedInstances . get ( id )


def clean(self):
        """Removed expired tests"""
        expiredIds = []
        now = time.time()
        for inst in self.storedInstances.itervalues():
            if inst.creationTime + self.lifetime < now:
                expiredIds.append(inst.id)
        for id in expiredIds:
            del self.storedInstances[id]

def clean ( self ) : expiredIds = [ ] now = time . time ( ) for inst in self . storedInstances . itervalues ( ) : if inst . creationTime + self . lifetime < now : expiredIds . append ( inst . id ) for id in expiredIds : del self . storedInstances [ id ]


Test the given list of solutions against the BaseCaptcha instance created earlier with the given id . Returns True if the test passed False on failure . In either case the test is invalidated . Returns False in the case of an invalid id .

def test(self, id, solutions):
        """Test the given list of solutions against the BaseCaptcha instance
           created earlier with the given id. Returns True if the test passed,
           False on failure. In either case, the test is invalidated. Returns
           False in the case of an invalid id.
           """
        self.clean()
        inst = self.storedInstances.get(id)
        if not inst:
            return False
        result = inst.testSolutions(solutions)
        return result

def test ( self , id , solutions ) : self . clean ( ) inst = self . storedInstances . get ( id ) if not inst : return False result = inst . testSolutions ( solutions ) return result


def _checkExtension(self, name):
        """Check the file against our given list of extensions"""
        for ext in self.extensions:
            if name.endswith(ext):
                return True
        return False

def _checkExtension ( self , name ) : for ext in self . extensions : if name . endswith ( ext ) : return True return False


From our given file list find a list of full paths to files

def _findFullPaths(self):
        """From our given file list, find a list of full paths to files"""
        paths = []
        for name in self.fileList:
            path = os.path.join(dataDir, self.basePath, name)
            if os.path.isdir(path):
                for content in os.listdir(path):
                    if self._checkExtension(content):
                        paths.append(os.path.join(path, content))
            else:
                paths.append(path)
        return paths

def _findFullPaths ( self ) : paths = [ ] for name in self . fileList : path = os . path . join ( dataDir , self . basePath , name ) if os . path . isdir ( path ) : for content in os . listdir ( path ) : if self . _checkExtension ( content ) : paths . append ( os . path . join ( path , content ) ) else : paths . append ( path ) return paths


Get a PIL image representing this CAPTCHA test creating it if necessary

def getImage(self):
        """Get a PIL image representing this CAPTCHA test, creating it if necessary"""
        if not self._image:
            self._image = self.render()
        return self._image

def getImage ( self ) : if not self . _image : self . _image = self . render ( ) return self . _image


Subclasses must override this to return a list of Layer instances to render . Lists within the list of layers are recursively rendered .

def getLayers(self):
        """Subclasses must override this to return a list of Layer instances to render.
           Lists within the list of layers are recursively rendered.
           """
        return []


Render this CAPTCHA returning a PIL image

def render(self, size=None):
        """Render this CAPTCHA, returning a PIL image"""
        if size is None:
            size = self.defaultSize
        img = Image.new("RGB", size)
        return self._renderList(self._layers, Image.new("RGB", size))

def render ( self , size = None ) : if size is None : size = self . defaultSize img = Image . new ( "RGB" , size ) return self . _renderList ( self . _layers , Image . new ( "RGB" , size ) )


Returns a ( fileName size ) tuple that can be passed to ImageFont . truetype ()

def pick(self):
        """Returns a (fileName, size) tuple that can be passed to ImageFont.truetype()"""
        fileName = File.RandomFileFactory.pick(self)
        size = int(random.uniform(self.minSize, self.maxSize) + 0.5)
        return (fileName, size)

def pick ( self ) : fileName = File . RandomFileFactory . pick ( self ) size = int ( random . uniform ( self . minSize , self . maxSize ) + 0.5 ) return ( fileName , size )


Return a transformation function subclasses should override this

def getTransform(self, image):
        """Return a transformation function, subclasses should override this"""
        return lambda x, y: (x, y)

def getTransform ( self , image ) : return lambda x , y : ( x , y )