Repository: kornia/kornia

Issue:
Importing solve function from PyTorch fails for edge case version 
### Describe the bug

Hi there,

We're running the PyTorch version labeled `1.7.1+cu110`, but it is giving us issues when importing Kornia because of the following check in `_compat.py`:

```
if version.parse(torch.__version__) > version.parse("1.7.1"):
    # TODO: remove the type: ignore once Python 3.6 is deprecated.
    # It turns out that Pytorch has no attribute `torch.linalg` for
    # Python 3.6 / PyTorch 1.7.0, 1.7.1
    from torch.linalg import solve  # type: ignore
else:
    from torch import solve as _solve

    # NOTE: in previous versions `torch.solve` accepted arguments in another order.
    def solve(A: torch.Tensor, B: torch.Tensor) -> torch.Tensor:
        return _solve(B, A).solution
```

This check appears to believe that our version is > 1.7.1 and therefore attempts to import the wrong `solve` function.


### Reproduction steps

```bash
1. Get PyTorch 1.7.1+anything (cu110, cu101, cu92, cpu) 
2. Attempt to import Kornia
```


### Expected behavior

Importing Kornia with this version should not fail on a PyTorch version check. Perhaps it would make sense to split on `+` before checking the version.

### Environment

```shell
- PyTorch Version (e.g., 1.0): 1.7.1+cu110
- OS (e.g., Linux): Ubuntu 20.04
- How you installed PyTorch (`conda`, `pip`, source): `pip`
- Build command you used (if compiling from source): -
- Python version: 3.7.5
- CUDA/cuDNN version: -
- GPU models and configuration: - 
- Any other relevant information: -
```


### Additional context

_No response_


Discussion:
definitely, we didn't consider that. /cc @pmeier  
A quick solution is to split version by + and take first element before parsing to compare. If that works, could you send a quick or to fix ?
@edgarriba Yes that should work. 

I'm just wondering how you are able to use the `packaging` package in the first place? `kornia` does not depend on it so if you can import it is comes as dependency from another package. In my env it is required by `pytest`, but I wouldn't expect a regular user to have that installed. 
I'm honestly a bit lost what you mean with the `packaging` part; I don't think that's relevant/mentioned anywhere? Please correct me if I'm wrong.
@mdjong1 The version comparison is performed by the [`packaging`](https://pypi.org/project/packaging/) package:

https://github.com/kornia/kornia/blob/b2bba7950d748ba0b8ce0cc68035a248799a1044/kornia/utils/_compat.py#L3-L5

Since `kornia` does not depend on it, `pip install kornia` will not install it. In case the user does not have it installed, `kornia` will now fail as soon as this module is imported.
Reproduction:

```shell
$ pip list
Package    Version
---------- -------
pip        21.2.4
setuptools 58.0.4
wheel      0.37.0
$ pip install kornia
[...]
Successfully installed kornia-0.5.10 torch-1.9.0 typing-extensions-3.10.0.2
$ python -c "import kornia"
[...]
ModuleNotFoundError: No module named 'packaging'
```
We have pytest as one of our dev dependencies, so that might be why it didn't fail there
@pmeier you are right, my fault to include in main dependencies list. Problem of always going under development setup :) 
@mdjong1 this is the right place to include https://github.com/kornia/kornia/blob/master/setup.py#L115



Resolving patch:
diff --git a/kornia/utils/_compat.py b/kornia/utils/_compat.py
--- a/kornia/utils/_compat.py
+++ b/kornia/utils/_compat.py
@@ -2,7 +2,13 @@
 
 from packaging import version
 
-if version.parse(torch.__version__) > version.parse("1.7.1"):
+
+def torch_version() -> str:
+    """Parse the `torch.__version__` variable and removes +cu*/cpu."""
+    return torch.__version__.split('+')[0]
+
+
+if version.parse(torch_version()) > version.parse("1.7.1"):
     # TODO: remove the type: ignore once Python 3.6 is deprecated.
     # It turns out that Pytorch has no attribute `torch.linalg` for
     # Python 3.6 / PyTorch 1.7.0, 1.7.1
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -112,7 +112,10 @@ def run(self):
     subprocess.call(['rm -rf dist/ build/ kornia.egg*'], shell=True)
 
 
-requirements = ['torch' + kornia_pt_dependencies[dep_version(version)]]
+requirements = [
+    'torch' + kornia_pt_dependencies[dep_version(version)],
+    'packaging'  # REMOVE once we deprecate pytorch > 1.7.1. See: issue #1264
+]
 
 
 if __name__ == '__main__':


Test patch: