Here’s a simple starter script, just add logic.

```
#BPYCONSTRAINT
'''
PyConstraint template, access this in the "add constraint" scripts submenu.
Add docstring here
'''
import Blender
from Blender import Mathutils
'''
This variable specifies the number of targets
that this constraint can use
'''
NUM_TARGETS = 1
'''
This function is called to evaluate the constraint
obmatrix: (Matrix) copy of owner's 'ownerspace' matrix
targetmatrices: (List) list of copies of the 'targetspace' matrices of the targets (where applicable)
idprop: (IDProperties) wrapped data referring to this
constraint instance's idproperties
'''
def doConstraint(obmatrix, targetmatrices, idprop):
# Separate out the tranformation components for easy access.
obloc = obmatrix.translationPart() # Translation
obrot = obmatrix.toEuler() # Rotation
obsca = obmatrix.scalePart() # Scale
print obrot
# add logic here :)
# Check rot here
#if idprop['u_rot'] == 1:
# obrot[0] += ra*rv[0]
# obrot[1] += ra*rv[1]
# obrot[2] += ra*rv[2]
mtxloc = Mathutils.TranslationMatrix( obloc )
mtxrot = obrot.toMatrix().resize4x4()
mtxsca = Mathutils.Matrix([obsca[0],0,0,0], [0,obsca[1],0,0], [0,0,obsca[2],0], [0,0,0,1])
outputmatrix = mtxsca * mtxrot * mtxloc
# Return the new matrix.
return outputmatrix
'''
This function manipulates the matrix of a target prior to sending it to doConstraint()
target_object: wrapped data, representing the target object
subtarget_bone: wrapped data, representing the subtarget pose-bone/vertex-group (where applicable)
target_matrix: (Matrix) the transformation matrix of the target
id_properties_of_constraint: (IDProperties) wrapped idproperties
'''
def doTarget(target_object, subtarget_bone, target_matrix, id_properties_of_constraint):
return target_matrix
'''
This function draws a pupblock that lets the user set
the values of custom settings the constraint defines.
This function is called when the user presses the settings button.
idprop: (IDProperties) wrapped data referring to this
constraint instance's idproperties
'''
def getSettings(idprop):
return None
```

<edit>

In case you are wondering how to handle the logic, you could perhaps put it this way:

- figure out how to convert current rotation to a sum of X and Z rotations. ie. rotate first in Z and then in X (hint: Y rotation is 0 in this case, perhaps that helps)
- check X rotation and clamp it if needed</edit>