simfix 0.1.1__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {simfix-0.1.1/simfix.egg-info → simfix-0.1.3}/PKG-INFO +12 -2
  2. {simfix-0.1.1 → simfix-0.1.3}/README.md +11 -1
  3. {simfix-0.1.1 → simfix-0.1.3}/pyproject.toml +1 -1
  4. {simfix-0.1.1 → simfix-0.1.3}/simfix/__init__.py +1 -1
  5. {simfix-0.1.1 → simfix-0.1.3}/simfix/cli.py +57 -1
  6. simfix-0.1.3/simfix/recommendations.py +131 -0
  7. {simfix-0.1.1 → simfix-0.1.3/simfix.egg-info}/PKG-INFO +12 -2
  8. {simfix-0.1.1 → simfix-0.1.3}/simfix.egg-info/SOURCES.txt +1 -0
  9. {simfix-0.1.1 → simfix-0.1.3}/tests/test_basic.py +104 -1
  10. {simfix-0.1.1 → simfix-0.1.3}/LICENSE +0 -0
  11. {simfix-0.1.1 → simfix-0.1.3}/setup.cfg +0 -0
  12. {simfix-0.1.1 → simfix-0.1.3}/simfix/analyzer.py +0 -0
  13. {simfix-0.1.1 → simfix-0.1.3}/simfix/cmake.py +0 -0
  14. {simfix-0.1.1 → simfix-0.1.3}/simfix/commands.py +0 -0
  15. {simfix-0.1.1 → simfix-0.1.3}/simfix/compatibility.py +0 -0
  16. {simfix-0.1.1 → simfix-0.1.3}/simfix/conda_environment.py +0 -0
  17. {simfix-0.1.1 → simfix-0.1.3}/simfix/conda_fixer.py +0 -0
  18. {simfix-0.1.1 → simfix-0.1.3}/simfix/cuda_docker.py +0 -0
  19. {simfix-0.1.1 → simfix-0.1.3}/simfix/docker_runner.py +0 -0
  20. {simfix-0.1.1 → simfix-0.1.3}/simfix/dockerfile.py +0 -0
  21. {simfix-0.1.1 → simfix-0.1.3}/simfix/fixer.py +0 -0
  22. {simfix-0.1.1 → simfix-0.1.3}/simfix/git_assets.py +0 -0
  23. {simfix-0.1.1 → simfix-0.1.3}/simfix/planner.py +0 -0
  24. {simfix-0.1.1 → simfix-0.1.3}/simfix/pypi.py +0 -0
  25. {simfix-0.1.1 → simfix-0.1.3}/simfix/pyproject.py +0 -0
  26. {simfix-0.1.1 → simfix-0.1.3}/simfix/python_requirements.py +0 -0
  27. {simfix-0.1.1 → simfix-0.1.3}/simfix/repo.py +0 -0
  28. {simfix-0.1.1 → simfix-0.1.3}/simfix/report.py +0 -0
  29. {simfix-0.1.1 → simfix-0.1.3}/simfix/ros_docker.py +0 -0
  30. {simfix-0.1.1 → simfix-0.1.3}/simfix/ros_package.py +0 -0
  31. {simfix-0.1.1 → simfix-0.1.3}/simfix/setup_py.py +0 -0
  32. {simfix-0.1.1 → simfix-0.1.3}/simfix/system.py +0 -0
  33. {simfix-0.1.1 → simfix-0.1.3}/simfix/system_docker.py +0 -0
  34. {simfix-0.1.1 → simfix-0.1.3}/simfix.egg-info/dependency_links.txt +0 -0
  35. {simfix-0.1.1 → simfix-0.1.3}/simfix.egg-info/entry_points.txt +0 -0
  36. {simfix-0.1.1 → simfix-0.1.3}/simfix.egg-info/requires.txt +0 -0
  37. {simfix-0.1.1 → simfix-0.1.3}/simfix.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simfix
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: A dependency checker and installation assistant for simulator repositories.
5
5
  Author-email: Habib ur Rehmaan <h.rehmaan96@gmail.com>
6
6
  License-Expression: MIT
@@ -102,6 +102,15 @@ Analyze a GitHub repository directly:
102
102
  simfix doctor https://github.com/user/repository.git
