Created
October 4, 2024 13:37
-
-
Save ErikKalkoken/526e54215475bc794fe425d0a0dfcb85 to your computer and use it in GitHub Desktop.
Find_apps is a command line tool to identify Django apps in a Python package
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Find_apps is a command line tool to identify all Django apps in a Python package. | |
The tools will look for and parse AppConfig definitions in apps.py files. | |
Django apps which do not have an apps.py file will not be recognized. | |
usage: find_apps.py [-h] [-path PATH] [-hide-name] | |
options: | |
-h, --help show this help message and exit | |
-path PATH, -p PATH starting path (default: .) | |
-hide-name do not show app names (default: False) | |
""" | |
import argparse | |
import re | |
from pathlib import Path | |
from typing import NamedTuple | |
class AppConfig(NamedTuple): | |
name: str | |
label: str | |
def main(): | |
parser = argparse.ArgumentParser( | |
formatter_class=argparse.ArgumentDefaultsHelpFormatter | |
) | |
parser.add_argument("-path", "-p", default=".", help="starting path") | |
parser.add_argument("-hide-name", action='store_true', help="do not show app names") | |
args = parser.parse_args() | |
start = Path(args.path).absolute() | |
print(f"Looking for Django apps at: {start}") | |
apps = find_apps(start) | |
if args.hide_name: | |
for a in apps: | |
print(a.label) | |
else: | |
label_width = max_label_width(apps) | |
for a in apps: | |
print(f"{a.label:{label_width}} {a.name}") | |
def find_apps(start: Path) -> list[AppConfig]: | |
apps = [] | |
for p in start.rglob("apps.py"): | |
text = p.read_text() | |
if "AppConfig" not in text: | |
continue | |
ac = extract_config(text) | |
if ac == "": | |
print(f"ERROR: failed to determine label for {p}") | |
apps.append(ac) | |
apps.sort(key=lambda x:x.label) | |
return apps | |
def extract_config(text: str) -> AppConfig: | |
m = re.search(r"name\s*=\s*[\"']([\w.]+)[\"']", text) | |
if m is None: | |
return "" | |
name = m.group(1) | |
parts = name.split(".") | |
label = parts.pop() | |
m = re.search(r"label\s*=\s*[\"'](\w+)[\"']", text) | |
if m is not None: | |
label = m.group(1) # label defined | |
return AppConfig(name=name, label=label) | |
def max_label_width(apps): | |
w = 0 | |
for a in apps: | |
w = max(w, len(a.label)) | |
return w | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment