Does "code smell" just mean "style I don't like"? Most of your concerns have nothing to do with what the code is actually doing.
Line 43-55 is the scrutinee (pattern) of the case statement. It only binds values to the given variables and enters the block if `node` matches the quite complex structure shown there.
The alternative would be doing something repetitive like this:
if not isinstance(node, WithStmt):
return
expr = node.expr
if not len(expr) == 1:
return
if not isinstance(expr, CallExpr):
return
callee = expr.callee
if not (isinstance(callee, NameExpr) and callee.name == 'open'):
return
... etc ...
You could do the same thing with duck typing and try/except, but the semantics would be different (sometimes you DO want nominal typing, even in python).