Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions appdirs/appdirs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import sys

import tree_sitter_python
from tree_sitter import Language, Parser, Query

PY_LANGUAGE = Language(tree_sitter_python.language())
parser = Parser(PY_LANGUAGE)


def update_module(inpath: str, outpath: str, oldmod: str, newmod: str) -> None:
with open(inpath) as f:
code = f.read()

modified_code = change_module(code, oldmod, newmod)

with open(outpath, "w") as f:
f.write(modified_code)

def change_module(code: str, oldmod: str, newmod: str) -> str:

query = Query(PY_LANGUAGE, f"""
(
(import_statement
name: (dotted_name) @module_name)
(#eq? @module_name "{oldmod}")
)

(
(call
function: (attribute
object: (identifier) @module_name))
(#eq? @module_name "{oldmod}")
)
""")

tree = parser.parse(code.encode("utf-8"))
matches = query.matches(tree.root_node)

replacements = []
for _, captures in matches:
node = captures["module_name"][0]
assert node.text == oldmod.encode("utf-8")
replacements.append((node.start_byte, node.end_byte))

replacements.sort(reverse=True)

modified_code = code.encode("utf-8")
for start, end in replacements:
modified_code = modified_code[:start] + newmod.encode("utf-8") + modified_code[end:]

return modified_code.decode("utf-8")


def main(*files):
for file in files:
update_module(file, file, "appdirs", "platformdirs")


if __name__ == "__main__":
sys.exit(main(*sys.argv[1:]))
6 changes: 6 additions & 0 deletions appdirs/ick.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[[rule]]
name = "appdirs"
description = "Replace use of appdirs with platformdirs"
impl = "python"
scope = "file"
deps = ["tree-sitter", "tree-sitter-python"]
10 changes: 10 additions & 0 deletions appdirs/tests/appdirs/input/thing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import appdirs
import something_else

print(appdirs)

def main():
print(appdirs.get_user_home())
return 1

# appdirs was used here.
10 changes: 10 additions & 0 deletions appdirs/tests/appdirs/output/thing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import platformdirs
import something_else

print(appdirs)
Copy link

Copilot AI Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test output still references appdirs, which will cause a NameError after replacement; it should reference platformdirs.

Suggested change
print(appdirs)
print(platformdirs)

Copilot uses AI. Check for mistakes.

def main():
print(platformdirs.get_user_home())
return 1

# appdirs was used here.