This resolves #1589. It updates the MRO for PyProxy: now `proxy.destroy` always refers to the method PyProxy class method that destroys the proxy, `proxy.$destroy` refers to an attribute or method on the proxied Python object. Similarly, `proxy.get` refers to the `PyProxy.get` method if `type(proxy)` has a `__getitem__` method. Otherwise, it refers to an attribute or method on the proxied object. To unambigiously look up `get` on the proxied object, use `proxy.$get`.

The docs should be updated to explain this.
ENH Use leading $ to distinguish shadowed PyProxy methods. This resolves #1589. It updates the MRO for PyProxy: now `proxy.destroy` always refers to the method PyProxy class method that destroys the proxy, `proxy.$destroy` refers to an attribute or method on the proxied Python object. Similarly, `proxy.get` refers to the `PyProxy.get` method if `type(proxy)` has a `__getitem__` method. Otherwise, it refers to an attribute or method on the proxied object. To unambigiously look up `get` on the proxied object, use `proxy.$get`.

The docs should be updated to explain this.
# setup: import numpy as np ; N = 50 ; X, Y = np.random.randn(100,N), np.random.randn(40,N)  # noqa
# run: allpairs_distances(X, Y)

# pythran export allpairs_distances(float64[][], float64[][])
import numpy as np


def allpairs_distances(A, B):
    """This returns the euclidean distances squared
    dist2(x, y) = dot(x, x) - 2 * dot(x, y) + dot(y, y)
    """
    A2 = np.einsum("ij,ij->i", A, A)
    B2 = np.einsum("ij,ij->i", B, B)
    return A2[:, None] + B2[None, :] - 2 * np.dot(A, B.T)

# setup: import numpy as np ; N = 50 ; X, Y = np.random.randn(100,N), np.random.randn(40,N)  # noqa
# run: allpairs_distances(X, Y)

# pythran export allpairs_distances(float64[][], float64[][])
import numpy as np


def allpairs_distances(A, B):
    """This returns the euclidean distances squared
    dist2(x, y) = dot(x, x) - 2 * dot(x, y) + dot(y, y)
    """
    A2 = np.einsum("ij,ij->i", A, A)
    B2 = np.einsum("ij,ij->i", B, B)
    return A2[:, None] + B2[None, :] - 2 * np.dot(A, B.T)
