yanex 0.1.0__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.
@@ -0,0 +1,146 @@
1
+ """
2
+ Environment capture utilities.
3
+ """
4
+
5
+ import platform
6
+ import sys
7
+ from pathlib import Path
8
+ from typing import Any, Dict, Optional
9
+
10
+ import git
11
+
12
+ from ..utils.exceptions import GitError
13
+ from .git_utils import get_current_commit_info, get_git_repo, get_repository_info
14
+
15
+
16
+ def capture_python_environment() -> Dict[str, Any]:
17
+ """
18
+ Capture Python environment information.
19
+
20
+ Returns:
21
+ Dictionary with Python environment details
22
+ """
23
+ return {
24
+ "python_version": sys.version,
25
+ "python_version_info": {
26
+ "major": sys.version_info.major,
27
+ "minor": sys.version_info.minor,
28
+ "micro": sys.version_info.micro,
29
+ },
30
+ "python_executable": sys.executable,
31
+ "python_path": sys.path.copy(),
32
+ "platform": platform.platform(),
33
+ }
34
+
35
+
36
+ def capture_system_environment() -> Dict[str, Any]:
37
+ """
38
+ Capture system environment information.
39
+
40
+ Returns:
41
+ Dictionary with system details
42
+ """
43
+ return {
44
+ "platform": {
45
+ "system": platform.system(),
46
+ "release": platform.release(),
47
+ "version": platform.version(),
48
+ "machine": platform.machine(),
49
+ "processor": platform.processor(),
50
+ "architecture": platform.architecture(),
51
+ },
52
+ "hostname": platform.node(),
53
+ "working_directory": str(Path.cwd()),
54
+ }
55
+
56
+
57
+ def capture_git_environment(repo_path: Optional[Path] = None) -> Dict[str, Any]:
58
+ """
59
+ Capture git environment information.
60
+
61
+ Args:
62
+ repo_path: Path to git repository, defaults to current directory
63
+
64
+ Returns:
65
+ Dictionary with git environment details
66
+ """
67
+ try:
68
+ repo = get_git_repo(repo_path)
69
+
70
+ git_info = {
71
+ "repository": get_repository_info(repo),
72
+ "commit": get_current_commit_info(repo),
73
+ "git_version": git.Git().version(),
74
+ }
75
+
76
+ return git_info
77
+
78
+ except GitError:
79
+ # If we can't get git info, return minimal info
80
+ return {
81
+ "repository": None,
82
+ "commit": None,
83
+ "git_version": None,
84
+ "error": "Git repository not found or not accessible",
85
+ }
86
+
87
+
88
+ def capture_dependencies() -> Dict[str, Any]:
89
+ """
90
+ Capture dependency information.
91
+
92
+ Returns:
93
+ Dictionary with dependency details
94
+ """
95
+ deps_info = {
96
+ "requirements_txt": None,
97
+ "environment_yml": None,
98
+ "pyproject_toml": None,
99
+ }
100
+
101
+ cwd = Path.cwd()
102
+
103
+ # Check for requirements.txt
104
+ requirements_path = cwd / "requirements.txt"
105
+ if requirements_path.exists():
106
+ try:
107
+ deps_info["requirements_txt"] = requirements_path.read_text().strip()
108
+ except Exception:
109
+ deps_info["requirements_txt"] = "Error reading requirements.txt"
110
+
111
+ # Check for environment.yml (conda)
112
+ env_yml_path = cwd / "environment.yml"
113
+ if env_yml_path.exists():
114
+ try:
115
+ deps_info["environment_yml"] = env_yml_path.read_text().strip()
116
+ except Exception:
117
+ deps_info["environment_yml"] = "Error reading environment.yml"
118
+
119
+ # Check for pyproject.toml
120
+ pyproject_path = cwd / "pyproject.toml"
121
+ if pyproject_path.exists():
122
+ try:
123
+ deps_info["pyproject_toml"] = pyproject_path.read_text().strip()
124
+ except Exception:
125
+ deps_info["pyproject_toml"] = "Error reading pyproject.toml"
126
+
127
+ return deps_info
128
+
129
+
130
+ def capture_full_environment(repo_path: Optional[Path] = None) -> Dict[str, Any]:
131
+ """
132
+ Capture complete environment information.
133
+
134
+ Args:
135
+ repo_path: Path to git repository, defaults to current directory
136
+
137
+ Returns:
138
+ Dictionary with complete environment details
139
+ """
140
+ return {
141
+ "python": capture_python_environment(),
142
+ "system": capture_system_environment(),
143
+ "git": capture_git_environment(repo_path),
144
+ "dependencies": capture_dependencies(),
145
+ "capture_timestamp": None, # Will be set by storage layer
146
+ }
@@ -0,0 +1,153 @@
1
+ """
2
+ Git integration utilities.
3
+ """
4
+
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
8
+ import git
9
+ from git import Repo
10
+
11
+ from ..utils.exceptions import DirtyWorkingDirectoryError, GitError
12
+
13
+
14
+ def get_git_repo(path: Optional[Path] = None) -> Repo:
15
+ """
16
+ Get git repository instance.
17
+
18
+ Args:
19
+ path: Path to search for git repo, defaults to current directory
20
+
21
+ Returns:
22
+ Git repository instance
23
+
24
+ Raises:
25
+ GitError: If no git repository found
26
+ """
27
+ if path is None:
28
+ path = Path.cwd()
29
+
30
+ try:
31
+ return Repo(path, search_parent_directories=True)
32
+ except git.InvalidGitRepositoryError as e:
33
+ raise GitError(f"No git repository found at {path}") from e
34
+
35
+
36
+ def validate_clean_working_directory(repo: Optional[Repo] = None) -> None:
37
+ """
38
+ Validate that git working directory is clean.
39
+
40
+ Args:
41
+ repo: Git repository instance, defaults to current directory
42
+
43
+ Raises:
44
+ DirtyWorkingDirectoryError: If working directory has uncommitted changes
45
+ GitError: If git operations fail
46
+ """
47
+ if repo is None:
48
+ repo = get_git_repo()
49
+
50
+ try:
51
+ if repo.is_dirty():
52
+ # Get list of changed files
53
+ changes = []
54
+
55
+ # Modified files
56
+ for item in repo.index.diff(None):
57
+ changes.append(f"Modified: {item.a_path}")
58
+
59
+ # Staged files
60
+ for item in repo.index.diff("HEAD"):
61
+ changes.append(f"Staged: {item.a_path}")
62
+
63
+ # Untracked files
64
+ for file_path in repo.untracked_files:
65
+ changes.append(f"Untracked: {file_path}")
66
+
67
+ raise DirtyWorkingDirectoryError(changes)
68
+
69
+ except git.GitError as e:
70
+ raise GitError(f"Git operation failed: {e}") from e
71
+
72
+
73
+ def get_current_commit_info(repo: Optional[Repo] = None) -> dict[str, str]:
74
+ """
75
+ Get current git commit information.
76
+
77
+ Args:
78
+ repo: Git repository instance, defaults to current directory
79
+
80
+ Returns:
81
+ Dictionary with commit information
82
+
83
+ Raises:
84
+ GitError: If git operations fail
85
+ """
86
+ if repo is None:
87
+ repo = get_git_repo()
88
+
89
+ try:
90
+ commit = repo.head.commit
91
+
92
+ return {
93
+ "commit_hash": commit.hexsha,
94
+ "commit_hash_short": commit.hexsha[:8],
95
+ "branch": repo.active_branch.name,
96
+ "author": str(commit.author),
97
+ "message": commit.message.strip(),
98
+ "committed_date": commit.committed_datetime.isoformat(),
99
+ }
100
+
101
+ except git.GitError as e:
102
+ raise GitError(f"Failed to get commit info: {e}") from e
103
+
104
+
105
+ def get_repository_info(repo: Optional[Repo] = None) -> dict[str, str]:
106
+ """
107
+ Get git repository information.
108
+
109
+ Args:
110
+ repo: Git repository instance, defaults to current directory
111
+
112
+ Returns:
113
+ Dictionary with repository information
114
+
115
+ Raises:
116
+ GitError: If git operations fail
117
+ """
118
+ if repo is None:
119
+ repo = get_git_repo()
120
+
121
+ try:
122
+ info = {
123
+ "repo_path": str(repo.working_dir),
124
+ "git_dir": str(repo.git_dir),
125
+ }
126
+
127
+ # Get remote URL if available
128
+ try:
129
+ if repo.remotes:
130
+ origin = repo.remotes.origin
131
+ info["remote_url"] = origin.url
132
+ else:
133
+ info["remote_url"] = None
134
+ except (AttributeError, IndexError):
135
+ info["remote_url"] = None
136
+
137
+ return info
138
+
139
+ except git.GitError as e:
140
+ raise GitError(f"Failed to get repository info: {e}") from e
141
+
142
+
143
+ def ensure_git_available() -> None:
144
+ """
145
+ Ensure git is available in the system.
146
+
147
+ Raises:
148
+ GitError: If git command is not available
149
+ """
150
+ try:
151
+ git.Git().version()
152
+ except git.GitCommandError as e:
153
+ raise GitError("Git command not found. Please install Git.") from e