diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d327515 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,63 @@ +name: CI + +on: + push: + branches: ["*"] + pull_request: + branches: [main] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install linters + run: pip install flake8 ruff + + - name: Run flake8 + run: | + flake8 . \ + --max-line-length=120 \ + --extend-ignore=E501,W503,E402,E722,W291,W293,W391,E303,E302,E305,E261,E262,E127,E128,E221,F401,F403 \ + --exclude=".git,__pycache__,build,dist,.claude,*.egg-info,venv,.venv,dashboard/journal_dashboard - Copy.py" \ + --count --show-source --statistics + + - name: Run ruff + run: | + ruff check . \ + --line-length=120 \ + --extend-ignore=E501,E402,E722,F401,F403 \ + --extend-exclude=".git,__pycache__,build,dist,.claude,venv,.venv,dashboard/journal_dashboard - Copy.py" + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install Tesseract OCR + run: sudo apt-get update && sudo apt-get install -y tesseract-ocr + + - name: Install dependencies + run: | + pip install --upgrade pip + pip install -r requirements.txt + pip install pytest + + - name: Run tests + run: | + if [ -d "tests" ]; then + python -m pytest tests/ -v --tb=short + else + echo "No tests directory found, skipping tests" + fi diff --git a/dashboard/journal_chat.py b/dashboard/journal_chat.py index 871b56f..dd48318 100644 --- a/dashboard/journal_chat.py +++ b/dashboard/journal_chat.py @@ -193,9 +193,9 @@ st.sidebar.metric("Total Entries", stats['total_entries']) st.sidebar.metric("Total Words", f"{stats['total_words']:,}") if stats['date_range']['first']: - st.sidebar.text(f"Date Range:") + st.sidebar.text("Date Range:") st.sidebar.text(f"{stats['date_range']['first']}") - st.sidebar.text(f"to") + st.sidebar.text("to") st.sidebar.text(f"{stats['date_range']['last']}") except Exception: pass diff --git a/dashboard/journal_dashboard.py b/dashboard/journal_dashboard.py index 0b9af4f..7de5906 100644 --- a/dashboard/journal_dashboard.py +++ b/dashboard/journal_dashboard.py @@ -949,4 +949,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/ocr/auto_ocr_watcher.py b/ocr/auto_ocr_watcher.py index f0de0fb..524f45c 100644 --- a/ocr/auto_ocr_watcher.py +++ b/ocr/auto_ocr_watcher.py @@ -104,12 +104,12 @@ def watch_folder(watch_dir: str, output_dir: str, engine: str = "tesseract"): if not watch_path.exists(): raise FileNotFoundError(f"Watch directory does not exist: {watch_dir}") - print(f"Starting journal photo watcher...") + print("Starting journal photo watcher...") print(f" Watching: {watch_path.absolute()}") print(f" Output: {output_dir}") print(f" OCR Engine: {engine}") - print(f"\nAdd new journal photos to the watch folder to process them automatically.") - print(f" Press Ctrl+C to stop.\n") + print("\nAdd new journal photos to the watch folder to process them automatically.") + print(" Press Ctrl+C to stop.\n") # Initialize pipeline pipeline = JournalOCRPipeline(engine=engine, output_dir=output_dir) diff --git a/plugins/calendar_view.py b/plugins/calendar_view.py index face6a0..20347c3 100644 --- a/plugins/calendar_view.py +++ b/plugins/calendar_view.py @@ -54,7 +54,6 @@ def render(ctx): theme = ctx.load_theme() link_color = theme.get("link_color", "#0066cc") - bg_color = theme.get("bg_color", "#ffffff") text_color = theme.get("text_color", "#111111") # Determine a subtle highlight for entry days diff --git a/rag/journal_rag.py b/rag/journal_rag.py index d61b5ff..407cd1e 100644 --- a/rag/journal_rag.py +++ b/rag/journal_rag.py @@ -474,7 +474,7 @@ def interactive_search(rag: JournalRAG, use_llm: bool = False, llm_model: str = print("="*60) stats = rag.get_stats() - print(f"\nDatabase Stats:") + print("\nDatabase Stats:") print(f" Entries: {stats['total_entries']}") print(f" Date Range: {stats['date_range']['first']} to {stats['date_range']['last']}") print(f" Total Words: {stats['total_words']:,}") @@ -541,7 +541,7 @@ def interactive_search(rag: JournalRAG, use_llm: bool = False, llm_model: str = elif command == 'list': entries = rag.list_all_entries() - print(f"\nAll entries in database:\n") + print("\nAll entries in database:\n") for entry in entries: print(f" {entry['date']} - {entry['chunks']} chunks, ~{entry['word_count']} words") print() @@ -565,7 +565,7 @@ def interactive_search(rag: JournalRAG, use_llm: bool = False, llm_model: str = elif command == 'stats': stats = rag.get_stats() - print(f"\nDatabase Statistics:") + print("\nDatabase Statistics:") print(f" Total Entries: {stats['total_entries']}") print(f" Total Chunks: {stats['total_chunks']}") print(f" Total Words: {stats['total_words']:,}") @@ -680,7 +680,7 @@ def main(): elif args.command == 'list': entries = rag.list_all_entries() - print(f"\nAll entries in database:\n") + print("\nAll entries in database:\n") for entry in entries: print(f" {entry['date']} - {entry['chunks']} chunks, ~{entry['word_count']} words") print(f"\nTotal: {len(entries)} entries\n")