From 2564eb8835ffe12d26b19c9d8b20909aeeaea48c Mon Sep 17 00:00:00 2001 From: vvanglro Date: Wed, 5 Jun 2024 11:00:45 +0800 Subject: [PATCH 1/2] feat: add remove symlink --- pyslink.py | 94 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 13 deletions(-) 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()) From 72e8d0072c586bec03dd8694e2115de584477d62 Mon Sep 17 00:00:00 2001 From: vvanglro Date: Wed, 5 Jun 2024 12:29:21 +0800 Subject: [PATCH 2/2] Update readme.md --- readme.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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