Skip to content

Commit 57f9936

Browse files
tarekziadevasqu
andauthored
qa: bumped mlinter and allow local override (#45585)
* qa: bumped mlinter and allow local override * bump version * Update utils/check_modeling_rules_doc.py Co-authored-by: Anton Vlasjuk <73884904+vasqu@users.noreply.github.com> * license header * license header --------- Co-authored-by: Anton Vlasjuk <73884904+vasqu@users.noreply.github.com>
1 parent 1e071b2 commit 57f9936

6 files changed

Lines changed: 323 additions & 28 deletions

File tree

docs/source/en/modeling_rules.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,22 @@ specific language governing permissions and limitations under the License.
1313

1414
# Model structure rules
1515

16-
Transformers enforces a set of static rules on every `modeling_*.py`, `modular_*.py`, and `configuration_*.py` file. The [mlinter](https://github.com/huggingface/transformers-mlinter) tool checks them as part of `make typing` and errors out if violations are found.
16+
Transformers enforces a set of static rules on every `modeling_*.py`, `modular_*.py`, and `configuration_*.py` file. The [mlinter](https://github.com/huggingface/transformers-mlinter) package provides the checker engine, and the repository keeps its active rule set in `utils/rules.toml`. That local TOML lets us enable, disable, or tweak rules quickly without waiting for a new `transformers-mlinter` release.
1717

1818
These are the expected model conventions for adding or changing modeling code. They keep the codebase consistent and ensure compatibility with features like pipeline parallelism, device maps, and weight tying.
1919

2020
## Running the checker
2121

22-
`make typing` runs `mlinter` alongside the `ty` type checker. Run `mlinter` on its own with the following commands.
22+
`make typing` runs `mlinter` alongside the `ty` type checker through the repo wrapper, so it picks up `utils/rules.toml`. Run the same wrapper directly with the following commands.
2323

2424
```bash
25-
mlinter # check all modeling files
26-
mlinter --changed-only # check only files changed vs origin/main
27-
mlinter --list-rules # list all rules and their enabled status
28-
mlinter --rule TRF001 # show built-in docs for a specific rule
25+
python utils/check_modeling_structure.py # check all modeling files
26+
python utils/check_modeling_structure.py --changed-only # check only files changed vs origin/main
27+
python utils/check_modeling_structure.py --list-rules # list all rules and their enabled status
28+
python utils/check_modeling_structure.py --rule TRF001 # show built-in docs for a specific rule
2929
```
3030

31-
The `--changed-only` flag is the fastest option during development. It only checks the files you've modified relative to the main branch.
31+
The `--changed-only` flag is the fastest option during development. It only checks the files you've modified relative to the main branch. If you invoke `mlinter` directly instead of the wrapper, pass `--rules-toml utils/rules.toml` so local overrides are applied.
3232

3333
## Fixing a violation
3434

@@ -52,7 +52,7 @@ Use the rule ID to look up the fix in the [rules reference](#rules-reference). T
5252

5353
## Rules reference
5454

55-
Each rule below lists what it enforces and a diff showing the fix. Run `mlinter --rule TRF001` to see the built-in docs for any rule.
55+
Each rule below lists what it enforces and a diff showing the fix. Run `python utils/check_modeling_structure.py --rule TRF001` to see the built-in docs for any rule with the repo's current rule set.
5656

5757
<!-- BEGIN RULES REFERENCE -->
5858

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@
124124
"rjieba",
125125
"rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1",
126126
"ruff==0.14.10",
127-
"transformers-mlinter==0.1.0",
127+
# When bumping `transformers-mlinter`, sync repo-local rule overrides from
128+
# `utils/rules.toml` back into the released package.
129+
"transformers-mlinter==0.1.1",
128130
"ty==0.0.20",
129131
# `sacrebleu` not used in `transformers`. However, it is needed in several tests, when a test calls
130132
# `evaluate.load("sacrebleu")`. This metric is used in the examples that we use to test the `Trainer` with, in the

src/transformers/dependency_versions_table.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"rjieba": "rjieba",
5757
"rouge-score": "rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1",
5858
"ruff": "ruff==0.14.10",
59-
"transformers-mlinter": "transformers-mlinter==0.1.0",
59+
"transformers-mlinter": "transformers-mlinter==0.1.1",
6060
"ty": "ty==0.0.20",
6161
"sacrebleu": "sacrebleu>=1.4.12,<2.0.0",
6262
"sacremoses": "sacremoses",

utils/check_modeling_rules_doc.py

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414
"""
1515
Keep `## Rules reference` section of docs/source/en/modeling_rules.md in sync
16-
with the rules defined in the mlinter package.
16+
with the rules defined in utils/rules.toml via the installed mlinter package.
1717
1818
Usage (from the root of the repo):
1919
@@ -31,21 +31,22 @@
3131
"""
3232

3333
import argparse
34-
import os
34+
from pathlib import Path
3535

3636

3737
CHECKER_CONFIG = {
3838
"name": "modeling_rules_doc",
3939
"label": "Modeling rules documentation",
40-
# Depends on the installed `mlinter` package output, which cannot be expressed
41-
# as repo file globs for the checker cache.
40+
# Depends on utils/rules.toml plus the installed `mlinter` package output,
41+
# which cannot be fully expressed as repo file globs for the checker cache.
4242
"file_globs": None,
43-
"check_args": [],
44-
"fix_args": ["--fix_and_overwrite"],
43+
"check_args": ["--rules-toml", "utils/rules.toml"],
44+
"fix_args": ["--rules-toml", "utils/rules.toml", "--fix_and_overwrite"],
4545
}
4646

47-
ROOT = os.path.dirname(os.path.dirname(__file__))
48-
DOC_PATH = os.path.join(ROOT, "docs", "source", "en", "modeling_rules.md")
47+
ROOT = Path(__file__).resolve().parent.parent
48+
DOC_PATH = ROOT / "docs" / "source" / "en" / "modeling_rules.md"
49+
RULES_TOML_PATH = ROOT / "utils" / "rules.toml"
4950

5051
BEGIN_MARKER = "<!-- BEGIN RULES REFERENCE -->"
5152
END_MARKER = "<!-- END RULES REFERENCE -->"
@@ -54,21 +55,29 @@
5455
def _require_mlinter():
5556
try:
5657
import mlinter
58+
from mlinter import mlinter as mlinter_impl
5759
except ModuleNotFoundError as error:
5860
raise ModuleNotFoundError(
5961
"This script requires the standalone `transformers-mlinter` package. "
6062
'Install the repo quality dependencies with `pip install -e ".[quality]"` and retry.'
6163
) from error
6264

63-
return mlinter
65+
return mlinter, mlinter_impl
6466

6567

66-
def generate_rules_reference() -> str:
67-
return _require_mlinter().render_rules_reference()
68+
def _resolve_path(path: Path) -> Path:
69+
return path if path.is_absolute() else ROOT / path
6870

6971

70-
def check_modeling_rules_doc(overwrite: bool = False):
71-
with open(DOC_PATH, encoding="utf-8") as f:
72+
def generate_rules_reference(rule_specs_path: Path = RULES_TOML_PATH) -> str:
73+
mlinter, mlinter_impl = _require_mlinter()
74+
# Reuse mlinter's registry-switching helper so docs rendering reflects the repo-local rule file.
75+
with mlinter_impl._using_rule_specs(_resolve_path(rule_specs_path)):
76+
return mlinter.render_rules_reference()
77+
78+
79+
def check_modeling_rules_doc(overwrite: bool = False, rule_specs_path: Path = RULES_TOML_PATH):
80+
with DOC_PATH.open(encoding="utf-8") as f:
7281
content = f.read()
7382

7483
begin_idx = content.find(BEGIN_MARKER)
@@ -80,30 +89,36 @@ def check_modeling_rules_doc(overwrite: bool = False):
8089
)
8190

8291
after_begin = begin_idx + len(BEGIN_MARKER)
83-
expected = "\n\n" + generate_rules_reference() + "\n"
92+
expected = "\n\n" + generate_rules_reference(rule_specs_path) + "\n"
8493
current = content[after_begin:end_idx]
8594

8695
if current == expected:
8796
return
8897

8998
if overwrite:
9099
new_content = content[:after_begin] + expected + content[end_idx:]
91-
with open(DOC_PATH, "w", encoding="utf-8") as f:
100+
with DOC_PATH.open("w", encoding="utf-8") as f:
92101
f.write(new_content)
93102
print(f"Updated rules reference in {DOC_PATH}")
94103
else:
95104
raise ValueError(
96105
"The rules reference section in docs/source/en/modeling_rules.md is out of sync "
97-
"with the mlinter package's rules. Run `make fix-repo` to regenerate it."
106+
"with utils/rules.toml. Run `make fix-repo` to regenerate it."
98107
)
99108

100109

101110
if __name__ == "__main__":
102111
parser = argparse.ArgumentParser()
112+
parser.add_argument(
113+
"--rules-toml",
114+
type=Path,
115+
default=RULES_TOML_PATH,
116+
help="Path to a rules TOML file. Defaults to utils/rules.toml.",
117+
)
103118
parser.add_argument("--fix_and_overwrite", action="store_true", help="Whether to fix inconsistencies.")
104119
args = parser.parse_args()
105120

106121
try:
107-
check_modeling_rules_doc(args.fix_and_overwrite)
122+
check_modeling_rules_doc(args.fix_and_overwrite, args.rules_toml)
108123
except ModuleNotFoundError as error:
109124
raise SystemExit(str(error)) from error

utils/check_modeling_structure.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
#!/usr/bin/env python
2+
# Copyright 2026 The HuggingFace Team. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
215
"""Thin local entrypoint for the external mlinter package."""
316

17+
import sys
18+
from pathlib import Path
19+
20+
421
CHECKER_CONFIG = {
522
"name": "modeling_structure",
623
"label": "Modeling file structure",
@@ -9,10 +26,12 @@
926
"src/transformers/models/**/modular_*.py",
1027
"src/transformers/models/**/configuration_*.py",
1128
],
12-
"check_args": [],
29+
"check_args": ["--rules-toml", "utils/rules.toml"],
1330
"fix_args": None,
1431
}
1532

33+
RULES_TOML_PATH = Path(__file__).resolve().with_name("rules.toml")
34+
1635

1736
def _require_mlinter():
1837
try:
@@ -26,8 +45,16 @@ def _require_mlinter():
2645
return mlinter
2746

2847

48+
def _add_default_rules_toml(argv: list[str]) -> list[str]:
49+
if any(arg == "--rules-toml" or arg.startswith("--rules-toml=") for arg in argv[1:]):
50+
return argv
51+
52+
return [argv[0], "--rules-toml", str(RULES_TOML_PATH), *argv[1:]]
53+
54+
2955
if __name__ == "__main__":
3056
try:
57+
sys.argv = _add_default_rules_toml(sys.argv)
3158
raise SystemExit(_require_mlinter().main())
3259
except ModuleNotFoundError as error:
3360
raise SystemExit(str(error)) from error

0 commit comments

Comments
 (0)