athena-code 0.0.14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of athena-code might be problematic. Click here for more details.

athena/repository.py ADDED
@@ -0,0 +1,75 @@
1
+ from pathlib import Path
2
+ from typing import Iterator
3
+
4
+
5
+ EXCLUDED_DIRS = {
6
+ "node_modules",
7
+ ".venv",
8
+ "venv",
9
+ "__pycache__",
10
+ "build",
11
+ "dist",
12
+ ".git",
13
+ ".tox",
14
+ "vendor",
15
+ }
16
+
17
+
18
+ class RepositoryNotFoundError(Exception):
19
+ """Raised when no git repository is found."""
20
+ pass
21
+
22
+
23
+ def find_repository_root(start_path: Path = Path.cwd()) -> Path:
24
+ """Find the root of the git repository by walking up the directory tree.
25
+
26
+ Args:
27
+ start_path: The directory to start searching from (defaults to current directory)
28
+
29
+ Returns:
30
+ Path to the repository root (the directory containing .git/)
31
+
32
+ Raises:
33
+ RepositoryNotFoundError: If no .git directory is found
34
+ """
35
+ current = start_path.resolve()
36
+
37
+ while current != current.parent:
38
+ if (current / ".git").exists():
39
+ return current
40
+ current = current.parent
41
+
42
+ if (current / ".git").exists():
43
+ return current
44
+
45
+ raise RepositoryNotFoundError(
46
+ f"No git repository found from {start_path}"
47
+ )
48
+
49
+
50
+ def find_python_files(root: Path) -> Iterator[Path]:
51
+ """Find all Python files in the repository, excluding common directories.
52
+
53
+ Args:
54
+ root: The repository root directory to search
55
+
56
+ Yields:
57
+ Path objects for each .py file found
58
+ """
59
+ for path in root.rglob("*.py"):
60
+ if any(excluded in path.parts for excluded in EXCLUDED_DIRS):
61
+ continue
62
+ yield path
63
+
64
+
65
+ def get_relative_path(file_path: Path, root: Path) -> str:
66
+ """Convert an absolute file path to a POSIX-style relative path from root.
67
+
68
+ Args:
69
+ file_path: Absolute path to a file
70
+ root: Repository root directory
71
+
72
+ Returns:
73
+ POSIX-style relative path as a string
74
+ """
75
+ return file_path.relative_to(root).as_posix()
athena/status.py ADDED
@@ -0,0 +1,88 @@
1
+ """Status command - check entity docstring hash synchronization state."""
2
+
3
+ from pathlib import Path
4
+
5
+ from athena.entity_path import EntityPath, parse_entity_path
6
+ from athena.models import EntityStatus
7
+ from athena.sync import collect_sub_entities, inspect_entity
8
+
9
+
10
+ def check_status(entity_path_str: str, repo_root: Path) -> list[EntityStatus]:
11
+ """Check status of a single entity.
12
+
13
+ Args:
14
+ entity_path_str: Entity path string (e.g., "src/foo.py:Bar")
15
+ repo_root: Repository root directory
16
+
17
+ Returns:
18
+ List containing single EntityStatus
19
+
20
+ Raises:
21
+ FileNotFoundError: If entity file doesn't exist
22
+ ValueError: If entity is not found in file or path is invalid
23
+ NotImplementedError: For package/module level status
24
+ """
25
+ status = inspect_entity(entity_path_str, repo_root)
26
+ return [status]
27
+
28
+
29
+ def check_status_recursive(entity_path_str: str, repo_root: Path) -> list[EntityStatus]:
30
+ """Check status of an entity and all its sub-entities recursively.
31
+
32
+ For modules: checks all functions, classes, and methods
33
+ For packages: checks all modules and their entities
34
+ For classes: checks the class and all its methods
35
+ For functions/methods: checks only that entity
36
+
37
+ Args:
38
+ entity_path_str: Entity path string
39
+ repo_root: Repository root directory
40
+
41
+ Returns:
42
+ List of EntityStatus for all entities
43
+
44
+ Raises:
45
+ FileNotFoundError: If entity file doesn't exist
46
+ ValueError: If entity is not found in file or path is invalid
47
+ """
48
+ entity_path = parse_entity_path(entity_path_str)
49
+
50
+ entities_to_check = []
51
+
52
+ if entity_path.is_package or entity_path.is_module:
53
+ entities_to_check = collect_sub_entities(entity_path, repo_root)
54
+ else:
55
+ if entity_path.is_class:
56
+ entities_to_check.append(entity_path_str)
57
+ entities_to_check.extend(collect_sub_entities(entity_path, repo_root))
58
+ else:
59
+ entities_to_check.append(entity_path_str)
60
+
61
+ statuses = []
62
+ for entity in entities_to_check:
63
+ try:
64
+ status = inspect_entity(entity, repo_root)
65
+ statuses.append(status)
66
+ except (ValueError, FileNotFoundError) as e:
67
+ print(f"Warning: Failed to inspect {entity}: {e}")
68
+
69
+ return statuses
70
+
71
+
72
+ def filter_out_of_sync(statuses: list[EntityStatus]) -> list[EntityStatus]:
73
+ """Filter list to only out-of-sync entities.
74
+
75
+ An entity is out-of-sync if:
76
+ - It has no recorded hash (None)
77
+ - The recorded hash doesn't match the calculated hash
78
+
79
+ Args:
80
+ statuses: List of EntityStatus
81
+
82
+ Returns:
83
+ Filtered list containing only out-of-sync entities
84
+ """
85
+ return [
86
+ s for s in statuses
87
+ if s.recorded_hash is None or s.recorded_hash != s.calculated_hash
88
+ ]