You want to avoid duplicates though. Here’s a simple recursive solution. It takes a list and creates pairs between the first element and the rest. Then it calls the same function but with the first element of the list removed. Continue this until everything is paired. Just copy/paste and run in empty scene. If you want to reuse existing object, you can uncomment the part that says uncomment if…

```
import bpy
from mathutils import Vector
from random import uniform
def pairsByDist(points,dist,pairs=[]):
if len(points)==0: return pairs
a,*remaining = points #neat trick to split the first element off the list
newPairs=[(a[0],b[0]) for b in remaining if (b[1]-a[1]).length<=dist] #collect with distance filter (the if)
return pairsByDist(remaining,dist,pairs+newPairs)
#p0 and p1 can be tuples,lists or vectors
def randGrid(p0,p1,n):
return [Vector([uniform(a,b) for a,b in zip(p0,p1)])
for i in range(0,n)]
#generate random set of points in given bounds
gridPoints=randGrid((-4,-4,-4),(4,4,4),200)
#uncomment if you wish to reuse existing object as source points (rename it accordingly)
#srcMesh = bpy.data.objects['sourceobj'].data
#gridPoints=[p.co for p in srcMesh.vertices]
#bundle with point indices as (id,points) tuples. (force to a list)
grid=list(enumerate(gridPoints))
# get list of pairs as (id1,id2) tuples
edges=pairsByDist(grid,1.5)
#create new mesh object
me = bpy.data.meshes.new('grid')
ob = bpy.data.objects.new('grid', me)
bpy.context.scene.objects.link(ob)
me.from_pydata(gridPoints, edges, []) #convert the python data to mesh data
me.update(calc_edges=True)
```