Skip to content

Commit

Permalink
feat: support output for unused requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
agusmakmun committed Apr 5, 2024
1 parent 85997fd commit 472fe51
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 38 deletions.
35 changes: 28 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,40 @@ pip3 install scanreq

## Usage

> **Note:** Ensure you're working on python environment.
```console
(env-myproject) ➜ myproject git:(development) ✗ scanreq -r requirements.txt -p .
scanreq -r requirements.txt -p . -o unused-requirements.txt
```

```
[i] Please wait! It may take few minutes to complete...
[i] Scanning unused packages:
1. Module: rcssmin ---> Package: rcssmin
2. Module: model_utils ---> Package: django-model-utils
3. Module: pinax_theme_bootstrap ---> Package: pinax-theme-bootstrap
4. Module: phonenumbers ---> Package: phonenumbers
1. Module: rcssmin -> Package: rcssmin
2. Module: model_utils -> Package: django-model-utils
3. Module: pinax_theme_bootstrap -> Package: pinax-theme-bootstrap
4. Module: phonenumbers -> Package: phonenumbers
```

```console
cat unused-requirements.txt
```

```
rcssmin
django-model-utils
pinax-theme-bootstrap
phonenumbers
```

Cool right? 😎

```console
(env-myproject) ➜ myproject git:(development) ✗ scanreq --help
usage: scan.py [-h] [-r REQUIREMENTS] [-p PATH]
scanreq --help
```

```
usage: scan.py [-h] [-r REQUIREMENTS] [-p PATH] [-o OUTPUT]
Scan for unused Python packages.
Expand All @@ -61,6 +79,8 @@ optional arguments:
-r REQUIREMENTS, --requirements REQUIREMENTS
Path to the requirements.txt file to read packages from.
-p PATH, --path PATH Project path to scan for unused packages (default: current directory).
-o OUTPUT, --output OUTPUT
Path to the output file where unused packages will be saved.
```

> **Note:** Don't forget to cross-check the unused packages after finding them,
Expand All @@ -73,6 +93,7 @@ optional arguments:
- [x] Support argument parser (command arguments)
- [x] Directory to scan
- [x] Requirement file to scan
- [x] Option to write the output of unused packages
- [ ] Option to auto replace the package from requirements.txt file
- [ ] Option to exclude or ignore some packages
- [x] Support CLI - make it as a command
Expand Down
6 changes: 6 additions & 0 deletions docs/build-publish.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ $ hatch new scanreq
$ hatch run test -vv
```

Executing the script:

```console
$ hatch run python src/scanreq/__main__.py -r requirements.txt -p .
```


### 3. Versioning

Expand Down
2 changes: 1 addition & 1 deletion src/scanreq/__about__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.0.6"
__version__ = "0.0.7"
43 changes: 13 additions & 30 deletions src/scanreq/__main__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import argparse
from typing import List

from scanreq.scanner import (
get_main_packages,
read_requirements,
search_string_in_python_files,
)
from scanreq.scanner import scan


def main():
Expand All @@ -24,32 +19,20 @@ def main():
default=".",
help="Project path to scan for unused packages (default: current directory).",
)
parser.add_argument(
"-o",
"--output",
type=str,
default=None,
help="Path to the output file where unused packages will be saved.",
)
args = parser.parse_args()
project_path: str = args.path
requirement_file: str = args.requirements

print("\n[i] Please wait! It may take few minutes to complete...")

main_packages: dict = get_main_packages()
package_names: List[str] = read_requirements(requirement_file)

print("[i] Scanning unused packages:")
unused_packages: List[str] = []
number: int = 1
for package_name in package_names:
for module_name, package_names in main_packages.items():
if package_name in package_names:
results: list = search_string_in_python_files(project_path, module_name)
if not results and (module_name not in unused_packages):
unused_packages.append(package_name)
print(
f" {number}. Module: {module_name} ---> Package: {package_name}"
)
number += 1

if len(unused_packages) < 1:
print("[i] Great! No unused packages found.")
return unused_packages
scan(
requirement_file=args.requirements,
project_path=args.path,
output_path=args.output,
)


if __name__ == "__main__":
Expand Down
41 changes: 41 additions & 0 deletions src/scanreq/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
".cfg",
".yml",
".yaml",
"Dockerfile",
)


Expand Down Expand Up @@ -126,3 +127,43 @@ def read_requirements(file_path: str) -> List[str]:
package_name: str = line.split("==")[0].strip().lower()
package_names.append(package_name)
return package_names


def scan(requirement_file: str, project_path: str, output_path: str = None) -> None:
"""
A function that scans for unused packages in a project based on a given requirements file.
Parameters:
- requirement_file (str): the path to the requirements file to be scanned.
- project_path (str): the path to the project to be scanned.
- output_path (str, optional): the path to the output file where unused packages will be saved. Defaults to None.
Returns:
- None
"""
print("\n[i] Please wait! It may take few minutes to complete...")

package_names: List[str] = read_requirements(requirement_file)
main_packages: dict = get_main_packages()

print("[i] Scanning unused packages:")
unused_packages: List[str] = []
number: int = 1
for package_name in package_names:
for module_name, package_names in main_packages.items():
if package_name in package_names:
results: list = search_string_in_python_files(project_path, module_name)
if not results and (module_name not in unused_packages):
unused_packages.append(package_name)
number_str: str = f"{number}."
print(
f" {number_str: <4}Module: {module_name: <30}-> Package: {package_name}"
)
number += 1

if len(unused_packages) < 1:
print("[i] Great! No unused packages found.")

elif unused_packages and output_path:
with open(output_path, "w") as _file:
_file.writelines("\n".join(unused_packages) + "\n")

0 comments on commit 472fe51

Please sign in to comment.