spark: Add line_counter.py utility for counting lines and CSV fields
This commit is contained in:
1 parent
4e509f1343
commit
6b5197bf37
5 files changed
+129
-58
No files matched your search
@@ -147,4 +147,33 @@ python3 json_schema_validator.py <schema_file.json> <data_file.json>
|
|||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
Check: python3 /root/.hermes/wizard-outputs/spark/json_schema_validator.py test_schema.json test_data_valid.json && echo "PASS"
|
Check: python3 /root/.hermes/wizard-outputs/spark/json_schema_validator.py test_schema.json test_data_valid.json && echo "PASS"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Line Counter Utility (spark/artifact)
|
||||||
|
|
||||||
|
A simple Python utility for counting lines in files and fields in CSV files.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- **line_counter.py** - Main script (1,542 bytes)
|
||||||
|
- **test_data.csv** - Test CSV file with 5 comma-separated items
|
||||||
|
- **test_log.txt** - Test log file with 10 lines
|
||||||
|
- **test_line_counter.py** - Test script verifying functionality
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 line_counter.py <filepath> <mode>
|
||||||
|
```
|
||||||
|
|
||||||
|
Modes:
|
||||||
|
- `count` - Count total lines in a file
|
||||||
|
- `csv` - Count items in comma-separated line (first row)
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
VERDICT: Utility correctly counts lines and CSV fields with proper error handling
|
||||||
|
|
||||||
|
CHECK: python3 /root/troupe-standup/wizard-work/spark/test_line_counter.py
|
||||||
@@ -1,66 +1,48 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Count lines in Python files - a simple verification utility."""
|
"""Line counter utility - counts lines in a file."""
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
def count_lines(filepath):
|
||||||
|
"""Count lines in a file, return -1 if file doesn't exist or is unreadable."""
|
||||||
|
try:
|
||||||
|
with open(filepath, 'r') as f:
|
||||||
|
return sum(1 for _ in f)
|
||||||
|
except (FileNotFoundError, PermissionError, IOError):
|
||||||
|
return -1
|
||||||
|
|
||||||
def count_python_lines(directory: str) -> dict:
|
def count_comma_separated(filepath):
|
||||||
"""Count total lines, code lines, and comment lines in Python files."""
|
"""Count items in a comma-separated file (first row, count commas + 1)."""
|
||||||
total_lines = 0
|
try:
|
||||||
code_lines = 0
|
with open(filepath, 'r') as f:
|
||||||
comment_lines = 0
|
first_line = f.readline().strip()
|
||||||
files_count = 0
|
if not first_line:
|
||||||
|
return 0
|
||||||
dir_path = Path(directory)
|
return len(first_line.split(','))
|
||||||
if not dir_path.exists():
|
except (FileNotFoundError, PermissionError, IOError):
|
||||||
return {"error": f"Directory not found: {directory}"}
|
return -1
|
||||||
|
|
||||||
for py_file in dir_path.rglob("*.py"):
|
|
||||||
try:
|
|
||||||
with open(py_file, 'r', encoding='utf-8') as f:
|
|
||||||
lines = f.readlines()
|
|
||||||
files_count += 1
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
stripped = line.strip()
|
|
||||||
total_lines += 1
|
|
||||||
if stripped.startswith('#'):
|
|
||||||
comment_lines += 1
|
|
||||||
elif stripped:
|
|
||||||
code_lines += 1
|
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return {
|
|
||||||
"directory": str(dir_path.resolve()),
|
|
||||||
"python_files": files_count,
|
|
||||||
"total_lines": total_lines,
|
|
||||||
"code_lines": code_lines,
|
|
||||||
"comment_lines": comment_lines,
|
|
||||||
"empty_lines": total_lines - code_lines - comment_lines
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
def main():
|
if len(sys.argv) != 3:
|
||||||
if len(sys.argv) < 2:
|
print(f"Usage: {sys.argv[0]} <filepath> <mode>", file=sys.stderr)
|
||||||
print("Usage: line_counter.py <directory>")
|
print("Modes: count (lines), csv (fields)", file=sys.stderr)
|
||||||
print("Counts lines in Python files recursively")
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
result = count_python_lines(sys.argv[1])
|
filepath = sys.argv[1]
|
||||||
|
mode = sys.argv[2]
|
||||||
|
|
||||||
if "error" in result:
|
if mode == 'count':
|
||||||
print(f"Error: {result['error']}")
|
result = count_lines(filepath)
|
||||||
sys.exit(1)
|
if result == -1:
|
||||||
|
print(f"ERROR: Cannot read file '{filepath}'", file=sys.stderr)
|
||||||
print(f"Python files: {result['python_files']}")
|
sys.exit(2)
|
||||||
print(f"Total lines: {result['total_lines']}")
|
print(result)
|
||||||
print(f"Code lines: {result['code_lines']}")
|
elif mode == 'csv':
|
||||||
print(f"Comment lines: {result['comment_lines']}")
|
result = count_comma_separated(filepath)
|
||||||
print(f"Empty lines: {result['empty_lines']}")
|
if result == -1:
|
||||||
|
print(f"ERROR: Cannot read file '{filepath}'", file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
if __name__ == "__main__":
|
print(result)
|
||||||
main()
|
else:
|
||||||
|
print(f"Unknown mode: {mode}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
apple, banana, cherry, date, elderberry
|
||||||
|
@@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Test script for line_counter.py utility."""
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def run_test(cmd, expected, description):
|
||||||
|
"""Run a test command and verify output."""
|
||||||
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||||
|
actual = result.stdout.strip()
|
||||||
|
|
||||||
|
if actual == str(expected) and result.returncode == 0:
|
||||||
|
print(f"PASS: {description}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"FAIL: {description}")
|
||||||
|
print(f" Expected: {expected}, Got: {actual}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test CSV mode with known data
|
||||||
|
test_csv_pass = run_test(
|
||||||
|
['python3', 'line_counter.py', 'test_data.csv', 'csv'],
|
||||||
|
5,
|
||||||
|
"CSV count mode (5 items)"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test count mode with known lines
|
||||||
|
test_count_pass = run_test(
|
||||||
|
['python3', 'line_counter.py', 'test_log.txt', 'count'],
|
||||||
|
10,
|
||||||
|
"Line count mode (10 lines)"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test error handling for non-existent file
|
||||||
|
result = subprocess.run(
|
||||||
|
['python3', 'line_counter.py', 'nonexistent.txt', 'count'],
|
||||||
|
capture_output=True,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
if result.returncode == 2:
|
||||||
|
print("PASS: Error handling (exit code 2 for missing file)")
|
||||||
|
error_pass = True
|
||||||
|
else:
|
||||||
|
print(f"FAIL: Error handling (expected exit code 2, got {result.returncode})")
|
||||||
|
error_pass = False
|
||||||
|
|
||||||
|
all_pass = test_csv_pass and test_count_pass and error_pass
|
||||||
|
print(f"\nAll tests: {'PASSED' if all_pass else 'FAILED'}")
|
||||||
|
sys.exit(0 if all_pass else 1)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
line 4
|
||||||
|
line 5
|
||||||
|
line 6
|
||||||
|
line 7
|
||||||
|
line 8
|
||||||
|
line 9
|
||||||
|
line 10
|
||||||
Reference in new issue
Block a user