Extend import utils to cover "editable" torch versions
Author: bhack
Pull request: yes

# What does this PR do?

<!--
Congratulations! You've made it this far! You're not quite done yet though.

Once merged, your PR is going to appear in the release notes with the title you set, so make sure it's a great title that fully reflects the extent of your awesome contribution.

Then, please replace this with a description of the change and which issue is fixed (if applicable). Please also include relevant motivation and context. List any dependencies (if any) that are required for this change.

Once you're done, someone will review your PR shortly (see the section "Who can review?" below to tag some potential reviewers). They may suggest changes to make the code even better. If no one reviewed your PR after a week has passed, don't hesitate to post a new comment @-mentioning the same persons---sometimes notifications get lost.
-->

<!-- Remove if not applicable -->

Fixes #28999


## Before submitting
- [ ] This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
- [X] Did you read the [contributor guideline](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md#create-a-pull-request),
      Pull Request section?
- [X] Was this discussed/approved via a Github issue or the [forum](https://discuss.huggingface.co/)? Please add a link
      to it if that's the case.
- [ ] Did you make sure to update the documentation with your changes? Here are the
      [documentation guidelines](https://github.com/huggingface/transformers/tree/main/docs), and
      [here are tips on formatting docstrings](https://github.com/huggingface/transformers/tree/main/docs#writing-source-documentation).
- [ ] Did you write any new necessary tests?


## Who can review?

Anyone in the community is free to review the PR once the tests have passed. Feel free to tag
members/contributors who may be interested in your PR.

<!-- Your PR will be replied to more quickly if you can figure out the right person to tag with @

 If you know how to use git blame, that is the easiest way, otherwise, here is a rough guide of **who to tag**.
 Please tag fewer than 3 people.

Models:

- text models: @ArthurZucker and @younesbelkada
- vision models: @amyeroberts
- speech models: @sanchit-gandhi
- graph models: @clefourrier

Library:

- flax: @sanchit-gandhi
- generate: @gante
- pipelines: @Narsil
- tensorflow: @gante and @Rocketknight1
- tokenizers: @ArthurZucker
- trainer: @muellerzr and @pacman100

Integrations:

- deepspeed: HF Trainer/Accelerate: @pacman100
- ray/raytune: @richardliaw, @amogkam
- Big Model Inference: @SunMarc
- quantization (bitsandbytes, autogpt): @SunMarc and @younesbelkada

Documentation: @stevhliu and @MKhalusova

HF projects:

- accelerate: [different repo](https://github.com/huggingface/accelerate)
- datasets: [different repo](https://github.com/huggingface/datasets)
- diffusers: [different repo](https://github.com/huggingface/diffusers)
- rust tokenizers: [different repo](https://github.com/huggingface/tokenizers)

Maintained examples (not research project or legacy):

- Flax: @sanchit-gandhi
- PyTorch: See Models above and tag the person corresponding to the modality of the example.
- TensorFlow: @Rocketknight1

 -->


Comments:
Why formatting error we have? it isn't clear from the CI log

The repository uses double quotes for string literals. You can format your code by running 'make style' (see [contributor guideline](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md#create-a-pull-request)).

Done, who can review this?

@bhack Thanks for opening this PR! 

For anyone who's coming to this PR in the future, could you share the torch version in your environment i.e. when running `pip list | grep torch`?

I've requested a review from @ydshieh as he is the king of all things version and package handling. I'd like to get his opinion before we merge. He's off for a for days, so would next week when this can get merged in.  

Gently ping

Gentle ping @ydshieh 

@bhack Could you also share the torch version listed in your environment, as requested?

It is in the mentioned ticket in the description. This is for the `dev`pytorch versions.

@bhack Yes, I understand it's for the dev version, what I'm asking for is how that appears in your env when running `pip list | grep torch`

These are the nightly releases.. you can find the patterns at https://download.pytorch.org/whl/nightly/torch/

Hi @bhack Thank you for the PR.

I am up to have this, but I am worried about the fact that the dev version might cause problem in the ecosystem.
For example, what would happen 

> version.parse(_torch_version)
and 
> version.parse(_torch_version) >= version.parse("2.1.1")

Would they fail? Would they give the correct results? ect.

Are we not working with this on `dev` only when the import fail?

Well, I might lack some context, but my understanding is

if `importlib.metadata.version(pkg_name)` gives `importlib.metadata.PackageNotFoundError` (which happens with `dev`), we use `importlib.import_module(pkg_name)` to grab the version (and this means the import will work).

So `dev` could be imported, and we can grab its version. But it is unclear to me if the usages (that I listed in the previous comment) will work or give the correct results.

Hope the above make my concern a bit more clear


Yes but I don't understand your example. Where we are using this?
```python
version.parse(_torch_version)
and
version.parse(_torch_version) >= version.parse("2.1.1")
```

If you meant here:
https://github.com/huggingface/transformers/blob/6957c09f81f9ab6da40dbedc91486b34d80a23ec/src/transformers/utils/import_utils.py#L292
We can add the   'dev` version as it has the date as a fake version and control the date.


E.g just tested the PR code today and the `assert` is ok

``` 2.3.0.dev20240314`
```python
import importlib
from importlib import metadata
package_exists = importlib.util.find_spec("torch") is not None
pkg_name="torch"
try:
    # Primary method to get the package version
    package_version = importlib.metadata.version(pkg_name)
    package_exists = True
except importlib.metadata.PackageNotFoundError:
    # Fallback method: Only for "torch" and versions containing "dev"
    if pkg_name == "torch":
        try:
            package = importlib.import_module(pkg_name)
            temp_version = getattr(package, "__version__", "N/A")
            # Check if the version contains "dev"
            if "dev" in temp_version:
                package_version = temp_version
                package_exists = True
            else:
                package_exists = False
        except ImportError:
            # If the package can't be imported, it's not available
            package_exists = False
    else:
        # For packages other than "torch", don't attempt the fallback and set as not available
        package_exists = False
print(f"Detected  version {package_version}")
print(f"Detected  version: {package_version}")
from packaging import version
assert(version.parse(package_version) >= version.parse("2.1.1"))
```

Very nice! Thank you for checking, that's exactly what I am looking for.

@amyeroberts I tried  to do the same (install torch editable version, but it took forever). The changes in this PR LGTM however.

BTW, @bhack could you rebase the PR on the latest main branch? Thanks.

Done

> I tried to do the same (install torch editable version, but it took forever). The changes in this PR LGTM however.

Strange, follow the official mentiond pytorch contributing markdown for rightly 

It is quite fast to prepare.

> pytorch contributing

well, I was trying to use `pip -e` and found probably an old doc (in pytorch forum) that is probably not working anymore

No it is https://github.com/pytorch/pytorch/blob/main/CONTRIBUTING.md#nightly-checkout--pull

The docs for this PR live [here](https://moon-ci-docs.huggingface.co/docs/transformers/pr_29000). All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

Still good to me, but we don't need the last commit `Restore package_exists`.

I will leave @amyeroberts to make the final decision however.

I think the same but it was explicitly requested. So, as you like.

> I think the same but it was explicitly requested. So, as you like.

Sure :-)

(but you can still express you thought instead of just following the request 😃 )