103
103
  ```
104
104
 
105
+ ## Environment recommendations
106
+
107
+ Some simulator projects require system-level or vendor-managed dependencies such as NVIDIA drivers, CUDA, ROS, Gazebo, Isaac Gym, or Isaac Sim. SimFix does not install these automatically because they depend on the operating system, hardware, driver compatibility, administrator permissions, and vendor installation steps.
108
+
109
+ Use:
110
+
111
+ ```bash
112
+ simfix recommendations <repo>
113
+ ```
105
114
  ## Main commands
106
115
 
107
116
  ```bash
@@ -109,10 +118,11 @@ simfix --version
109
118
  simfix system
110
119
  simfix doctor <repo>
111
120
  simfix doctor <repo> --report
121
+ simfix recommendations <repo>
122
+ simfix fix <repo>
112
123
  simfix analyze <repo>
113
124
  simfix plan <repo>
114
125
  simfix commands <repo>
115
- simfix fix <repo>
116
126
  ```
117
127
 
118
128
  ## What SimFix can detect
@@ -68,6 +68,15 @@ Analyze a GitHub repository directly:
68
68
  simfix doctor https://github.com/user/repository.git
69
69
  ```
70
70
 
71
+ ## Environment recommendations
72
+
73
+ Some simulator projects require system-level or vendor-managed dependencies such as NVIDIA drivers, CUDA, ROS, Gazebo, Isaac Gym, or Isaac Sim. SimFix does not install these automatically because they depend on the operating system, hardware, driver compatibility, administrator permissions, and vendor installation steps.
74
+
75
+ Use:
76
+
77
+ ```bash
78
+ simfix recommendations <repo>
79
+ ```
71
80
  ## Main commands
72
81
 
73
82
  ```bash
@@ -75,10 +84,11 @@ simfix --version
75
84
  simfix system
76
85
  simfix doctor <repo>
77
86
  simfix doctor <repo> --report
87
+ simfix recommendations <repo>
88
+ simfix fix <repo>
78
89
  simfix analyze <repo>
79
90
  simfix plan <repo>
80
91
  simfix commands <repo>
81
- simfix fix <repo>
82
92
  ```
83
93
 
84
94
  ## What SimFix can detect
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simfix"
7
- version = "0.1.1"
7
+ version = "0.1.3"
8
8
  description = "A dependency checker and installation assistant for simulator repositories."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """SimFix package."""
2
2
 
3
- __version__ = "0.1.1"
3
+ __version__ = "0.1.3"
@@ -16,7 +16,7 @@ from simfix.pypi import check_pypi_packages
16
16
  from simfix.repo import clone_repo, is_git_url
17
17
  from simfix.report import generate_markdown_report, write_markdown_report
18
18
  from simfix.system import get_system_info
19
-
19
+ from simfix.recommendations import generate_recommendations
20
20
 
21
21
  console = Console()
22
22
 
@@ -58,6 +58,33 @@ def _resolve_repo_path(repo: str) -> Path:
58
58
  return Path(repo)
59
59
 
60
60
 
61
+ def print_recommendations_table(recommendations: list) -> None:
62
+ """Print system and vendor dependency recommendations."""
63
+ if not recommendations:
64
+ console.print(
65
+ "[green]No additional system or vendor recommendations found.[/green]"
66
+ )
67
+ return
68
+
69
+ table = Table(title="Environment compatibility recommendations")
70
+ table.add_column("Category")
71
+ table.add_column("Status")
72
+ table.add_column("Title")
73
+ table.add_column("Reason")
74
+ table.add_column("Suggestion")
75
+
76
+ for recommendation in recommendations:
77
+ table.add_row(
78
+ recommendation.category,
79
+ recommendation.status,
80
+ recommendation.title,
81
+ recommendation.reason,
82
+ recommendation.suggestion,
83
+ )
84
+
85
+ console.print(table)
86
+
87
+
61
88
  @app.command()
62
89
  def analyze(repo: str) -> None:
63
90
  """Analyze repository dependency files without system diagnostics."""
@@ -84,6 +111,23 @@ def analyze(repo: str) -> None:
84
111
  console.print(f"[bold]Detected ecosystem(s):[/bold] {ecosystems}")
85
112
 
86
113
 
114
+ @app.command()
115
+ def recommendations(repo: str) -> None:
116
+ """Show environment compatibility and manual dependency guidance."""
117
+ repo_path = Path(repo).expanduser().resolve()
118
+ analysis = analyze_repo(repo_path)
119
+
120
+ repo_recommendations = generate_recommendations(
121
+ dependencies=analysis.all_python_dependencies,
122
+ detected_ecosystems=analysis.detected_ecosystems,
123
+ )
124
+
125
+ console.print("[bold]SimFix Recommendations[/bold]")
126
+ console.print(f"Repository: {repo_path}")
127
+
128
+ print_recommendations_table(repo_recommendations)
129
+
130
+
87
131
  @app.command()
