sixseven 0.1.0__tar.gz

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,84 @@
1
+ Metadata-Version: 2.2
2
+ Name: sixseven
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Sixtyseven ML experiment tracking
5
+ Author: Sixtyseven Team
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/sixtyseven/sixtyseven
8
+ Project-URL: Documentation, https://docs.sixtyseven.ai
9
+ Project-URL: Repository, https://github.com/sixtyseven/sixtyseven
10
+ Keywords: ml,machine-learning,experiment-tracking,metrics,training
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Programming Language :: Python :: 3 :: Only
24
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ Requires-Dist: requests>=2.28.0
28
+ Requires-Dist: websocket-client>=1.4.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
31
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
32
+ Requires-Dist: responses>=0.23.0; extra == "dev"
33
+ Requires-Dist: black>=23.0.0; extra == "dev"
34
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
35
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
36
+
37
+ # Sixtyseven Python SDK
38
+
39
+ Track ML experiments locally. No server setup required.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install sixtyseven
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ ```python
50
+ from sixtyseven import Run
51
+
52
+ with Run(project="my-project", name="experiment-1") as run:
53
+ run.log_config({"learning_rate": 0.001, "epochs": 10})
54
+
55
+ for epoch in range(10):
56
+ loss = train_one_epoch()
57
+ run.log_metrics({"loss": loss}, step=epoch)
58
+ ```
59
+
60
+ ## View Results
61
+
62
+ ```bash
63
+ sixtyseven --logdir ~/.sixtyseven/logs
64
+ ```
65
+
66
+ Opens a dashboard at http://localhost:6767
67
+
68
+ ## API
69
+
70
+ ```python
71
+ run.log_metrics({"loss": 0.5, "accuracy": 0.85}, step=epoch) # Log metrics
72
+ run.log_config({"lr": 0.001}) # Log config
73
+ run.add_tags(["baseline"]) # Add tags
74
+ ```
75
+
76
+ ## Environment Variables
77
+
78
+ | Variable | Description | Default |
79
+ | ------------------- | ------------------ | -------------------- |
80
+ | `SIXTYSEVEN_LOGDIR` | Where to save logs | `~/.sixtyseven/logs` |
81
+
82
+ ## License
83
+
84
+ MIT
@@ -0,0 +1,48 @@
1
+ # Sixtyseven Python SDK
2
+
3
+ Track ML experiments locally. No server setup required.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install sixtyseven
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ from sixtyseven import Run
15
+
16
+ with Run(project="my-project", name="experiment-1") as run:
17
+ run.log_config({"learning_rate": 0.001, "epochs": 10})
18
+
19
+ for epoch in range(10):
20
+ loss = train_one_epoch()
21
+ run.log_metrics({"loss": loss}, step=epoch)
22
+ ```
23
+
24
+ ## View Results
25
+
26
+ ```bash
27
+ sixtyseven --logdir ~/.sixtyseven/logs
28
+ ```
29
+
30
+ Opens a dashboard at http://localhost:6767
31
+
32
+ ## API
33
+
34
+ ```python
35
+ run.log_metrics({"loss": 0.5, "accuracy": 0.85}, step=epoch) # Log metrics
36
+ run.log_config({"lr": 0.001}) # Log config
37
+ run.add_tags(["baseline"]) # Add tags
38
+ ```
39
+
40
+ ## Environment Variables
41
+
42
+ | Variable | Description | Default |
43
+ | ------------------- | ------------------ | -------------------- |
44
+ | `SIXTYSEVEN_LOGDIR` | Where to save logs | `~/.sixtyseven/logs` |
45
+
46
+ ## License
47
+
48
+ MIT
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69,<77", "wheel", "packaging>=23.2"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sixseven"
7
+ version = "0.1.0"
8
+ description = "Python SDK for Sixtyseven ML experiment tracking"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.8"
12
+ authors = [
13
+ { name = "Sixtyseven Team" }
14
+ ]
15
+ keywords = ["ml", "machine-learning", "experiment-tracking", "metrics", "training"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Intended Audience :: Science/Research",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.8",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Programming Language :: Python :: 3.14",
29
+ "Programming Language :: Python :: 3 :: Only",
30
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
31
+ ]
32
+
33
+ dependencies = [
34
+ "requests>=2.28.0",
35
+ "websocket-client>=1.4.0",
36
+ ]
37
+
38
+ [project.optional-dependencies]
39
+ dev = [
40
+ "pytest>=7.0.0",
41
+ "pytest-asyncio>=0.21.0",
42
+ "responses>=0.23.0",
43
+ "black>=23.0.0",
44
+ "ruff>=0.1.0",
45
+ "mypy>=1.0.0",
46
+ ]
47
+
48
+ [project.urls]
49
+ Homepage = "https://github.com/sixtyseven/sixtyseven"
50
+ Documentation = "https://docs.sixtyseven.ai"
51
+ Repository = "https://github.com/sixtyseven/sixtyseven"
52
+
53
+ [project.scripts]
54
+ sixtyseven = "sixtyseven.cli:main"
55
+
56
+ [tool.setuptools]
57
+ package-dir = {"" = "src"}
58
+ packages = ["sixtyseven"]
59
+ include-package-data = true
60
+
61
+ [tool.setuptools.package-data]
62
+ sixtyseven = ["bin/**"]
63
+
64
+ [tool.mypy]
65
+ python_version = "3.8"
66
+ warn_return_any = true
67
+ warn_unused_configs = true
68
+ ignore_missing_imports = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,25 @@
1
+ from __future__ import annotations
2
+
3
+ from setuptools import setup
4
+
5
+
6
+ try:
7
+ from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
8
+
9
+ class bdist_wheel(_bdist_wheel):
10
+ def finalize_options(self) -> None:
11
+ super().finalize_options()
12
+ self.root_is_pure = False
13
+ if hasattr(self, "root_is_purelib"):
14
+ self.root_is_purelib = False
15
+
16
+ def get_tag(self) -> tuple[str, str, str]:
17
+ _, _, plat = super().get_tag()
18
+ # py3-none-<platform>: works with any Python 3, no ABI, platform-specific
19
+ return "py3", "none", plat
20
+
21
+ except Exception: # wheel not available
22
+ bdist_wheel = None # type: ignore[assignment]
23
+
24
+
25
+ setup(cmdclass={"bdist_wheel": bdist_wheel} if bdist_wheel else {})
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.2
2
+ Name: sixseven
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Sixtyseven ML experiment tracking
5
+ Author: Sixtyseven Team
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/sixtyseven/sixtyseven
8
+ Project-URL: Documentation, https://docs.sixtyseven.ai
9
+ Project-URL: Repository, https://github.com/sixtyseven/sixtyseven
10
+ Keywords: ml,machine-learning,experiment-tracking,metrics,training
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Programming Language :: Python :: 3 :: Only
24
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ Requires-Dist: requests>=2.28.0
28
+ Requires-Dist: websocket-client>=1.4.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
31
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
32
+ Requires-Dist: responses>=0.23.0; extra == "dev"
33
+ Requires-Dist: black>=23.0.0; extra == "dev"
34
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
35
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
36
+
37
+ # Sixtyseven Python SDK
38
+
39
+ Track ML experiments locally. No server setup required.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install sixtyseven
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ ```python
50
+ from sixtyseven import Run
51
+
52
+ with Run(project="my-project", name="experiment-1") as run:
53
+ run.log_config({"learning_rate": 0.001, "epochs": 10})
54
+
55
+ for epoch in range(10):
56
+ loss = train_one_epoch()
57
+ run.log_metrics({"loss": loss}, step=epoch)
58
+ ```
59
+
60
+ ## View Results
61
+
62
+ ```bash
63
+ sixtyseven --logdir ~/.sixtyseven/logs
64
+ ```
65
+
66
+ Opens a dashboard at http://localhost:6767
67
+
68
+ ## API
69
+
70
+ ```python
71
+ run.log_metrics({"loss": 0.5, "accuracy": 0.85}, step=epoch) # Log metrics
72
+ run.log_config({"lr": 0.001}) # Log config
73
+ run.add_tags(["baseline"]) # Add tags
74
+ ```
75
+
76
+ ## Environment Variables
77
+
78
+ | Variable | Description | Default |
79
+ | ------------------- | ------------------ | -------------------- |
80
+ | `SIXTYSEVEN_LOGDIR` | Where to save logs | `~/.sixtyseven/logs` |
81
+
82
+ ## License
83
+
84
+ MIT
@@ -0,0 +1,19 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ src/sixseven.egg-info/PKG-INFO
5
+ src/sixseven.egg-info/SOURCES.txt
6
+ src/sixseven.egg-info/dependency_links.txt
7
+ src/sixseven.egg-info/entry_points.txt
8
+ src/sixseven.egg-info/requires.txt
9
+ src/sixseven.egg-info/top_level.txt
10
+ src/sixtyseven/__init__.py
11
+ src/sixtyseven/cli.py
12
+ src/sixtyseven/client.py
13
+ src/sixtyseven/config.py
14
+ src/sixtyseven/exceptions.py
15
+ src/sixtyseven/local.py
16
+ src/sixtyseven/metrics.py
17
+ src/sixtyseven/run.py
18
+ src/sixtyseven/server.py
19
+ src/sixtyseven/utils.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ sixtyseven = sixtyseven.cli:main
@@ -0,0 +1,10 @@
1
+ requests>=2.28.0
2
+ websocket-client>=1.4.0
3
+
4
+ [dev]
5
+ pytest>=7.0.0
6
+ pytest-asyncio>=0.21.0
7
+ responses>=0.23.0
8
+ black>=23.0.0
9
+ ruff>=0.1.0
10
+ mypy>=1.0.0
@@ -0,0 +1 @@
1
+ sixtyseven
@@ -0,0 +1,36 @@
1
+ """
2
+ Sixtyseven - ML Experiment Tracking SDK
3
+
4
+ A Python SDK for tracking machine learning experiments with Sixtyseven.
5
+
6
+ Example usage:
7
+ from sixtyseven import Run
8
+
9
+ with Run(project="my-team/image-classifier") as run:
10
+ run.log_config({"learning_rate": 0.001})
11
+
12
+ for epoch in range(100):
13
+ loss = train()
14
+ run.log_metrics({"loss": loss}, step=epoch)
15
+ """
16
+
17
+ from sixtyseven.config import configure
18
+ from sixtyseven.exceptions import (
19
+ APIError,
20
+ AuthenticationError,
21
+ ServerError,
22
+ SixtySevenError,
23
+ ValidationError,
24
+ )
25
+ from sixtyseven.run import Run
26
+
27
+ __version__ = "0.1.0"
28
+ __all__ = [
29
+ "Run",
30
+ "configure",
31
+ "SixtySevenError",
32
+ "AuthenticationError",
33
+ "APIError",
34
+ "ValidationError",
35
+ "ServerError",
36
+ ]
@@ -0,0 +1,64 @@
1
+ """Console entrypoint for the bundled sixtyseven CLI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import platform
7
+ import shutil
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Optional
11
+
12
+
13
+ def _platform_id() -> Optional[str]:
14
+ system = platform.system().lower()
15
+ machine = platform.machine().lower()
16
+
17
+ if machine in {"x86_64", "amd64"}:
18
+ arch = "amd64"
19
+ elif machine in {"aarch64", "arm64"}:
20
+ arch = "arm64"
21
+ else:
22
+ return None
23
+
24
+ if system == "darwin":
25
+ return f"darwin-{arch}"
26
+ if system == "linux":
27
+ return f"linux-{arch}"
28
+ if system == "windows":
29
+ return f"windows-{arch}"
30
+ return None
31
+
32
+
33
+ def _bundled_binary_path() -> Optional[str]:
34
+ platform_id = _platform_id()
35
+ if not platform_id:
36
+ return None
37
+
38
+ binary_name = "sixtyseven.exe" if platform.system() == "Windows" else "sixtyseven"
39
+ base_dir = Path(__file__).resolve().parent
40
+ candidate = base_dir / "bin" / platform_id / binary_name
41
+ if candidate.is_file() and os.access(candidate, os.X_OK):
42
+ return str(candidate)
43
+ return None
44
+
45
+
46
+ def _find_binary() -> Optional[str]:
47
+ bundled = _bundled_binary_path()
48
+ if bundled:
49
+ return bundled
50
+
51
+ binary_name = "sixtyseven.exe" if platform.system() == "Windows" else "sixtyseven"
52
+ return shutil.which(binary_name)
53
+
54
+
55
+ def main() -> None:
56
+ binary = _find_binary()
57
+ if not binary:
58
+ print(
59
+ "Could not find 'sixtyseven' binary. Reinstall the package or set SIXTYSEVEN_BINARY.",
60
+ file=sys.stderr,
61
+ )
62
+ raise SystemExit(1)
63
+
64
+ os.execv(binary, [binary, *sys.argv[1:]])
@@ -0,0 +1,190 @@
1
+ """HTTP client for communicating with the Sixtyseven API."""
2
+
3
+ import time
4
+ from typing import Any, Dict, List, Optional
5
+ from urllib.parse import urljoin
6
+
7
+ import requests
8
+
9
+ from sixtyseven.config import SDKConfig
10
+ from sixtyseven.exceptions import APIError, AuthenticationError
11
+
12
+
13
+ class SixtySevenClient:
14
+ """HTTP client for the Sixtyseven API."""
15
+
16
+ def __init__(self, config: SDKConfig, api_key: Optional[str] = None):
17
+ """
18
+ Initialize the client.
19
+
20
+ Args:
21
+ config: SDK configuration
22
+ api_key: API key (overrides config)
23
+ """
24
+ self.config = config
25
+ self.api_key = api_key or config.api_key
26
+ self.session = requests.Session()
27
+
28
+ if self.api_key:
29
+ self.session.headers["Authorization"] = f"Bearer {self.api_key}"
30
+
31
+ self.session.headers["Content-Type"] = "application/json"
32
+ self.session.headers["User-Agent"] = "sixtyseven-python/0.1.0"
33
+
34
+ def _url(self, path: str) -> str:
35
+ """Build full URL for an API endpoint."""
36
+ return urljoin(self.config.base_url, f"/api/v1{path}")
37
+
38
+ def _request(
39
+ self,
40
+ method: str,
41
+ path: str,
42
+ data: Optional[Dict[str, Any]] = None,
43
+ params: Optional[Dict[str, Any]] = None,
44
+ ) -> Dict[str, Any]:
45
+ """
46
+ Make an HTTP request with retry logic.
47
+
48
+ Args:
49
+ method: HTTP method
50
+ path: API path
51
+ data: Request body data
52
+ params: Query parameters
53
+
54
+ Returns:
55
+ Response JSON data
56
+
57
+ Raises:
58
+ AuthenticationError: If authentication fails
59
+ APIError: If the request fails
60
+ """
61
+ url = self._url(path)
62
+ last_error = None
63
+
64
+ for attempt in range(self.config.retry_count):
65
+ try:
66
+ response = self.session.request(
67
+ method=method,
68
+ url=url,
69
+ json=data,
70
+ params=params,
71
+ timeout=self.config.timeout,
72
+ )
73
+
74
+ if response.status_code == 401:
75
+ raise AuthenticationError("Invalid API key")
76
+
77
+ if response.status_code == 403:
78
+ raise AuthenticationError("Insufficient permissions")
79
+
80
+ if response.status_code >= 400:
81
+ error_data = response.json() if response.text else {}
82
+ raise APIError(
83
+ error_data.get(
84
+ "error",
85
+ f"Request failed with status {response.status_code}",
86
+ ),
87
+ status_code=response.status_code,
88
+ response=error_data,
89
+ )
90
+
91
+ if response.text:
92
+ return response.json()
93
+ return {}
94
+
95
+ except requests.exceptions.RequestException as e:
96
+ last_error = e
97
+ if attempt < self.config.retry_count - 1:
98
+ time.sleep(self.config.retry_delay * (attempt + 1))
99
+ continue
100
+
101
+ raise APIError(
102
+ f"Request failed after {self.config.retry_count} attempts: {last_error}"
103
+ )
104
+
105
+ def create_run(
106
+ self,
107
+ team_slug: str,
108
+ app_slug: str,
109
+ name: Optional[str] = None,
110
+ tags: Optional[List[str]] = None,
111
+ config: Optional[Dict[str, Any]] = None,
112
+ git_info: Optional[Dict[str, Any]] = None,
113
+ system_info: Optional[Dict[str, Any]] = None,
114
+ ) -> str:
115
+ """
116
+ Create a new run.
117
+
118
+ Returns:
119
+ The run ID
120
+ """
121
+ data = {
122
+ "name": name,
123
+ "tags": tags or [],
124
+ "config": config or {},
125
+ }
126
+
127
+ if git_info:
128
+ data["git_info"] = git_info
129
+ if system_info:
130
+ data["system_info"] = system_info
131
+
132
+ response = self._request(
133
+ "POST",
134
+ f"/teams/{team_slug}/apps/{app_slug}/runs",
135
+ data=data,
136
+ )
137
+
138
+ return response["id"]
139
+
140
+ def update_run_status(
141
+ self,
142
+ run_id: str,
143
+ status: str,
144
+ error: Optional[str] = None,
145
+ ) -> None:
146
+ """Update run status (completed, failed, aborted)."""
147
+ data = {"status": status}
148
+ if error:
149
+ data["error_message"] = error
150
+
151
+ self._request("PUT", f"/runs/{run_id}/status", data=data)
152
+
153
+ def update_run_config(self, run_id: str, config: Dict[str, Any]) -> None:
154
+ """Merge new config with existing run config."""
155
+ self._request("PUT", f"/runs/{run_id}/config", data=config)
156
+
157
+ def batch_log_metrics(
158
+ self,
159
+ run_id: str,
160
+ metrics: List[Dict[str, Any]],
161
+ ) -> None:
162
+ """
163
+ Log a batch of metrics.
164
+
165
+ Args:
166
+ run_id: The run ID
167
+ metrics: List of metric dictionaries with name, value, step, timestamp
168
+ """
169
+ self._request(
170
+ "POST",
171
+ f"/runs/{run_id}/metrics",
172
+ data={"metrics": metrics},
173
+ )
174
+
175
+ def add_run_tags(self, run_id: str, tags: List[str]) -> None:
176
+ """Add tags to a run."""
177
+ # This would need to be implemented via the update endpoint
178
+ pass
179
+
180
+ def upload_artifact(
181
+ self,
182
+ run_id: str,
183
+ path: str,
184
+ name: Optional[str] = None,
185
+ metadata: Optional[Dict[str, Any]] = None,
186
+ ) -> None:
187
+ """Upload an artifact file."""
188
+ # Artifact upload would need multipart form handling
189
+ # For now, this is a placeholder
190
+ pass