Skip to content

Commit 7eadd24

Browse files
committed
feat!: Redesign configuration layerfor full typing and OOP friendliness
Split Config into schema/loader and resolver components to enable fully typed, OOP-friendly configuration without existing temporary workarounds. Introduces explicit runtime loading for rules and formatters instead of lazy attributes in Config class.
1 parent 09ab721 commit 7eadd24

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2933
-2685
lines changed

docs/generate_rules_list.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import robocop
1212
from docs.rules_metadata import GROUPS_LOOKUP
1313
from robocop.linter.rules import SeverityThreshold
14+
from robocop.runtime.resolver import DocumentationImporter
1415

1516
RULES_LIST_TEMPLATE = """
1617
# Rules list
@@ -120,7 +121,7 @@
120121

121122
def get_checker_docs() -> tuple[list[tuple], int]:
122123
"""Load rules for dynamic docs generation"""
123-
doc_importer = robocop.linter.rules.DocumentationImporter()
124+
doc_importer = DocumentationImporter()
124125
rules_count = 0
125126
for _, rule in doc_importer.get_builtin_rules():
126127
rules_count += 1

docs/linter/custom_rules.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ be used to run any code, for example, analysis of the project dependencies and a
414414
Example project checker:
415415

416416
```python title="project_checker.py"
417-
from robocop.config_manager import ConfigManager
417+
from robocop.config.manager import ConfigManager
418418
from robocop.linter.rules import Rule, ProjectChecker, RuleSeverity
419419

420420

noxfile.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ def install_doc_deps(session: nox.Session, robot_version: str) -> None:
5656
@nox.session()
5757
def docs(session: nox.Session) -> None:
5858
install_doc_deps(session, "7.2.2")
59-
# session.run("sphinx-build", "-a", "-E", "-b", "html", "docs", "docs/_build/")
60-
command = ["sphinx-build", "-a", "-E", "--verbose", "-b", "html", "docs/source", "docs/_build/"]
59+
command = ["mkdocs", "build", "--clean", "--verbose", "--config-file", "mkdocs.yml"]
6160
session.run(*command)
6261

6362

@@ -95,4 +94,4 @@ def performance(session: nox.Session, robocop_version: str) -> None:
9594
f"--python={session.virtualenv.location}",
9695
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
9796
)
98-
session.run("python", "-m", "tests.performance.generate_reports", external=True, silent=False)
97+
session.run("python", "-m", "tests.performance.generate_reports", robocop_version, external=True, silent=False)

src/robocop/cache.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,20 @@
88
from __future__ import annotations
99

1010
from dataclasses import dataclass, field
11-
from pathlib import Path
1211
from typing import TYPE_CHECKING, Any
1312

1413
import msgpack
1514

1615
from robocop import __version__
16+
from robocop.config import defaults
1717
from robocop.source_file import SourceFile
1818

1919
if TYPE_CHECKING:
20+
from pathlib import Path
21+
2022
from robocop.config import Config
2123
from robocop.linter.diagnostics import Diagnostic
22-
23-
24-
CACHE_VERSION = "1.0"
25-
CACHE_DIR_NAME = ".robocop_cache"
26-
CACHE_FILE_NAME = "cache.msgpack"
24+
from robocop.runtime.resolved_config import ResolvedConfig
2725

2826

2927
@dataclass(frozen=True)
@@ -201,7 +199,6 @@ def from_dict(cls, data: dict[str, Any]) -> FormatterCacheEntry:
201199
class CacheData:
202200
"""Mutable container for cache data."""
203201

204-
version: str = CACHE_VERSION
205202
robocop_version: str = field(default_factory=lambda: __version__)
206203
linter: dict[str, LinterCacheEntry] = field(default_factory=dict)
207204
formatter: dict[str, FormatterCacheEntry] = field(default_factory=dict)
@@ -215,7 +212,6 @@ def to_dict(self) -> dict[str, Any]:
215212
216213
"""
217214
return {
218-
"version": self.version,
219215
"robocop_version": self.robocop_version,
220216
"linter": {path: entry.to_dict() for path, entry in self.linter.items()},
221217
"formatter": {path: entry.to_dict() for path, entry in self.formatter.items()},
@@ -231,7 +227,6 @@ def from_dict(cls, data: dict[str, Any]) -> CacheData:
231227
232228
"""
233229
return cls(
234-
version=data.get("version", CACHE_VERSION),
235230
robocop_version=data.get("robocop_version", ""),
236231
linter={path: LinterCacheEntry.from_dict(entry) for path, entry in data.get("linter", {}).items()},
237232
formatter={path: FormatterCacheEntry.from_dict(entry) for path, entry in data.get("formatter", {}).items()},
@@ -248,9 +243,9 @@ class RobocopCache:
248243

249244
def __init__(
250245
self,
251-
cache_dir: Path | None = None,
252-
enabled: bool = True,
253-
verbose: bool = False,
246+
cache_dir: Path,
247+
enabled: bool,
248+
verbose: bool,
254249
) -> None:
255250
"""
256251
Initialize the cache.
@@ -262,7 +257,7 @@ def __init__(
262257
263258
"""
264259
self.enabled = enabled
265-
self.cache_dir = cache_dir or Path.cwd() / CACHE_DIR_NAME
260+
self.cache_dir = cache_dir
266261
self.verbose = verbose
267262
self._data: CacheData | None = None
268263
self._dirty = False
@@ -282,7 +277,7 @@ def _load(self) -> None:
282277
self._data = CacheData()
283278
return
284279

285-
cache_file = self.cache_dir / CACHE_FILE_NAME
280+
cache_file = self.cache_dir / defaults.CACHE_FILE_NAME
286281

287282
if not cache_file.is_file():
288283
self._data = CacheData()
@@ -315,7 +310,7 @@ def save(self) -> None:
315310

316311
self.cache_dir.mkdir(parents=True, exist_ok=True)
317312
self._create_gitignore()
318-
cache_file = self.cache_dir / CACHE_FILE_NAME
313+
cache_file = self.cache_dir / defaults.CACHE_FILE_NAME
319314

320315
try:
321316
cache_file.write_bytes(msgpack.packb(self._data.to_dict(), use_bin_type=True))
@@ -517,6 +512,7 @@ def restore_diagnostics(
517512
cached_entry: LinterCacheEntry,
518513
source: Path,
519514
config: Config,
515+
resolved_config: ResolvedConfig,
520516
) -> list[Diagnostic] | None:
521517
"""
522518
Restore Diagnostic objects from cached data.
@@ -525,6 +521,7 @@ def restore_diagnostics(
525521
cached_entry: The cached linter entry.
526522
source: The source file path (Path object for consistency with normal diagnostics).
527523
config: Configuration associated with the source file.
524+
resolved_config: ResolvedConfig with loaded runtime objects such as rules.
528525
529526
Returns:
530527
List of restored diagnostics, or None if restoration failed
@@ -536,9 +533,9 @@ def restore_diagnostics(
536533
restored = []
537534
for cached_diag in cached_entry.diagnostics:
538535
# Try to find rule by ID first, fall back to name
539-
rule = config.linter.rules.get(cached_diag.rule_id)
536+
rule = resolved_config.rules.get(cached_diag.rule_id)
540537
if rule is None:
541-
rule = config.linter.rules.get(cached_diag.rule_name)
538+
rule = resolved_config.rules.get(cached_diag.rule_name)
542539

543540
if rule is None:
544541
# Rule no longer exists - invalidate cache entry

0 commit comments

Comments
 (0)