From c3eb2a6109725c1b3ab93d66a052f0ecf746ae00 Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Sat, 25 Mar 2023 15:25:49 -0600 Subject: [PATCH] feat: get site-packages dir dynamically --- CHANGELOG.md | 88 +++++++++++++++++++++++--------------------- README.md | 18 ++++++--- pip_tree/__init__.py | 2 + pip_tree/cli.py | 5 ++- pip_tree/tree.py | 8 +++- setup.py | 2 +- 6 files changed, 70 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab3eecd..73572f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,73 +1,77 @@ # CHANGELOG +## v2.1.0 (2023-03-25) + +- Makes the `path` CLI arg optional, the default value is now the virtual environment that Pip Tree is running from meaning that you can install Pip Tree to a project and run it without needing to specify the `site-packages` directory explicitly + ## 2.0.2 (2021-12-02) -* Adds `mypy` type checking and fixes types -* Fixes a potential bug when regex pattern matching on package names would result in `None` +- Adds `mypy` type checking and fixes types +- Fixes a potential bug when regex pattern matching on package names would result in `None` ## v2.0.1 (2021-11-25) -* Small bug fix to change the types of functions available in the `__all__` variable to strings +- Small bug fix to change the types of functions available in the `__all__` variable to strings ## v2.0.0 (2021-11-25) -* Refactored code - * Unwrapped functions from `PipTree` class, exposed them outside the package - * Removed an entire loop and function, now Pip Tree will run even faster - * Broke out `cli` logic to a separate module - * Use smarter enumeration for package count -* Added type hinting -* Updated documentation +- Refactored code + - Unwrapped functions from `PipTree` class, exposed them outside the package + - Removed an entire loop and function, now Pip Tree will run even faster + - Broke out `cli` logic to a separate module + - Use smarter enumeration for package count +- Added type hinting +- Updated documentation ## v1.1.0 (2021-09-20) -* Drops support for Python 3.6 -* Removes unused `mock` library +- Drops support for Python 3.6 +- Removes unused `mock` library ## v1.0.0 (2021-05-13) -* Switched from shelling out to Pip to using the internal Pip API natively via Python (closes #4 and closes #2), this change makes the previous ~1 minute operation now take ~1 second! -* Adds `updated` field indicating when the package was installed or updated (closes #5) -* The `requires` and `required-by` keys are now lists instead of comma separated strings, they also include the version the requirements are pinned to -* Using `argparse` instead of environment variable to specify path to site-packages -* Separated out code better into classes and additional functions -* 100% code coverage -* Converted classmethods to staticmethods +- Switched from shelling out to Pip to using the internal Pip API natively via Python (closes #4 and closes #2), this change makes the previous ~1 minute operation now take ~1 second! +- Adds `updated` field indicating when the package was installed or updated (closes #5) +- The `requires` and `required-by` keys are now lists instead of comma separated strings, they also include the version the requirements are pinned to +- Using `argparse` instead of environment variable to specify path to site-packages +- Separated out code better into classes and additional functions +- 100% code coverage +- Converted classmethods to staticmethods ## v0.5.0 (2020-11-24) -* Removes pip version warnings from output -* Fixes `local variable 'i' referenced before assignment` error -* Matching pip command timeout by setting the subprocess timeout to 15 from 10 seconds -* Running pip commands in isolated mode which ignores custom configuration -* Running pip commands while skipping user input (if ever applicable) -* Small speed improvements were made by shifting logic around +- Removes pip version warnings from output +- Fixes `local variable 'i' referenced before assignment` error +- Matching pip command timeout by setting the subprocess timeout to 15 from 10 seconds +- Running pip commands in isolated mode which ignores custom configuration +- Running pip commands while skipping user input (if ever applicable) +- Small speed improvements were made by shifting logic around ## v0.4.0 (2020-11-24) -* Fixed reference of `PIPPIN_PIP` to `PIP_PATH` now that the package has been renamed -* Removed unused pip variables in favor of the constant `PIP_PATH` -* Updated documentation +- Fixed reference of `PIPPIN_PIP` to `PIP_PATH` now that the package has been renamed +- Removed unused pip variables in favor of the constant `PIP_PATH` +- Updated documentation ## v0.3.0 (2020-11-16) -* Refactored Pippin from a shell script to a Python script -* Now retrieve the pip list as JSON -* Now retrieve the pip package details as RFC-compliant mail header format -* Now with Python, we shell out to pip and run the commands but retrieve the data as machine parseable instead of human readable and chopping it up after the fact -* Added unit tests, updated docs, added Makefile -* Changed name from `Pippin` to `Pip Tree`... stupid PyPi naming rules +- Refactored Pippin from a shell script to a Python script +- Now retrieve the pip list as JSON +- Now retrieve the pip package details as RFC-compliant mail header format +- Now with Python, we shell out to pip and run the commands but retrieve the data as machine parseable instead of human readable and chopping it up after the fact +- Added unit tests, updated docs, added Makefile +- Changed name from `Pippin` to `Pip Tree`... stupid PyPi naming rules ## v0.2.0 (2020-11-12) -* Added the version number of the packages to the output -* Removed redundant file deletion to boost performance and decrease file manipulation calls -* Added documentation to better explain what each function does -* Small tweaks throughout +- Added the version number of the packages to the output +- Removed redundant file deletion to boost performance and decrease file manipulation calls +- Added documentation to better explain what each function does +- Small tweaks throughout ## v0.1.0 (2020-11-10) -* Initial release -* Pippin will generate a report of the dependency breakdown of your Python virtual environment -* Pippin will say the number of dependencies in an environment -* Pippin will take an optional argument allowing you to specify which virtual environment (path to pip) to use +- Initial release +- Pippin will generate a report of the dependency breakdown of your Python virtual environment +- Pippin will say the number of dependencies in an environment +- Pippin will take an optional argument allowing you to specify which virtual environment (path to pip) to use diff --git a/README.md b/README.md index 12ab156..746c795 100644 --- a/README.md +++ b/README.md @@ -18,25 +18,31 @@ There is no simple, native way to get the dependency tree of a Python virtual en ## Install ```bash -# Install Pip Tree +# Install Pip Tree globally pip3 install pip-tree +# Install Pip Tree into the virtual environment of the project you want to run it on +venv/bin/pip install pip-tree + # Install locally make install ``` ## Usage -``` -Usage: +```text +Virtual Env Usage: + pip-tree + +Global Usage: pip-tree --path "path/to/my_project/venv/lib/python3.9/site-packages" Options: -h, --help show this help message and exit - -p PATH, --path PATH The path to the site-packages directory of a Python virtual environment. + -p PATH, --path PATH The path to the site-packages directory of a Python virtual environment. If a path is not provided, the virtual environment Pip Tree is run from will be used. ``` -**Sample Output** +### Sample Output ```bash Generating Pip Tree Report... @@ -79,7 +85,7 @@ Generating Pip Tree Report... Pip Tree report complete! 40 dependencies found for "path/to/my_project/venv/lib/python3.9/site-packages". ``` -**Package** +### Package In addition to the CLI tool, you can use functions to retrieve the list of packages and their details from a Python virtual environment in your own code: diff --git a/pip_tree/__init__.py b/pip_tree/__init__.py index 4fe0958..096cc48 100644 --- a/pip_tree/__init__.py +++ b/pip_tree/__init__.py @@ -1,4 +1,6 @@ +# flake8: noqa from pip_tree.tree import ( + SITE_PACKAGES_PATH, generate_pip_tree, get_package_details, get_pip_package_list, diff --git a/pip_tree/cli.py b/pip_tree/cli.py index cf5d1a6..fd26fb8 100644 --- a/pip_tree/cli.py +++ b/pip_tree/cli.py @@ -12,9 +12,10 @@ def __init__(self): parser.add_argument( '-p', '--path', - required=True, + required=False, + default=pip_tree.SITE_PACKAGES_PATH, type=str, - help='The path to the site-packages directory of a Python virtual environment.', + help='The path to the site-packages directory of a Python virtual environment. If a path is not provided, the virtual environment Pip Tree is run from will be used.', # noqa ) parser.parse_args(namespace=self) diff --git a/pip_tree/tree.py b/pip_tree/tree.py index 9343b6d..a523092 100644 --- a/pip_tree/tree.py +++ b/pip_tree/tree.py @@ -1,6 +1,7 @@ import datetime import os import re +import sysconfig import time from typing import ( Any, @@ -13,7 +14,10 @@ import pkg_resources -def generate_pip_tree(path: str) -> Tuple[List[Dict[str, Any]], int]: +SITE_PACKAGES_PATH = sysconfig.get_paths()['platlib'] + + +def generate_pip_tree(path: str = SITE_PACKAGES_PATH) -> Tuple[List[Dict[str, Any]], int]: """Generate the Pip Tree of the virtual environment specified.""" pip_tree_results = [] required_by_data: Dict[str, List[str]] = {} @@ -35,7 +39,7 @@ def generate_pip_tree(path: str) -> Tuple[List[Dict[str, Any]], int]: return final_output, package_count -def get_pip_package_list(path: str) -> Generator[pkg_resources.Distribution, None, None]: +def get_pip_package_list(path: str = SITE_PACKAGES_PATH) -> Generator[pkg_resources.Distribution, None, None]: """Get the Pip package list of a Python virtual environment. Must be a path like: /project/venv/lib/python3.9/site-packages diff --git a/setup.py b/setup.py index bf88e16..e8cb307 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ setuptools.setup( name='pip-tree', - version='2.0.2', + version='2.1.0', description='Get the dependency tree of your Python virtual environment via Pip.', long_description=long_description, long_description_content_type="text/markdown",