Module paroxython.cli_recommend
Read and execute a pipeline of commands and report the learning costs.
Usage
paroxython recommend [options] DB_PATH
Description
Requires an existing database previously generated by the command: paroxython collect DIRECTORY ... and a pipeline of commands describing which concepts (taxa) are already known, which ones need to be illustrated or must be avoided. By default, it results in a list of recommended programs, along with their total learning costs and the individual learning cost of each of the concepts they feature. These results are presented in Markdown format. With the option `-o stdout` the program list is simply printed to stdout.
Shortcut
For DB_PATH, instead of the path of a tag database, you can provide the DIRECTORY previously collected. Paroxython will automatically look for the tag database at DIRECTORY/../DIRECTORY_db.json.
Options
-b --base=PATH Value accessible, with the syntax "{base}", by any shell command of the pipeline. If not specified, this is the parent directory of DB_PATH. [default: ] -c --cost=STR Learning cost assessment strategy. [default: zeno] Currently available: • zeno: the i-th edge of a taxon, if not already imparted, costs 2^(-i). For instance, the taxon old/new/new will costs 2^-2 + 2^-3 = 0.375. • linear: simply count the number of new edges. -o --output=PATH The path of the resulting report. If it is omitted, a value of PREFIX_recommendations.md is inferred from the path PREFIX_db.json of DB_PATH. If it is STDOUT, the sorted list of recommended (but not hidden) programs, is printed on the standard output. [default: ] -p --pipe=PATH Path of the command pipeline. If it is omitted, a value of PREFIX_pipe.py is inferred from the path PREFIX_db.json of DB_PATH. If is is <code>\[]</code>, no filter is applied. [default: ] -f --format=STR The format of program titles in the report. This string can contains the following identifiers (between braces): • name: filename of the program. • path: program key in the DB "programs" dictionary. • prefix: name of DB_PATH, minus any "_db.json" suffix. • absolute: absolute path to DB_PATH's parent folder. • relative: relative path to DB_PATH's parent folder. Shortcut: if format is "vscode", makes program names to be clickable and opening in VS Code. [default: `{name}`]
Example
Use `-o stdout` to pipe the results into another shell command. For instance, let's assume that: - your program repository is `path/to/programs`; - your tag database is at its default location `path/to/programs_db.json`; - your pipeline is at its default location `path/to/programs_pipe.py`. Then, to copy (not move) all the recommended programs to an existing directory DEST, just do: paroxython recommend -o stdout path/to/programs_db.json \ | xargs -I {} sh -c "cp path/to/programs/{} DEST"
Expand source code Browse GitHub
import json
import sys
from pathlib import Path
import regex # type: ignore
from ast import literal_eval
from .goodies import print_success, print_exit
from .recommend_programs import Recommendations
def cli_wrapper(args):
db_path = Path(args["DB_PATH"])
if not db_path.exists():
print_exit(f"no file or directory at '{db_path.absolute()}': aborted.")
parent_path = db_path.parent
if db_path.is_dir():
for suffix in ("_db", "-db"):
db_path = parent_path / f"{db_path.name}{suffix}.json"
if db_path.is_file():
print(f"Using database '{db_path}'.")
break
else:
print_exit(f"unable to locate a tag database in '{parent_path}': aborted.")
m = regex.fullmatch(r"(.+[_-])db\.json", db_path.name)
prefix = m[1] if m else ""
pipeline_path = Path(args["--pipe"] or parent_path / f"{prefix}pipe.py")
if pipeline_path.is_file():
print(f"Using pipeline '{pipeline_path}'.")
try:
commands = literal_eval(pipeline_path.read_text())
except Exception: # Too many possible exceptions
print_exit(f"Malformed pipeline: aborted.")
elif args["--pipe"] == "[]":
print("Using an empty pipeline.")
commands = []
else:
print_exit(f"No pipeline at '{pipeline_path}': aborted.")
stdout_backup = sys.stdout
if args["--output"].upper() == "STDOUT":
sys.stdout = sys.stderr
title_format = args["--format"]
if title_format.lower() == "vscode":
title_format = "[`{name}`](vscode://file/{absolute}/{prefix}/{path})"
title_format = title_format.format(
name="{name}",
path="{path}",
prefix=prefix.rstrip("_-"),
absolute=parent_path.resolve(),
relative=parent_path,
)
rec = Recommendations(
db=json.loads(db_path.read_text()),
base_path=Path(args["--base"] or parent_path),
assessment_strategy=args["--cost"],
title_format=title_format,
)
rec.run_pipeline(commands)
if args["--output"].upper() == "STDOUT":
sys.stdout = stdout_backup
return print("\n".join(sorted(rec.selected_programs - rec.hidden_programs)))
output_path = Path(args["--output"] or parent_path / f"{prefix}recommendations.md")
output_path.write_text(rec.get_markdown())
print_success(f"Dumped: {output_path.resolve()}\n")
Functions
def cli_wrapper(args)
-
Expand source code Browse GitHub
def cli_wrapper(args): db_path = Path(args["DB_PATH"]) if not db_path.exists(): print_exit(f"no file or directory at '{db_path.absolute()}': aborted.") parent_path = db_path.parent if db_path.is_dir(): for suffix in ("_db", "-db"): db_path = parent_path / f"{db_path.name}{suffix}.json" if db_path.is_file(): print(f"Using database '{db_path}'.") break else: print_exit(f"unable to locate a tag database in '{parent_path}': aborted.") m = regex.fullmatch(r"(.+[_-])db\.json", db_path.name) prefix = m[1] if m else "" pipeline_path = Path(args["--pipe"] or parent_path / f"{prefix}pipe.py") if pipeline_path.is_file(): print(f"Using pipeline '{pipeline_path}'.") try: commands = literal_eval(pipeline_path.read_text()) except Exception: # Too many possible exceptions print_exit(f"Malformed pipeline: aborted.") elif args["--pipe"] == "[]": print("Using an empty pipeline.") commands = [] else: print_exit(f"No pipeline at '{pipeline_path}': aborted.") stdout_backup = sys.stdout if args["--output"].upper() == "STDOUT": sys.stdout = sys.stderr title_format = args["--format"] if title_format.lower() == "vscode": title_format = "[`{name}`](vscode://file/{absolute}/{prefix}/{path})" title_format = title_format.format( name="{name}", path="{path}", prefix=prefix.rstrip("_-"), absolute=parent_path.resolve(), relative=parent_path, ) rec = Recommendations( db=json.loads(db_path.read_text()), base_path=Path(args["--base"] or parent_path), assessment_strategy=args["--cost"], title_format=title_format, ) rec.run_pipeline(commands) if args["--output"].upper() == "STDOUT": sys.stdout = stdout_backup return print("\n".join(sorted(rec.selected_programs - rec.hidden_programs))) output_path = Path(args["--output"] or parent_path / f"{prefix}recommendations.md") output_path.write_text(rec.get_markdown()) print_success(f"Dumped: {output_path.resolve()}\n")