auto-code-fixer 0.3.1__tar.gz → 0.3.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 (27) hide show
  1. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/PKG-INFO +1 -1
  2. auto_code_fixer-0.3.3/auto_code_fixer/__init__.py +1 -0
  3. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/cli.py +44 -7
  4. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/traceback_utils.py +13 -3
  5. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer.egg-info/PKG-INFO +1 -1
  6. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/pyproject.toml +1 -1
  7. auto_code_fixer-0.3.1/auto_code_fixer/__init__.py +0 -1
  8. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/LICENSE +0 -0
  9. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/README.md +0 -0
  10. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/command_runner.py +0 -0
  11. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/fixer.py +0 -0
  12. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/installer.py +0 -0
  13. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/models.py +0 -0
  14. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/patcher.py +0 -0
  15. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/plan.py +0 -0
  16. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/runner.py +0 -0
  17. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/sandbox.py +0 -0
  18. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/utils.py +0 -0
  19. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer/venv_manager.py +0 -0
  20. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer.egg-info/SOURCES.txt +0 -0
  21. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer.egg-info/dependency_links.txt +0 -0
  22. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer.egg-info/entry_points.txt +0 -0
  23. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer.egg-info/requires.txt +0 -0
  24. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/auto_code_fixer.egg-info/top_level.txt +0 -0
  25. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/setup.cfg +0 -0
  26. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/tests/test_fix_imported_file.py +0 -0
  27. {auto_code_fixer-0.3.1 → auto_code_fixer-0.3.3}/tests/test_internal_imports.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: auto-code-fixer
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: Automatically fix Python code using ChatGPT
5
5
  Author-email: Arif Shah <ashah7775@gmail.com>
6
6
  License: MIT
@@ -0,0 +1 @@
1
+ __version__ = "0.3.3"
@@ -88,15 +88,43 @@ def fix_file(file_path, project_root, api_key, ask, verbose, *, dry_run: bool, m
88
88
  if dry_run:
89
89
  log("DRY RUN: would apply fixes:\n" + "\n".join(rel_changes), "WARN")
90
90
  else:
91
+ sr = os.path.realpath(os.path.abspath(sandbox_root))
92
+ pr = os.path.realpath(os.path.abspath(project_root))
93
+
91
94
  for p in sorted(changed_sandbox_files):
92
- rel = os.path.relpath(p, sandbox_root)
93
- dst = os.path.join(project_root, rel)
94
- if os.path.exists(dst):
95
- bak = backup_file(dst)
95
+ p_real = os.path.realpath(os.path.abspath(p))
96
+
97
+ # compute rel using real paths to avoid macOS /private path weirdness
98
+ rel = os.path.relpath(p_real, sr)
99
+
100
+ # Safety: never allow paths escaping the sandbox
101
+ if rel.startswith(".." + os.sep) or rel == "..":
102
+ log(f"Skipping suspicious path outside sandbox: {p}", "WARN")
103
+ continue
104
+
105
+ dst = os.path.join(pr, rel)
106
+ dst_real = os.path.realpath(os.path.abspath(dst))
107
+
108
+ # Safety: never write outside the project root
109
+ if not (dst_real.startswith(pr + os.sep) or dst_real == pr):
110
+ log(f"Skipping suspicious destination outside project: {dst}", "WARN")
111
+ continue
112
+
113
+ # Avoid shutil.SameFileError
114
+ try:
115
+ if os.path.exists(dst_real) and os.path.samefile(p_real, dst_real):
116
+ log(f"Skip copy (same file): {dst_real}", "DEBUG")
117
+ continue
118
+ except Exception:
119
+ pass
120
+
121
+ if os.path.exists(dst_real):
122
+ bak = backup_file(dst_real)
96
123
  log(f"Backup created: {bak}", "DEBUG")
97
- os.makedirs(os.path.dirname(dst), exist_ok=True)
98
- shutil.copy(p, dst)
99
- log(f"File updated: {dst}")
124
+
125
+ os.makedirs(os.path.dirname(dst_real), exist_ok=True)
126
+ shutil.copy(p_real, dst_real)
127
+ log(f"File updated: {dst_real}")
100
128
 
101
129
  shutil.rmtree(sandbox_root)
102
130
  log(f"Fix completed in {attempt + 1} attempt(s) 🎉")
@@ -115,6 +143,15 @@ def fix_file(file_path, project_root, api_key, ask, verbose, *, dry_run: bool, m
115
143
 
116
144
  target_file = pick_relevant_file(stderr, sandbox_root=sandbox_root) or sandbox_entry
117
145
 
146
+ # Safety: ensure target_file is within sandbox
147
+ try:
148
+ sr = os.path.realpath(os.path.abspath(sandbox_root))
149
+ tf = os.path.realpath(os.path.abspath(target_file))
150
+ if not (tf.startswith(sr + os.sep) or tf == sr):
151
+ target_file = sandbox_entry
152
+ except Exception:
153
+ target_file = sandbox_entry
154
+
118
155
  # Optional AI fix plan can override file selection
119
156
  try:
120
157
  from auto_code_fixer.plan import ask_ai_for_fix_plan
@@ -4,24 +4,34 @@ import re
4
4
  _FILE_RE = re.compile(r"File \"([^\"]+)\", line (\d+)")
5
5
 
6
6
 
7
+ def _norm(p: str) -> str:
8
+ """Normalize paths for comparison.
9
+
10
+ On macOS tracebacks often include /private prefix; realpath handles that.
11
+ """
12
+ return os.path.realpath(os.path.abspath(p))
13
+
14
+
7
15
  def pick_relevant_file(stderr: str, *, sandbox_root: str) -> str | None:
8
16
  """Pick the most relevant python file from a traceback.
9
17
 
10
18
  Strategy: return the last file path that lives inside sandbox_root.
19
+
20
+ Uses realpath() to handle macOS '/private/var/...' vs '/var/...' differences.
11
21
  """
12
22
 
13
23
  if not stderr:
14
24
  return None
15
25
 
16
- sandbox_root = os.path.abspath(sandbox_root)
26
+ sandbox_root_n = _norm(sandbox_root)
17
27
  matches = _FILE_RE.findall(stderr)
18
28
  if not matches:
19
29
  return None
20
30
 
21
31
  chosen = None
22
32
  for path, _lineno in matches:
23
- ap = os.path.abspath(path)
24
- if ap.startswith(sandbox_root):
33
+ ap = _norm(path)
34
+ if ap.startswith(sandbox_root_n + os.sep) or ap == sandbox_root_n:
25
35
  chosen = ap
26
36
 
27
37
  return chosen
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: auto-code-fixer
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: Automatically fix Python code using ChatGPT
5
5
  Author-email: Arif Shah <ashah7775@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "auto-code-fixer"
7
- version = "0.3.1"
7
+ version = "0.3.3"
8
8
  description = "Automatically fix Python code using ChatGPT"
9
9
  readme = "README.md"
10
10
 
@@ -1 +0,0 @@
1
- __version__ = "0.3.1"
File without changes