diff --git a/pyslink.py b/pyslink.py
index 28530f8..ec78a4c 100644
--- a/pyslink.py
+++ b/pyslink.py
@@ -1,5 +1,6 @@
"""Soft link a file/directory with python site-packages directory"""
import os
+import ast
import subprocess
import sys
from distutils.sysconfig import get_python_lib
@@ -17,29 +18,27 @@ def sh(command: str) -> str:
).communicate()[0]
-def main() -> int:
- argv = sys.argv
- if len(argv) > 1 and len(argv) < 3:
- path = argv[1]
- else:
- print("requires one positional parameters")
- return 1
-
+def get_path_info(path: str):
pylib = get_python_lib()
original = os.path.abspath(path)
- path, target = os.path.split(original)
+ root_path, target = os.path.split(original)
dest = os.path.join(pylib, target)
+ return original, dest, root_path, pylib
+
+
+def create_symlink(path: str) -> int:
+ original, dest, root_path, pylib = get_path_info(path)
#
print(sh("ln -sfnv %s %s" % (original, dest)))
#
- setup = os.path.join(path, "setup.py")
+ setup = os.path.join(root_path, "setup.py")
if os.path.isfile(setup):
eggdir = None
current = os.getcwd()
try:
- os.chdir(path)
+ os.chdir(root_path)
print(sh("%s setup.py egg_info" % sys.executable))
- for name in os.listdir(path):
+ for name in os.listdir(root_path):
if name.endswith(".egg-info"):
eggdir = name
break
@@ -47,11 +46,80 @@ def main() -> int:
os.chdir(current)
if eggdir:
- original = os.path.join(path, eggdir)
+ original = os.path.join(root_path, eggdir)
dest = os.path.join(pylib, eggdir)
print(sh("ln -sfnv %s %s" % (original, dest)))
return 0
+def extract_setup_name(setup_path):
+ """
+ Extract the name field from the setup() function in setup.py.
+
+ Args:
+ setup_path (str): Path to the setup.py file.
+
+ Returns:
+ str: The value of the name field if found, else None.
+ """
+ try:
+ with open(setup_path, 'r', encoding='utf-8') as file:
+ setup_code = file.read()
+ except IOError as e:
+ print(f"Error reading {setup_path}: {e}")
+ return None
+
+ try:
+ tree = ast.parse(setup_code)
+ except SyntaxError as e:
+ print(f"Syntax error in {setup_path}: {e}")
+ return None
+ for node in ast.walk(tree):
+ if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == 'setup':
+ for keyword in node.keywords:
+ if keyword.arg == 'name':
+ if isinstance(keyword.value, ast.Constant):
+ return keyword.value.value
+
+ return None
+
+
+def remove_symlink(path: str) -> int:
+ original, dest, root_path, pylib = get_path_info(path)
+
+ if os.path.islink(dest):
+ os.unlink(dest)
+ print(f"Removed symlink: {dest}")
+ else:
+ print(f"No symlink found: {dest}")
+
+ setup_path = os.path.join(root_path, "setup.py")
+ if os.path.isfile(setup_path):
+ if package_name := extract_setup_name(setup_path):
+ package_name += ".egg-info"
+ egginfo_path = os.path.join(pylib, package_name)
+ if os.path.isdir(egginfo_path) and os.path.islink(egginfo_path):
+ os.unlink(egginfo_path)
+ print(f"Removed egg-info symlink: {egginfo_path}")
+ return 0
+
+
+def main() -> int:
+ argv = sys.argv
+ if len(argv) != 3:
+ print("Usage: pyslink ")
+ return 1
+
+ action, path = argv[1], argv[2]
+
+ if action == "create":
+ return create_symlink(path)
+ elif action == "remove":
+ return remove_symlink(path)
+ else:
+ print("Invalid action. Use 'create' or 'remove'.")
+ return 1
+
+
if __name__ == "__main__":
sys.exit(main())
diff --git a/readme.md b/readme.md
index 671c3a2..ceaee7e 100644
--- a/readme.md
+++ b/readme.md
@@ -9,11 +9,21 @@
Soft link a file/directory with python site-packages directory.
Useful during development.
+Currently only projects that use `setup` to package releases are supported.
+
Installation via pip:
```bash
pip install pyslink
```
-Soft link a package:
+Create soft link a package:
```bash
-pyslink path/to/main/module
+pyslink create path/to/main/module
+```
+Remove soft link a package
+```
+pyslink remove path/to/main/module
```
+
+## TODO
+
+- [ ] Support pyproject.toml