If you are willing to fabricate a mesh by specifying the vertices and faces, it is relatively straightforward to use from_pydata(v,e,f). The hard part is imagining the math to make your vertices and faces accomplish the look you are targeting.
There are many examples available on the internet, but here are two links: triangle donut; bathymetry
and a copy of the triangle donut code in case the internet is broken:
import bpy
import math
def triangleDonut(name, nChunks, r1, r2, z1, z2):
verts=[]
faces = []
for i in range(2*nChunks):
v1=i*3
v2 = v1+1
v3 = v1+2
v4 = v1+3
v5 = v1+4
v6 = v1+5
if (i+1 >= 2*nChunks): # connect the end to the start
v4=0
v5=1
v6=2
theta = i*math.pi/nChunks
if 0 == i%2:
z=z1
else:
z=z2
c = math.cos(theta)
s = math.sin(theta)
verts.append( [r1*c, r1*s, 0] )
verts.append( [r2*c, r2*s, z] )
verts.append( [r2*c, r2*s, -z] )
faces.append( [v1, v4, v5, v2] )
faces.append( [v2, v5, v6, v3] )
faces.append( [v3, v6, v4, v1] )
mesh = bpy.data.meshes.new(name);
mesh.from_pydata(verts, [], faces)
mesh.validate(True)
mesh.show_normal_face = True
obj = bpy.data.objects.new(name, mesh)
scn = bpy.context.scene
scn.objects.link(obj)
triangleDonut("donut", 20, 3, 2, 1,1.5)