From 65a1c095172634be81f10d4024d073c70212a24c Mon Sep 17 00:00:00 2001 From: ABDELLAH-Hallou Date: Sun, 1 Sep 2024 15:44:24 +0100 Subject: [PATCH 1/5] feat: Add support for custom requirements file and pip options - Added package versions to requirements.txt - Implemented support for additional pip options - Added functionality to handle custom requirements file names --- pwp/{__init.py => __init__.py} | 0 pwp/main.py | 86 ++++--------------------------- pwp/utils/pwp_manager.py | 23 +++++++++ pwp/utils/pwp_parser.py | 23 +++++++++ pwp/utils/requirements_manager.py | 62 ++++++++++++++++++++++ 5 files changed, 118 insertions(+), 76 deletions(-) rename pwp/{__init.py => __init__.py} (100%) create mode 100644 pwp/utils/pwp_manager.py create mode 100644 pwp/utils/pwp_parser.py create mode 100644 pwp/utils/requirements_manager.py diff --git a/pwp/__init.py b/pwp/__init__.py similarity index 100% rename from pwp/__init.py rename to pwp/__init__.py diff --git a/pwp/main.py b/pwp/main.py index 6b15c68..79c1361 100644 --- a/pwp/main.py +++ b/pwp/main.py @@ -1,70 +1,6 @@ -import os import sys -from pip._internal.cli.main import main as pip_main - -def create_or_update_requirements(package_names, action='install'): - requirements_file = 'requirements.txt' - - if action == 'install': - if not os.path.exists(requirements_file): - with open(requirements_file, 'w') as f: - for package in package_names: - f.write(f"{package}\n") - print(f"Created {requirements_file} and added {', '.join(package_names)}") - else: - with open(requirements_file, 'r') as f: - existing_packages = set(line.strip() for line in f) - - new_packages = [pkg for pkg in package_names if pkg not in existing_packages] - - if new_packages: - with open(requirements_file, 'a') as f: - for package in new_packages: - f.write(f"{package}\n") - print(f"Added {', '.join(new_packages)} to {requirements_file}") - - existing = set(package_names) & existing_packages - if existing: - print(f"Packages already in {requirements_file}: {', '.join(existing)}") - - elif action == 'uninstall': - if os.path.exists(requirements_file): - with open(requirements_file, 'r') as f: - packages = set(line.strip() for line in f) - - packages_to_remove = set(package_names) & packages - remaining_packages = packages - packages_to_remove - - with open(requirements_file, 'w') as f: - for package in remaining_packages: - f.write(f"{package}\n") - - if packages_to_remove: - print(f"Removed {', '.join(packages_to_remove)} from {requirements_file}") - - not_found = set(package_names) - packages - if not_found: - print(f"Packages not found in {requirements_file}: {', '.join(not_found)}") - else: - print(f"{requirements_file} not found") - -def pwp_install(): - if len(sys.argv) < 3: - print("Usage: pwp install [ ...]") - return - - package_names = sys.argv[2:] - pip_main(['install'] + package_names) - create_or_update_requirements(package_names, 'install') - -def pwp_uninstall(): - if len(sys.argv) < 3: - print("Usage: pwp uninstall [ ...]") - return - - package_names = sys.argv[2:] - pip_main(['uninstall', '-y'] + package_names) - create_or_update_requirements(package_names, 'uninstall') +from pwp.utils.pwp_manager import install, uninstall +from pwp.utils.pwp_parser import create_parser def main(): if len(sys.argv) < 2: @@ -94,14 +30,12 @@ def main(): return - command = sys.argv[1] - - if command == 'install': - pwp_install() - elif command == 'uninstall': - pwp_uninstall() + parser = create_parser() + args, unknown_args = parser.parse_known_args() + + if args.command == "install": + install(args, unknown_args) + elif args.command == "uninstall": + uninstall(args, unknown_args) else: - print(f"Unknown command: {command}") - -if __name__ == "__main__": - main() \ No newline at end of file + parser.print_help() diff --git a/pwp/utils/pwp_manager.py b/pwp/utils/pwp_manager.py new file mode 100644 index 0000000..c055977 --- /dev/null +++ b/pwp/utils/pwp_manager.py @@ -0,0 +1,23 @@ +import sys + +from pip._internal.cli.main import main as pip +from pwp.utils.requirements_manager import add_requirement, rm_requirement + + +def install(args,unknown_args): + if len(sys.argv) < 3: + print("Usage: pwp install [ ...]") + return + pip_args = ['install'] + args.packages + unknown_args + pip(pip_args) + add_requirement(package_names=args.packages, + requirements_file=args.req_file) + +def uninstall(args,unknown_args): + if len(sys.argv) < 3: + print("Usage: pwp uninstall [ ...]") + return + pip_args = ['uninstall', '-y'] + args.packages + unknown_args + pip(pip_args) + rm_requirement(package_names=args.packages, + requirements_file=args.req_file) \ No newline at end of file diff --git a/pwp/utils/pwp_parser.py b/pwp/utils/pwp_parser.py new file mode 100644 index 0000000..9d3b906 --- /dev/null +++ b/pwp/utils/pwp_parser.py @@ -0,0 +1,23 @@ +import argparse + +def create_parser(): + parser = argparse.ArgumentParser(description="Python package manager wrapper") + parser.add_argument( + "--req-file", + type=str, + default="requirements.txt", + help="Specify the name of the requirements file (default: requirements.txt)" + ) + subparsers = parser.add_subparsers(dest="command", help="Available commands :\n\tpwp install [ ...]\n\tpwp uninstall [ ...]") + + # Install command + install_parser = subparsers.add_parser("install", help="Install packages") + install_parser.add_argument("packages", nargs="+", help="Package(s) to install") + + + # Uninstall command + uninstall_parser = subparsers.add_parser("uninstall", help="Uninstall packages") + uninstall_parser.add_argument("packages", nargs="+", help="Package(s) to uninstall") + + return parser + diff --git a/pwp/utils/requirements_manager.py b/pwp/utils/requirements_manager.py new file mode 100644 index 0000000..ec688e3 --- /dev/null +++ b/pwp/utils/requirements_manager.py @@ -0,0 +1,62 @@ +import os +from pip._internal.cli.main import main as pip_main +import subprocess + +def get_package_version(package): + if "==" in package: + return package + try: + # Run `pip show ` to get the version + result = subprocess.run(['pip', 'show', package], capture_output=True, text=True, check=True) + output = result.stdout + for line in output.splitlines(): + if line.startswith('Version:'): + print(f"{package} version: {line.split(':', 1)[1].strip()}") + return f"{package}=={line.split(':', 1)[1].strip()}" + except subprocess.CalledProcessError as e: + print(f"Error getting version for {package}: {e}") + return package + +def add_requirement(package_names, requirements_file = 'requirements.txt'): + if not os.path.exists(requirements_file): + with open(requirements_file, 'w') as f: + for package in package_names: + f.write(f"{get_package_version(package)}\n") + + print(f"Created {requirements_file} and added {', '.join(package_names)}") + else: + with open(requirements_file, 'r') as f: + existing_packages = set(line.strip() for line in f) + + new_packages = [pkg for pkg in package_names if pkg not in existing_packages] + + if new_packages: + with open(requirements_file, 'a') as f: + for package in new_packages: + f.write(f"{get_package_version(package)}\n") + print(f"Added {', '.join(new_packages)} to {requirements_file}") + + existing = set(package_names) & existing_packages + if existing: + print(f"Packages already in {requirements_file}: {', '.join(existing)}") + +def rm_requirement(package_names, requirements_file = 'requirements.txt'): + if os.path.exists(requirements_file): + with open(requirements_file, 'r') as f: + packages = set(line.strip().split("==")[0] for line in f) + + packages_to_remove = set(package_names) & packages + remaining_packages = packages - packages_to_remove + + with open(requirements_file, 'w') as f: + for package in remaining_packages: + f.write(f"{package}\n") + + if packages_to_remove: + print(f"Removed {', '.join(packages_to_remove)} from {requirements_file}") + + not_found = set(package_names) - packages + if not_found: + print(f"Packages not found in {requirements_file}: {', '.join(not_found)}") + else: + print(f"{requirements_file} not found") From c628dfe005c23fe6c75c6adfa1d62c8e5219c54c Mon Sep 17 00:00:00 2001 From: ABDELLAH-Hallou Date: Sun, 1 Sep 2024 15:56:56 +0100 Subject: [PATCH 2/5] __init__.py --- pwp/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pwp/__init__.py b/pwp/__init__.py index e69de29..7fb14f3 100644 --- a/pwp/__init__.py +++ b/pwp/__init__.py @@ -0,0 +1,2 @@ +from pwp.utils.pwp_manager import install, uninstall +from pwp.utils.pwp_parser import create_parser \ No newline at end of file From 4d82e0eeb147015e0a48569ef03d76acd18bc1d8 Mon Sep 17 00:00:00 2001 From: ABDELLAH-Hallou Date: Sun, 1 Sep 2024 15:59:48 +0100 Subject: [PATCH 3/5] ADD : MANIFEST.in --- MANIFEST.in | 1 + pwp/__init__.py | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..5ad7990 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include pwp/utils * \ No newline at end of file diff --git a/pwp/__init__.py b/pwp/__init__.py index 7fb14f3..e69de29 100644 --- a/pwp/__init__.py +++ b/pwp/__init__.py @@ -1,2 +0,0 @@ -from pwp.utils.pwp_manager import install, uninstall -from pwp.utils.pwp_parser import create_parser \ No newline at end of file From f6f308d6f13b7cdee91be027b3a33cb50cb81d4a Mon Sep 17 00:00:00 2001 From: ABDELLAH-Hallou Date: Sun, 1 Sep 2024 16:10:00 +0100 Subject: [PATCH 4/5] ADD : __init__ to utils --- pwp/utils/__init__.py | 0 setup.py | 1 + 2 files changed, 1 insertion(+) create mode 100644 pwp/utils/__init__.py diff --git a/pwp/utils/__init__.py b/pwp/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/setup.py b/setup.py index 8425acf..82325c4 100644 --- a/setup.py +++ b/setup.py @@ -34,6 +34,7 @@ def run(self): author_email='kaito.collabs@gmail.com', description='a pip wrapper that automatically manages requirements.txt', long_description=open('README.md').read(), + packages=find_packages(), long_description_content_type='text/markdown', url='https://github.com/merouanezouaid/pwp', classifiers=[ From 04f90a621596a63a19eaae87ce7ff405b3cb5fbb Mon Sep 17 00:00:00 2001 From: ABDELLAH-Hallou Date: Sun, 1 Sep 2024 16:14:42 +0100 Subject: [PATCH 5/5] wheels issue fixed --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 82325c4..8425acf 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,6 @@ def run(self): author_email='kaito.collabs@gmail.com', description='a pip wrapper that automatically manages requirements.txt', long_description=open('README.md').read(), - packages=find_packages(), long_description_content_type='text/markdown', url='https://github.com/merouanezouaid/pwp', classifiers=[