# Adding a driver to the tilt attribute of a bezier curve to link it to a hook using a python script

I started using blender and python a couple weeks ago, and have been doing okay with the documentation that is available on the internet. Now I ran into a problem though. I am trying use a hook as a way of animating a bar that is able to flex in different directions. In order to achieve this I am able to add a hook to either control point of the MidLine curve, but that only controls the location, and rotation in Y and Z-axis, so I have to add a driver to the tilt (rotation around the X-axis). Here you can see what I managed to achieve for one leaf spring without scripting, but now the leaf spring has to be animated from inputs that will be provided in a list.

So the problem is as follows: I have the hook, and control point, but how do I add a driver to the tilt attribute of this control point (see red arrow in the picture)? I was easily able to do it manually, but I can't seem to find the proper syntax for accessing this feature with python... Here is a picture of what I want the driver to look like for clarification:

When I first do it manually, and then copy the following info window lines into my script it doesn't work:

bpy.context.object.data.id = bpy.data.objects["Control Point 1"]
bpy.context.object.data.transform_type = 'ROT_X'
bpy.context.object.data.rotation_mode = 'QUATERNION'


I also looked around a bunch online, but the documentation didn't make it clear enough for me. I feel the code below is as close as I got. I also included the rest of the code that gets you to the same blender workspace.

# IMPORT LIBRARIES
import bpy
import csv
from os import system

# CLEAR CONSOLE
cls = lambda: system('cls')
cls()

width = 1
thickness = 0.2

CrossSection = bpy.data.curves.new('Cross Section Curve', type='CURVE')
CrossSection.dimensions = '3D'
CrossSection.resolution_u = 12

polyline = CrossSection.splines.new('POLY')
polyline.points[0].co = (-width/2, thickness/2, 0, 1)
polyline.points[1].co = (-width/2, -thickness/2, 0, 1)
polyline.points[2].co = (width/2, -thickness/2, 0, 1)
polyline.points[3].co = (width/2, thickness/2, 0, 1)

# Create Object
curveOB = bpy.data.objects.new('Cross Section', CrossSection)

# Attach to scene

# Select object and set it to cyclic
bpy.data.objects["Cross Section"].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects['Cross Section']
bpy.ops.object.editmode_toggle()
bpy.ops.curve.select_all(action='SELECT')
bpy.ops.curve.cyclic_toggle()
bpy.ops.object.editmode_toggle()
bpy.ops.object.select_all(action='DESELECT')

# INITIALIZE UNIT MIDLINE NEXT
MidLine = bpy.data.curves.new('MidLine Curve', type='CURVE')
MidLine.dimensions = '3D'
MidLine.resolution_u = 12

polyline = MidLine.splines.new('BEZIER')
print(len(polyline.bezier_points))

polyline.bezier_points[0].handle_left = (-1, 0, 0)
polyline.bezier_points[0].handle_right = (1, 0, 0)
polyline.bezier_points[0].co = (0, 0, 0)

polyline.bezier_points[1].handle_left = (3-1, 0, 0)
polyline.bezier_points[1].handle_right = (3+1, 0, 0)
polyline.bezier_points[1].co = (3, 0, 0)

# Create Object
curveOB = bpy.data.objects.new('MidLine', MidLine)

# Attach to scene and validate context

# Select object and assign the cross section bevel
bpy.data.objects["MidLine"].select_set(True)
bpy.context.view_layer.objects.active = bpy.data.objects['MidLine']
bpy.ops.object.editmode_toggle()
bpy.ops.curve.select_all(action='SELECT')
bpy.context.object.data.bevel_mode = 'OBJECT'
bpy.context.object.data.bevel_object = bpy.data.objects["Cross Section"]
bpy.context.object.data.splines[0].use_smooth = False
bpy.context.object.data.use_fill_caps = True
bpy.ops.curve.select_all(action='DESELECT')
#bpy.ops.object.editmode_toggle()
#bpy.ops.object.select_all(action='DESELECT')

# CREATE THE HOOKS AND LINK THEM TO THE CONTROL POINTS
# Control point 1
bpy.context.active_object.data.splines[0].bezier_points[0].select_control_point = True
bpy.data.objects['Empty'].name = "Control Point 1"
#The following were attempts that also don't work:

Hopefully someone is able to clarify how to use these drivers with bpy. It is probably a lot easier for adding drivers to simple cubes, but this niche part of blender is quite ... well niche :P. I feel the documentation could be much easier to understand if some examples of how to use the syntax were included, by the way. I think the bpy_struct (bpy_struct), also could be of use, but I just don't understand how. Furthermore, for reference, here is a link to the question where I learned of the trick to add a driver to use a hook to control a bezier point.