Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copy this file to .env and fill values when needed.
JARVIS_ENV=development
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Python
__pycache__/
*.py[cod]
*.pyo
*.pyd
.Python
.pytest_cache/
.mypy_cache/
.ruff_cache/

# Virtual environments
.venv/
venv/
env/

# Build artifacts
build/
dist/
*.egg-info/

# IDE/editor
.vscode/
.idea/

# OS files
.DS_Store
Thumbs.db

# Local environment
.env
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# jarvis_glm

A Windows-friendly Python 3.11+ scaffold for a future Jarvis voice assistant.

## Quickstart

1. Create and activate a virtual environment.
2. Install package and dev tooling:

```bash
pip install -e .[dev]
```

## CLI

Run environment diagnostics:

```bash
python -m jarvis doctor
```

## Development checks

```bash
pytest
ruff check .
mypy
```
45 changes: 45 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "jarvis_glm"
version = "0.1.0"
description = "Windows-friendly voice assistant scaffold"
readme = "README.md"
requires-python = ">=3.11"
authors = [{ name = "Jarvis Team" }]
dependencies = []

[project.optional-dependencies]
dev = [
"pytest>=8.0",
"ruff>=0.6.0",
"mypy>=1.10",
]

[tool.setuptools]
package-dir = {"" = "src"}

[tool.setuptools.packages.find]
where = ["src"]

[tool.pytest.ini_options]
minversion = "8.0"
addopts = "-ra"
testpaths = ["tests"]

[tool.ruff]
line-length = 100
target-version = "py311"
src = ["src", "tests"]

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"]

[tool.mypy]
python_version = "3.11"
strict = true
mypy_path = ["src"]
packages = ["jarvis"]
warn_unused_configs = true
5 changes: 5 additions & 0 deletions src/jarvis/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""jarvis package."""

__all__ = ["__version__"]

__version__ = "0.1.0"
34 changes: 34 additions & 0 deletions src/jarvis/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""CLI entrypoint for jarvis."""

from __future__ import annotations

import argparse

from jarvis.doctor import format_diagnostics


def build_parser() -> argparse.ArgumentParser:
"""Build command-line parser."""
parser = argparse.ArgumentParser(prog="jarvis", description="Jarvis assistant CLI")
subparsers = parser.add_subparsers(dest="command")

subparsers.add_parser("doctor", help="Print environment diagnostics")

return parser


def main() -> int:
"""Run the jarvis CLI."""
parser = build_parser()
args = parser.parse_args()

if args.command == "doctor":
print(format_diagnostics())
return 0

parser.print_help()
return 0


if __name__ == "__main__":
raise SystemExit(main())
27 changes: 27 additions & 0 deletions src/jarvis/doctor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Environment diagnostics for Jarvis CLI."""

from __future__ import annotations

import os
import platform
import sys


def collect_diagnostics() -> dict[str, str]:
"""Collect basic diagnostics for the current runtime environment."""
return {
"python_executable": sys.executable,
"python_version": platform.python_version(),
"platform": platform.platform(),
"system": platform.system(),
"machine": platform.machine(),
"windows_comspec": os.environ.get("COMSPEC", "not set"),
}


def format_diagnostics() -> str:
"""Format diagnostics as human-readable text."""
diagnostics = collect_diagnostics()
lines = ["Jarvis Doctor", "============="]
lines.extend(f"{key}: {value}" for key, value in diagnostics.items())
return "\n".join(lines)
9 changes: 9 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from __future__ import annotations

import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "src"

sys.path.insert(0, str(SRC))
41 changes: 41 additions & 0 deletions tests/test_doctor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from __future__ import annotations

import os
import subprocess
import sys
from pathlib import Path

from jarvis.doctor import collect_diagnostics, format_diagnostics


def test_collect_diagnostics_contains_expected_keys() -> None:
diagnostics = collect_diagnostics()

assert diagnostics["python_executable"]
assert diagnostics["python_version"]
assert diagnostics["platform"]


def test_format_diagnostics_header() -> None:
output = format_diagnostics()

assert "Jarvis Doctor" in output
assert "python_version:" in output


def test_module_cli_doctor() -> None:
root = Path(__file__).resolve().parents[1]
src = root / "src"
env = os.environ.copy()
env["PYTHONPATH"] = str(src)

result = subprocess.run(
[sys.executable, "-m", "jarvis", "doctor"],
check=False,
capture_output=True,
text=True,
env=env,
)

assert result.returncode == 0
assert "Jarvis Doctor" in result.stdout