summaryrefslogtreecommitdiff
path: root/review.py
blob: 3c34eacfe46ebd660b85f9756060c5d9e2785873 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import sys
import os
import json
import subprocess
import re
from datetime import timedelta

# --- Configuration ---
HIGHLIGHT_SCRIPT_NAME = "highlight.py"
GOOD_DATASET_FILE = "dataset.jsonl"
BAD_FILES_LOG = "errors.txt"
PROGRESS_FILE = ".curation_progress.log"

# --- Unbuffered Input (Cross-Platform) ---
try:
    # Unix-like systems (Linux, macOS)
    import tty, termios
    def getch():
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch
except ImportError:
    # Windows
    import msvcrt
    def getch():
        return msvcrt.getch().decode()

# --- Main Curation Logic ---

def review_files(file_paths: list[str]):
    """
    Iterates through files, displays them for review, and sorts them based on user input.
    """
    if not os.path.exists(HIGHLIGHT_SCRIPT_NAME):
        print(f"Error: The visualization script '{HIGHLIGHT_SCRIPT_NAME}' was not found in this directory.")
        sys.exit(1)
        
    # Load the set of already processed files
    processed_files = set()
    if os.path.exists(PROGRESS_FILE):
        with open(PROGRESS_FILE, 'r', encoding='utf-8') as f:
            processed_files = {line.strip() for line in f}
    
    total_files = len(file_paths)
    for i, filepath in enumerate(file_paths):
        if filepath in processed_files:
            print(f"Skipping already processed file: {filepath}")
            continue

        print("-" * 80)
        print(f"Reviewing file ({i + 1}/{total_files}): {filepath}")

        # 1. Run highlight.py and pipe its output to the user's pager
        try:
            pager_cmd = os.environ.get("PAGER", "less").split()
            highlight_process = subprocess.Popen(
                ["python", HIGHLIGHT_SCRIPT_NAME, filepath],
                stdout=subprocess.PIPE,
                text=True,
                encoding='utf-8'
            )
            pager_process = subprocess.Popen(pager_cmd, stdin=highlight_process.stdout)
            highlight_process.stdout.close()
            return_code = pager_process.wait()
            if return_code != 0:
                print(f"Warning: Pager exited with code {return_code}.")
        except FileNotFoundError:
            print(f"Error: Pager command not found. Is '{os.environ.get('PAGER', 'less')}' installed?")
            continue
        except Exception as e:
            print(f"An error occurred while running the subprocess: {e}")
            continue

        # 2. Prompt for user decision
        while True:
            print("\nWas this file's labeling correct? (y/n): ", end="", flush=True)
            choice = getch().lower()
            print(choice)

            if choice == 'y':
                print(f" -> Appending {filepath} to {GOOD_DATASET_FILE}")
                try:
                    with open(filepath, 'r', encoding='utf-8') as infile, \
                         open(GOOD_DATASET_FILE, 'a', encoding='utf-8') as outfile:
                        for line in infile:
                            outfile.write(line)
                except Exception as e:
                    print(f"Error appending to dataset file: {e}")
                break
            elif choice == 'n':
                print(f" -> Logging {filepath} to {BAD_FILES_LOG}")
                try:
                    with open(BAD_FILES_LOG, 'a', encoding='utf-8') as errfile:
                        errfile.write(filepath + '\n')
                except Exception as e:
                    print(f"Error writing to log file: {e}")
                break
            elif choice in ['\x03', 'q']: # Handle Ctrl+C or 'q' to quit
                print("\nExiting review process.")
                sys.exit(0)
            else:
                print("Invalid input. Please press 'y' for yes or 'n' for no.")

        # Log the file as processed after a decision has been made
        with open(PROGRESS_FILE, 'a', encoding='utf-8') as f:
            f.write(filepath + '\n')

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python curate_dataset.py <file1.jsonl> <file2.jsonl> ...")
        print("Or: python curate_dataset.py /path/to/*/*.jsonl")
        sys.exit(1)
        
    review_files(sys.argv[1:])
    print("-" * 80)
    print("Curation complete.")