Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add remove symlink #4

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
94 changes: 81 additions & 13 deletions pyslink.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -17,41 +18,108 @@ 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
finally:
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 <create/remove> <path_to_target>")
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())
14 changes: 12 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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