Fix dynamic module loading from symlinked Hub cache (snapshots -> blobs)
Author: ldkhang1201
Pull request: yes

## What this fixes

Loading a `trust_remote_code` model from a **local, symlinked Hub/NGC cache** crashes with:

```
FileNotFoundError: [Errno 2] No such file or directory:
'.../blobs/transformers_4_44_2__modeling_rope_utils.py'
```

A standard `huggingface_hub` / NGC cache stores each file twice:

```
models--org--repo/
  blobs/<sha>                  # real content, content-addressed, hash-named, no .py extension
  snapshots/<rev>/modeling.py  # symlink -> ../../blobs/<sha>
```

`_compute_local_source_files_hash` did `Path(resolved_module_file).resolve()` before calling
`get_relative_import_files`. That follows the snapshot symlink into `blobs/`, and
`get_relative_import_files` then derives sibling import paths from `Path(module_file).parent`
(now `blobs/`). The named `.py` siblings only exist in `snapshots/<rev>/`, not in `blobs/`, so the
lookup raises `FileNotFoundError`.

## Fix

- Run relative-import discovery on the **unresolved** snapshot path, so traversal stays inside
  `snapshots/<rev>/` where the named `*.py` symlinks live.
- When building the hash key, canonicalize only the **parent directory** (to normalize symlinked
  path components such as macOS `/var`→`/private/var`) and keep the file's logical name.
  `read_bytes()` still follows the symlink, so content is hashed correctly. For plain
  non-symlinked local dirs the produced hash is unchanged (no cache churn).

## Regression range

- Good: `5.8.1` / `5.9.0` / `5.10.0`
- Broken: `5.10.1` / `5.10.2` … current `main`
- Introduced by #46022 ("include transitive relative imports when loading from local directory"),
  which switched the local hash path to `get_relative_import_files(resolved_module_file)` on the
  resolved path.

Real-world impact: NIM/vLLM serving custom-code models (e.g.
`nvidia/llama-3.3-nemotron-super-49b-v1.5`) from the NGC cache fails to start.

## Tests

Added two regression tests in `tests/utils/test_dynamic_module_utils.py` that build the real
`blobs/` + `snapshots/` symlink layout:

- `test_get_cached_module_file_local_handles_symlinked_hub_cache` — loads a module with a transitive
  relative-import chain (A→B→C) from a symlinked cache; fails on `main` with the exact
  `FileNotFoundError`, passes with the fix, and asserts the transitive deps are copied with correct
  content.
- `test_get_cached_module_file_symlinked_hub_cache_hash_tracks_blob_content` — ensures the cache key
  still tracks blob content (read via the symlink), not the snapshot-relative name.

```
$ python -m pytest tests/utils/test_dynamic_module_utils.py -q
17 passed
```

Both new tests were confirmed to fail on unpatched `main` with the production `FileNotFoundError`.
Also verified clean: `ruff check`, `ruff format`, `check_copies`, `check_modular_conversion`.

## Duplicate-work / coordination

- No existing open issue or PR addresses this (searched `gh issue/pr list` for
  `_compute_local_source_files_hash`, dynamic-module `symlink`/`blobs`, and
  `trust_remote_code FileNotFoundError snapshots`). The only related PR, #42891, is an unrelated,
  closed change.
- This is a net-new regression report + fix with a self-contained reproducer; it does not duplicate
  existing work.

## Disclosure

AI assistance (Claude Code) was used to root-cause and draft this change. The human submitter has
reviewed every changed line and is responsible for its contents.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


Comments:
**CI Dashboard:** [View test results in Grafana](https://transformers-ci.lor-e.huggingface.cool/d/pytest-observability-by-pr/pytest-observability-branch?var-pr=46611)