Python 2.8 - transform/resize UV map instead of object I am trying to replicate with scripts a manual procedure that works well.

Using Smart UV project manually, my object stretches the texture too much; I have found that if I resize the UV map (scale up the Y axis), the distortion disappears.

I have taken the python commands from the manual procedure and dropped them into the script.  The only problem is that instead of resizing the UV map, the script resizes the object.  I think I need to keep the vertices in the UV map selected while deselecting the mesh vertices; but I have not figured out how to do that.  

Question:  how can I make sure that the following code resizes the UV map instead of the object?

The code should work if cut-and-pasted; the texture can be downloaded here; to run the code you will need to change the pointer to the file in this line 'imgTex = bpy.data.images.load(...'

import bpy

bpy.ops.mesh.primitive_cylinder_add(vertices=32, radius=0.2, depth=30, enter_editmode=False, location=(0,0,0))

materials = bpy.data.materials
material = materials.get('mat')
if not material:
    material = materials.new('mat')
material.use_nodes = True
if material.node_tree:
    material.node_tree.links.clear()
    material.node_tree.nodes.clear()
nodes = material.node_tree.nodes
links = material.node_tree.links
output = nodes.new(type = 'ShaderNodeOutputMaterial' )
diffuse = nodes.new(type = 'ShaderNodeBsdfDiffuse' )
imgTex = bpy.data.images.load('G:\\Blender\\Textures\\wildtextures-zinc-galvanized-metal-sheet.jpg')
node_texture = nodes.new(type='ShaderNodeTexImage')
node_texture.image = imgTex
node_texture.location = 0,200    
tex_coord = nodes.new(type = 'ShaderNodeTexCoord')
links = material.node_tree.links
link=links.new(tex_coord.outputs["UV"], node_texture.inputs["Vector"]) 
link = links.new(node_texture.outputs[0], nodes.get('Diffuse BSDF').inputs[0])
link = links.new( diffuse.outputs['BSDF'], output.inputs['Surface'] )
obj=bpy.data.objects['Cylinder']
obj.active_material=material
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects['Cylinder'].select_set(True)
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.smart_project()

#AT THIS POINT THE TEXTURE HAS BEEN APPLIED
#BUT LOOKS DISTORTED DUE TO CYLINDER'S GEOMETRY;
#THE FOLLOWING ATTEMPTS TO UNDISTORT BY SCALING
#UP THE UVMAP ON THE Y-AXIS; BUT INSTEAD
#IT SIMPLY SCALES UP THE OBJECT INSTEAD
bpy.ops.uv.select_all(action='SELECT')
bpy.ops.transform.resize(value=(1, 30, 1), orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=100, use_proportional_connected=False, use_proportional_projected=False)
bpy.ops.object.mode_set(mode='OBJECT')
Use the right context

The issue here, as often with operators, is context.  .  If Transfrom resize  is run in the context of the UV editor it resizes the selected UVs, if run in the dopesheet scales the selected keyframes, ..., otherwise (or if run from 3dview) it defaults back to the object or the mesh.

Depending on how you are going to invoke your code, may need to override the context such that the operator "thinks" it was invoked in, in this case,  the UV area.  (Like pressing a button in that area)

Some python console test code

Areas in my current screen, area 2 is the image editor. 

&gt;&gt;&gt; for i, a in enumerate(C.screen.areas):
...     i, a.type
...     
(0, 'PROPERTIES')
(1, 'OUTLINER')
(2, 'IMAGE_EDITOR')
(3, 'VIEW_3D')
(4, 'CONSOLE')

&gt;&gt;&gt; ie = C.screen.areas[2]


The mesh is in edit mode with all faces selected. Running the operator like so scales my mesh.

&gt;&gt;&gt; bpy.ops.transform.resize(value=(1, 2, 1))
{'FINISHED'}


If I override context.area such that it is the image editor from above, it scales the UV.

&gt;&gt;&gt; bpy.ops.transform.resize({"area" : ie}, value=(1, 2, 1))
{'FINISHED'}


Related

poll() failed, context incorrect? - Example: bpy.ops.view3d.background_image_add()

Without the operator

From the text editor template templates &gt; python &gt; Operator mesh UV can scale the uv coordinates directly.

    uv_layer = bm.loops.layers.uv.verify()

    # adjust uv coordinates

    S = Matrix.Diagonal((1, 2)) # scale matrix

    for face in bm.faces:
        for loop in face.loops:
            loop_uv = loop[uv_layer]
            # use matrix to scale uv by 2 in y
            loop_uv.uv @= S