Skip to content

Commit d30995c

Browse files
Copilotshenxianpeng
andcommitted
Add ImportError troubleshooting and conflict detection
Co-authored-by: shenxianpeng <[email protected]>
1 parent 9d87ca3 commit d30995c

File tree

3 files changed

+102
-4
lines changed

3 files changed

+102
-4
lines changed

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,50 @@ repos:
183183
args: [--style=file, --version=21, --verbose] # Add -v or --verbose for detailed output
184184
```
185185

186+
### ImportError: cannot import name 'clang_format' from 'clang_format'
187+
188+
This error occurs when there are conflicting `clang-format` packages installed in your environment. The issue typically happens when:
189+
190+
1. You previously installed PyPI packages like `clang-format` that provide conflicting scripts
191+
2. Your environment has multiple versions of clang tools installed
192+
3. There are leftover scripts from older versions of this hooks package
193+
194+
**Solution 1: Remove conflicting packages**
195+
196+
```bash
197+
# Remove potentially conflicting packages
198+
pip uninstall clang-format clang-tidy clang-tools
199+
200+
# Reinstall cpp-linter-hooks cleanly
201+
pip install --force-reinstall cpp-linter-hooks
202+
```
203+
204+
**Solution 2: Check for conflicting scripts**
205+
206+
```bash
207+
# Check what clang-format script is being used
208+
which clang-format
209+
210+
# If it points to a conflicting script, remove it
211+
rm $(which clang-format) # Only if it's the conflicting script
212+
```
213+
214+
**Solution 3: Use specific entry points**
215+
216+
Ensure your `.pre-commit-config.yaml` is using the latest configuration:
217+
218+
```yaml
219+
repos:
220+
- repo: https://github.com/cpp-linter/cpp-linter-hooks
221+
rev: v1.1.1 # Use the latest version
222+
hooks:
223+
- id: clang-format
224+
args: [--style=file, --version=21]
225+
```
226+
227+
> [!NOTE]
228+
> This hooks package uses `clang-format-hook` and `clang-tidy-hook` as entry points, not the generic `clang-format` script. The error usually indicates that pre-commit is trying to use a conflicting `clang-format` script instead of the correct `clang-format-hook`.
229+
186230
## FAQ
187231

188232
### What's the difference between [`cpp-linter-hooks`](https://github.com/cpp-linter/cpp-linter-hooks) and [`mirrors-clang-format`](https://github.com/pre-commit/mirrors-clang-format)?

cpp_linter_hooks/clang_format.py

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,44 @@
11
import subprocess
22
import sys
3+
import os
4+
import shutil
35
from argparse import ArgumentParser
46
from typing import Tuple
57

68
from .util import ensure_installed, DEFAULT_CLANG_FORMAT_VERSION
79

810

11+
def _check_for_conflicts() -> None:
12+
"""Check for potential conflicts with PyPI clang-format packages."""
13+
# Check if there's a conflicting clang-format script
14+
clang_format_path = shutil.which("clang-format")
15+
if clang_format_path:
16+
try:
17+
# Try to read the script to see if it contains the problematic import
18+
with open(clang_format_path, 'r', encoding='utf-8') as f:
19+
content = f.read()
20+
if "from clang_format import clang_format" in content:
21+
print(
22+
"WARNING: Detected conflicting clang-format script at: " + clang_format_path,
23+
file=sys.stderr
24+
)
25+
print(
26+
"This may cause ImportError. Consider removing conflicting packages:",
27+
file=sys.stderr
28+
)
29+
print(
30+
" pip uninstall clang-format clang-tidy clang-tools",
31+
file=sys.stderr
32+
)
33+
print(
34+
"For more help: https://github.com/cpp-linter/cpp-linter-hooks#importerror-cannot-import-name-clang_format-from-clang_format",
35+
file=sys.stderr
36+
)
37+
except (IOError, UnicodeDecodeError):
38+
# If we can't read the file, ignore the check
39+
pass
40+
41+
942
parser = ArgumentParser()
1043
parser.add_argument("--version", default=DEFAULT_CLANG_FORMAT_VERSION)
1144
parser.add_argument(
@@ -49,7 +82,16 @@ def run_clang_format(args=None) -> Tuple[int, str]:
4982
return retval, output
5083

5184
except FileNotFoundError as e:
52-
return 1, str(e)
85+
error_msg = str(e)
86+
# Provide helpful error message for missing clang-format
87+
if "clang-format" in error_msg.lower():
88+
error_msg += "\nHint: The clang-format tool may not be installed or accessible."
89+
error_msg += f"\nThis hook will try to install clang-format version {hook_args.version}."
90+
return 1, error_msg
91+
except Exception as e:
92+
# Catch any other unexpected errors
93+
error_msg = f"Unexpected error running clang-format: {str(e)}"
94+
return 1, error_msg
5395

5496

5597
def _print_verbose_info(command: list, retval: int, output: str) -> None:
@@ -61,6 +103,10 @@ def _print_verbose_info(command: list, retval: int, output: str) -> None:
61103

62104

63105
def main() -> int:
106+
# Check for potential conflicts early
107+
if os.environ.get("CLANG_FORMAT_HOOK_DEBUG"):
108+
_check_for_conflicts()
109+
64110
retval, output = run_clang_format() # pragma: no cover
65111

66112
# Print output for errors, but not for dry-run mode

cpp_linter_hooks/clang_tidy.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,17 @@ def run_clang_tidy(args=None) -> Tuple[int, str]:
2424
if "warning:" in output or "error:" in output:
2525
retval = 1
2626
return retval, output
27-
except FileNotFoundError as stderr:
28-
retval = 1
29-
return retval, str(stderr)
27+
except FileNotFoundError as e:
28+
error_msg = str(e)
29+
# Provide helpful error message for missing clang-tidy
30+
if "clang-tidy" in error_msg.lower():
31+
error_msg += "\nHint: The clang-tidy tool may not be installed or accessible."
32+
error_msg += f"\nThis hook will try to install clang-tidy version {hook_args.version}."
33+
return 1, error_msg
34+
except Exception as e:
35+
# Catch any other unexpected errors
36+
error_msg = f"Unexpected error running clang-tidy: {str(e)}"
37+
return 1, error_msg
3038

3139

3240
def main() -> int:

0 commit comments

Comments
 (0)