The answer depends somewhat on what finite element space you are using for velocity.
---
If you are using a CG/DG VectorFunctionSpace, it's possible to impose BCs strongly that set one cartesian component to 0.  I think you access this by doing, e.g., DirichletBC(V.sub(0), 0, (1,)).  This has the limitation that you mentioned (i.e. it only works if that boundary is axis-aligned).
(Note: The code snippet you posted is setting both components of velocity, not just the normal component)
An alternative is to impose the boundary condition weakly.  I think this is as simple as adding a dot(v, n)*dot(u, n)*ds term to your equation, where v is a test function from the same space as u.  This is equivalent to saying "integral of gamma * u.n over the boundary = 0" for all appropriate test functions gamma, which is clearly a weak version of u.n = 0.
This works for arbitrary geometry.
(And if your velocity field is DG then you should be imposing the BC weakly anyway, according to the FE experts on the list!)
---
Finally, if you are using a vector-valued finite element space, e.g. an RT or BDM FunctionSpace, you can set no-normal flow BCs strongly with DirichletBC(V, 0, (1, 2, 3, 4)).  This sets the boundary degrees of freedom to 0, and the boundary degrees of freedom precisely represent the normal flow velocity due to the way the FE space is defined [actually, it's scaled so I think it's a flux rather than a velocity, but scaled 0 is still 0].
Again, this works for arbitrary geometry.
---
Hopefully one of these is suitable (imposing the BC weakly should always work).