88
132
  def plan(repo: str) -> None:
89
133
  """Generate a recommended installation plan for a repository."""
@@ -358,6 +402,18 @@ def doctor(
358
402
 
359
403
  console.print(warning_table)
360
404
 
405
+ repo_recommendations = generate_recommendations(
406
+ dependencies=analysis.all_python_dependencies,
407
+ detected_ecosystems=analysis.detected_ecosystems,
408
+ )
409
+
410
+ if repo_recommendations:
411
+ console.print()
412
+ console.print(
413
+ "[yellow]System/vendor recommendations found.[/yellow] "
414
+ f"Run: simfix recommendations {repo_path}"
415
+ )
416
+
361
417
  if report:
362
418
  report_text = generate_markdown_report(
363
419
  analysis=analysis,
@@ -0,0 +1,131 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+
6
+ @dataclass(frozen=True)
7
+ class Recommendation:
8
+ """A safe recommendation for a system or vendor dependency."""
9
+
10
+ category: str
11
+ title: str
12
+ status: str
13
+ reason: str
14
+ suggestion: str
15
+
16
+
17
+ def generate_recommendations(
18
+ dependencies: list[str],
19
+ detected_ecosystems: list[str],
20
+ ) -> list[Recommendation]:
21
+ """Generate safe system and vendor dependency recommendations.
22
+
23
+ This function does not install drivers, ROS, CUDA, or vendor tools.
24
+ It only detects likely requirements and returns guidance.
25
+ """
26
+ recommendations: list[Recommendation] = []
27
+
28
+ normalized_dependencies = [dependency.lower() for dependency in dependencies]
29
+
30
+ normalized_ecosystems = [ecosystem.lower() for ecosystem in detected_ecosystems]
31
+
32
+ has_isaacgym = any(
33
+ "isaacgym" in dependency for dependency in normalized_dependencies
34
+ )
35
+ has_isaacsim = any(
36
+ "isaacsim" in dependency or "omni.isaac" in dependency
37
+ for dependency in normalized_dependencies
38
+ )
39
+ has_cuda_dependency = any(
40
+ _has_cuda_keyword(dependency) for dependency in normalized_dependencies
41
+ )
42
+ has_ros = "ros" in normalized_ecosystems
43
+
44
+ if has_isaacgym:
45
+ recommendations.append(
46
+ Recommendation(
47
+ category="Vendor-managed dependency",
48
+ title="NVIDIA Isaac Gym required",
49
+ status="Manual installation required",
50
+ reason=(
51
+ "The dependency 'isaacgym' was detected, but it is not "
52
+ "available as a normal PyPI package."
53
+ ),
54
+ suggestion=(
55
+ "Install NVIDIA Isaac Gym manually in a compatible Linux "
56
+ "environment with NVIDIA GPU support. If the local machine "
57
+ "is not suitable, use an HPC GPU node or cloud GPU instance."
58
+ ),
59
+ )
60
+ )
61
+
62
+ if has_isaacsim:
63
+ recommendations.append(
64
+ Recommendation(
65
+ category="Vendor-managed dependency",
66
+ title="NVIDIA Isaac Sim required",
67
+ status="Manual installation required",
68
+ reason=(
69
+ "Isaac Sim or omni.isaac dependencies were detected. "
70
+ "These are NVIDIA-managed dependencies."
71
+ ),
72
+ suggestion=(
73
+ "Install Isaac Sim using NVIDIA's official installation "
74
+ "method. Use a supported system with compatible NVIDIA GPU "
75
+ "drivers."
76
+ ),
77
+ )
78
+ )
79
+
80
+ if has_isaacgym or has_isaacsim or has_cuda_dependency:
81
+ recommendations.append(
82
+ Recommendation(
83
+ category="GPU/CUDA",
84
+ title="CUDA-compatible environment recommended",
85
+ status="Check required",
86
+ reason=(
87
+ "GPU/CUDA-related dependencies were detected in the " "repository."
88
+ ),
89
+ suggestion=(
90
+ "Use a compatible Linux/NVIDIA GPU environment. If the "
91
+ "local GPU is not CUDA-compatible, consider a Docker setup "
92
+ "on a compatible machine, an HPC GPU node, a cloud GPU "
93
+ "instance, or CPU-only mode if the simulator supports it."
94
+ ),
95
+ )
96
+ )
97
+
98
+ if has_ros:
99
+ recommendations.append(
100
+ Recommendation(
101
+ category="ROS",
102
+ title="ROS environment required",
103
+ status="Manual installation required",
104
+ reason="ROS package files were detected in the repository.",
105
+ suggestion=(
106
+ "Use a matching ROS Docker image or install the correct "
107
+ "ROS distribution manually. For ROS 1/catkin projects, "
108
+ "ROS Noetic on Ubuntu 20.04 is commonly used. For ROS "
109
+ "2/ament projects, ROS Humble on Ubuntu 22.04 is commonly "
110
+ "used."
111
+ ),
112
+ )
113
+ )
114
+
115
+ return recommendations
116
+
117
+
118
+ def _has_cuda_keyword(dependency: str) -> bool:
119
+ """Return True if a dependency suggests GPU/CUDA requirements."""
120
+ cuda_keywords = [
121
+ "cuda",
122
+ "cudnn",
123
+ "cupy",
124
+ "pytorch3d",
125
+ "onnxruntime-gpu",
126
+ "tensorflow-gpu",
127
+ "jax[cuda",
128
+ "numba.cuda",
129
+ ]
130
+
131
+ return any(keyword in dependency for keyword in cuda_keywords)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simfix
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: A dependency checker and installation assistant for simulator repositories.
5
5
  Author-email: Habib ur Rehmaan <h.rehmaan96@gmail.com>
6
6
  License-Expression: MIT
@@ -102,6 +102,15 @@ Analyze a GitHub repository directly:
102
102
  simfix doctor https://github.com/user/repository.git
103
103
  ```
104
104
 
105
+ ## Environment recommendations
106
+
107
+ Some simulator projects require system-level or vendor-managed dependencies such as NVIDIA drivers, CUDA, ROS, Gazebo, Isaac Gym, or Isaac Sim. SimFix does not install these automatically because they depend on the operating system, hardware, driver compatibility, administrator permissions, and vendor installation steps.
108
+
109
+ Use:
110
+
111
+ ```bash
112
+ simfix recommendations <repo>
113
+ ```
105
114
  ## Main commands
106
115
 
107
116
  ```bash
@@ -109,10 +118,11 @@ simfix --version
109
118
  simfix system
110
119
  simfix doctor <repo>
111
120
  simfix doctor <repo> --report
121
+ simfix recommendations <repo>
122
+ simfix fix <repo>
112
123
  simfix analyze <repo>
113
124
  simfix plan <repo>
114
125
  simfix commands <repo>
115
- simfix fix <repo>
116
126
  ```
117
127
 
118
128
  ## What SimFix can detect
@@ -18,6 +18,7 @@ simfix/planner.py
18
18
  simfix/pypi.py
19
19
  simfix/pyproject.py
20
20
  simfix/python_requirements.py
21
+ simfix/recommendations.py
21
22
  simfix/repo.py
22
23
  simfix/report.py
23
24
  simfix/ros_docker.py
@@ -10,6 +10,7 @@ from simfix.conda_fixer import fix_conda_environment_file
10
10
  from simfix.cuda_docker import create_cuda_dockerfile, detect_gpu_project
11
11
  from simfix.docker_runner import create_docker_run_helper
12
12
  from simfix.dockerfile import parse_dockerfile
13
+ from simfix.recommendations import generate_recommendations
13
14
  from simfix.fixer import (
14
15
  extract_direct_pin_conflict,
15
16
  fix_pyproject_with_uv,
@@ -27,6 +28,11 @@ from simfix.report import generate_markdown_report, write_markdown_report
27
28
  from simfix.ros_docker import create_ros_dockerfile
28
29
  from simfix.ros_package import parse_ros_package
29
30
  from simfix.setup_py import parse_setup_py_dependencies
31
+
32
+ from typer.testing import CliRunner
33
+
34
+ from simfix.cli import app
35
+
30
36
  from simfix.system import (
31
37
  SystemInfo,
32
38
  command_exists,
@@ -39,7 +45,7 @@ from simfix.system import (
39
45
 
40
46
 
41
47
  def test_version() -> None:
42
- assert __version__ == "0.1.1"
48
+ assert __version__ == "0.1.3"
43
49
 
44
50
 
45
51
  def test_analyze_python_repo(tmp_path: Path) -> None:
@@ -1117,3 +1123,100 @@ def test_remove_direct_requirement_pin() -> None:
1117
1123
  )
1118
1124
 
1119
1125
  assert fixed_text == "urdfpy==0.0.22\nnumpy==1.23\n"
1126
+
1127
+
1128
+ def test_generate_recommendations_detects_isaacgym() -> None:
1129
+ recommendations = generate_recommendations(
1130
+ dependencies=["isaacgym", "torch"],
1131
+ detected_ecosystems=["python"],
1132
+ )
1133
+
1134
+ titles = [recommendation.title for recommendation in recommendations]
1135
+
1136
+ assert "NVIDIA Isaac Gym required" in titles
1137
+ assert "CUDA-compatible environment recommended" in titles
1138
+
1139
+
1140
+ def test_generate_recommendations_detects_isaacsim() -> None:
1141
+ recommendations = generate_recommendations(
1142
+ dependencies=["omni.isaac.core"],
1143
+ detected_ecosystems=["python"],
1144
+ )
1145
+
1146
+ titles = [recommendation.title for recommendation in recommendations]
1147
+
1148
+ assert "NVIDIA Isaac Sim required" in titles
1149
+ assert "CUDA-compatible environment recommended" in titles
1150
+
1151
+
1152
+ def test_generate_recommendations_detects_ros() -> None:
1153
+ recommendations = generate_recommendations(
1154
+ dependencies=[],
1155
+ detected_ecosystems=["ros"],
1156
+ )
1157
+
1158
+ titles = [recommendation.title for recommendation in recommendations]
1159
+
1160
+ assert "ROS environment required" in titles
1161
+
1162
+
1163
+ def test_generate_recommendations_empty_for_simple_python_project() -> None:
1164
+ recommendations = generate_recommendations(
1165
+ dependencies=["numpy", "matplotlib"],
1166
+ detected_ecosystems=["python"],
1167
+ )
1168
+
1169
+ assert recommendations == []
1170
+
1171
+
1172
+ def test_recommendations_command_simple_repo(tmp_path: Path) -> None:
1173
+ repo = tmp_path / "repo"
1174
+ repo.mkdir()
1175
+ (repo / "requirements.txt").write_text("numpy\n", encoding="utf-8")
1176
+
1177
+ runner = CliRunner()
1178
+ result = runner.invoke(app, ["recommendations", str(repo)])
1179
+
1180
+ assert result.exit_code == 0
1181
+ assert "SimFix Recommendations" in result.output
1182
+
1183
+
1184
+ def test_recommendations_command_detects_isaacgym(tmp_path: Path) -> None:
1185
+ repo = tmp_path / "repo"
1186
+ repo.mkdir()
1187
+ (repo / "requirements.txt").write_text("isaacgym\n", encoding="utf-8")
1188
+
1189
+ runner = CliRunner()
1190
+ result = runner.invoke(app, ["recommendations", str(repo)])
1191
+
1192
+ assert result.exit_code == 0
1193
+ assert "isaacgym" in result.output.lower()
1194
+
1195
+
1196
+ def test_doctor_shows_recommendations_hint_for_vendor_dependency(
1197
+ tmp_path: Path,
1198
+ ) -> None:
1199
+ repo = tmp_path / "repo"
1200
+ repo.mkdir()
1201
+ (repo / "requirements.txt").write_text("isaacgym\n", encoding="utf-8")
1202
+
1203
+ runner = CliRunner()
1204
+ result = runner.invoke(app, ["doctor", str(repo)])
1205
+
1206
+ assert result.exit_code == 0
1207
+ assert "System/vendor recommendations found" in result.output
1208
+ assert "simfix recommendations" in result.output
1209
+
1210
+
1211
+ def test_doctor_does_not_show_recommendations_hint_for_simple_repo(
1212
+ tmp_path: Path,
1213
+ ) -> None:
1214
+ repo = tmp_path / "repo"
1215
+ repo.mkdir()
1216
+ (repo / "requirements.txt").write_text("numpy\n", encoding="utf-8")
1217
+
1218
+ runner = CliRunner()
1219
+ result = runner.invoke(app, ["doctor", str(repo)])
1220
+
1221
+ assert result.exit_code == 0
1222
+ assert "System/vendor recommendations found" not in result.output
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes