From 5debd445725c5634e83d5de5a969dcc0177f4071 Mon Sep 17 00:00:00 2001 From: "Jules Lasne (jlasne)" Date: Thu, 13 Dec 2018 23:57:35 +0100 Subject: [PATCH] Version 0.0.1 --- LICENSE | 2 +- README.md | 13 ++++ potodo/__init__.py | 3 + potodo/__main__.py | 1 + potodo/potodo.py | 169 +++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 2 + setup.py | 35 ++++++++++ 7 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 potodo/__init__.py create mode 100644 potodo/__main__.py create mode 100644 potodo/potodo.py create mode 100644 requirements.txt create mode 100644 setup.py diff --git a/LICENSE b/LICENSE index 20cb188..e0a8e27 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Jules Lasne (jlasne) +Copyright (c) 2018 Jules Lasne (jlasne - seluj78) jules.lasne@gmail.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index dd78e3e..1cb8d2b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,15 @@ # Potodo Potodo, a Flawless TODO/progress listing CLI tool for po files + +## Installation + +```bash +pip install potodo +``` + +## Usage + +```bash +potodo -p PATH -r ORG/REPO +``` +This will run potodo in the given `PATH` and search for open issues on `github.com/ORG/REPO` \ No newline at end of file diff --git a/potodo/__init__.py b/potodo/__init__.py new file mode 100644 index 0000000..a9b2ec5 --- /dev/null +++ b/potodo/__init__.py @@ -0,0 +1,3 @@ +__author__ = """Jules Lasne""" +__email__ = "jules.lasne@gmail.com" +__version__ = "0.0.1" \ No newline at end of file diff --git a/potodo/__main__.py b/potodo/__main__.py new file mode 100644 index 0000000..259d881 --- /dev/null +++ b/potodo/__main__.py @@ -0,0 +1 @@ +__import__("potodo.potodo").potodo.main() \ No newline at end of file diff --git a/potodo/potodo.py b/potodo/potodo.py new file mode 100644 index 0000000..f5585a4 --- /dev/null +++ b/potodo/potodo.py @@ -0,0 +1,169 @@ +#!/bin/python3 + +import sys +import argparse +import statistics + +from pathlib import Path + +try: + import polib + import requests +except ImportError: + print("You need to install polib and requests to be able to run potodo.") + sys.exit(1) + + +def get_gh_issue_reservation(repo: str): + """ + TODO: Try except if repo unvalid + + Will query given repo and get all issues and return a list of reservations + + :param repo: The repository to query on the API + + :return: Returns a dict containing all issues with `title:login` + """ + + issues = requests.get( + "https://api.github.com/repos/" + repo + "/issues" + ).json() + reservations = { + issue["title"].split()[-1].lower(): issue["user"]["login"] for issue in issues + } + return reservations + + +def get_po_files_from_path(path: str): + """ + TODO: Try except if path unvalid + + Will get all po files from given path + + :param path: The path to search `po` files for + + :return: Returns a dict will the folder and the po files in it + """ + + po_files = [file for file in Path(path).glob("**/*.po") if ".git/" not in str(file)] + + po_files_per_directory = { + path.parent.name: set(path.parent.glob("*.po")) for path in po_files + } + return po_files_per_directory + + +def exec_potodo(path: str, above: int, below: int, repo: str): + """ + Will run everything based on the given parameters + + :param path: The path to search into + :param above: The above threshold + :param below: The below threshold + :param repo: The repository to query for issues + """ + + if not above and below: + is_all = False + is_above = False + is_below = True + elif not below and above: + is_all = False + is_above = True + is_below = False + elif not below and not above: + is_all = True + is_above = False + is_below = False + else: + raise ValueError("Unexpected error occuped when processing values for above and below.") + + if repo: + issue_reservations = get_gh_issue_reservation(repo) + else: + issue_reservations = None + + po_files_per_directory = get_po_files_from_path(path) + + for directory, po_files in sorted(po_files_per_directory.items()): + buffer = [] + folder_stats = [] + printed_list = [] + for po_file in sorted(po_files): + po_file_stats = polib.pofile(po_file) + po_file_stat_percent = po_file_stats.percent_translated() + if po_file_stat_percent == 100: + folder_stats.append(po_file_stat_percent) + printed_list.append(False) + continue + if not is_all: + if is_above: + if int(po_file_stat_percent) < above: + folder_stats.append(po_file_stat_percent) + printed_list.append(False) + continue + elif is_below: + if int(po_file_stat_percent) > below: + folder_stats.append(po_file_stat_percent) + printed_list.append(False) + continue + else: + raise ValueError("Unexpected error: is_above/is_below values shouldn't be like this") + + t = str(po_file).split('/')[-2:] + po_file_name = t[0] + '/' + t[1] + + buffer.append( + f"- {po_file.name:<30} " + + f"{len(po_file_stats.translated_entries()):3d} / {len(po_file_stats):3d} " + + f"({po_file_stat_percent:5.1f}% translated)" + + ( + f", {len(po_file_stats.fuzzy_entries())} fuzzy" + if po_file_stats.fuzzy_entries() + else "" + ) + + ( + f", réservé par {issue_reservations[po_file_name.lower()]}" + if po_file_name.lower() in issue_reservations + else "" + ) + ) + folder_stats.append(po_file_stat_percent) + printed_list.append(True) + if True in printed_list: + print(f"\n\n# {directory} ({statistics.mean(folder_stats):.2f}% done)\n") + print("\n".join(buffer)) + + +def main(): + """ + TODO: Add variable to skip github issues + TODO: Remove requirement of -r and fetch the repo name manually + TODO: Add json output possibility + TODO: -l for path line by line --matching-files + TODO: classify ? + TODO: Make it so you can specify both: list todos above 50 but below 60 (between 50 and 60) + """ + + parser = argparse.ArgumentParser( + prog="potodo", + description="List and prettify the po files left to translate", + ) + + parser.add_argument("-p", "--path", type=str, + help="REQUIRED: Execute Potodo in the given path", required=True) + + parser.add_argument("-r", "--repo", type=str, + help="REQUIRED: Repo in the form of ORG/REPO to display if translation is reserved in issues", required=True) + + group = parser.add_mutually_exclusive_group() + group.add_argument('-a', '--above', type=int, help="Will list all TODOs ABOVE given INT%% completion") + group.add_argument('-b', '--below', type=int, help="Will list all TODOs BELOW given INT%% completion") + + args = parser.parse_args() + if not args.path: + path = '.' + else: + path = str(args.path) + + exec_potodo(path, args.above, args.below, args.repo) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..966d4b9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +polib +requests \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..9bc4905 --- /dev/null +++ b/setup.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 + +import setuptools + +with open("README.md") as readme: + long_description = readme.read() + +setuptools.setup( + name="potodo", + version="0.0.1", + description="Will list all .po files that are to be transated", + long_description=long_description, + long_description_content_type="text/markdown", # This is important! + author="Jules Lasne", + author_email="jules.lasne@gmail.com", + url="https://github.com/seluj78/potodo", + packages=["potodo"], + package_dir={"potodo": "potodo"}, + entry_points={"console_scripts": ["potodo=potodo.potodo:main"]}, + include_package_data=True, + install_requires=["polib", 'requests'], + license="MIT license", + zip_safe=False, + keywords="potodo", + classifiers=[ + "Development Status :: 2 - Pre-Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + ], +)