Skip to content

Commit de5c767

Browse files
committed
add oneline option for displaying sync history
1 parent 0063a45 commit de5c767

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

src/humanloop/cli/__main__.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import os
88
from humanloop import Humanloop
99
from humanloop.sync.sync_client import SyncClient
10+
from datetime import datetime
1011

1112
# Set up logging
1213
logger = logging.getLogger(__name__)
@@ -132,10 +133,23 @@ def pull(path: Optional[str], environment: Optional[str], api_key: Optional[str]
132133
for file in metadata['failed_files']:
133134
click.echo(f" ✗ {file}")
134135

136+
def format_timestamp(timestamp: str) -> str:
137+
"""Format timestamp to a more readable format."""
138+
try:
139+
dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
140+
return dt.strftime('%Y-%m-%d %H:%M:%S')
141+
except (ValueError, AttributeError):
142+
return timestamp
143+
135144
@cli.command()
145+
@click.option(
146+
"--oneline",
147+
is_flag=True,
148+
help="Display history in a single line per operation",
149+
)
136150
@common_options
137151
@handle_sync_errors
138-
def history(api_key: Optional[str], env_file: Optional[str], base_dir: str, base_url: Optional[str]):
152+
def history(api_key: Optional[str], env_file: Optional[str], base_dir: str, base_url: Optional[str], oneline: bool):
139153
"""Show sync operation history."""
140154
client = get_client(api_key, env_file, base_url)
141155
sync_client = SyncClient(client, base_dir=base_dir)
@@ -145,23 +159,29 @@ def history(api_key: Optional[str], env_file: Optional[str], base_dir: str, base
145159
click.echo("No sync operations found in history.")
146160
return
147161

148-
click.echo("Sync Operation History:")
149-
click.echo("======================")
162+
if not oneline:
163+
click.echo("Sync Operation History:")
164+
click.echo("======================")
150165

151166
for op in history:
152-
click.echo(f"\nOperation: {op['operation_type']}")
153-
click.echo(f"Timestamp: {op['timestamp']}")
154-
click.echo(f"Path: {op['path'] or '(root)'}")
155-
if op['environment']:
156-
click.echo(f"Environment: {op['environment']}")
157-
click.echo(f"Duration: {op['duration_ms']}ms")
158-
if op['successful_files']:
159-
click.echo(f"Successfully synced {len(op['successful_files'])} file{'' if len(op['successful_files']) == 1 else 's'}")
160-
if op['failed_files']:
161-
click.echo(f"Failed to sync {len(op['failed_files'])} file{'' if len(op['failed_files']) == 1 else 's'}")
162-
if op['error']:
163-
click.echo(f"Error: {op['error']}")
164-
click.echo("----------------------")
167+
if oneline:
168+
# Format: timestamp | operation_type | path | environment | duration_ms | status
169+
status = "✓" if not op['failed_files'] else "✗"
170+
click.echo(f"{format_timestamp(op['timestamp'])} | {op['operation_type']} | {op['path'] or '(root)'} | {op['environment'] or '-'} | {op['duration_ms']}ms | {status}")
171+
else:
172+
click.echo(f"\nOperation: {op['operation_type']}")
173+
click.echo(f"Timestamp: {format_timestamp(op['timestamp'])}")
174+
click.echo(f"Path: {op['path'] or '(root)'}")
175+
if op['environment']:
176+
click.echo(f"Environment: {op['environment']}")
177+
click.echo(f"Duration: {op['duration_ms']}ms")
178+
if op['successful_files']:
179+
click.echo(f"Successfully synced {len(op['successful_files'])} file{'' if len(op['successful_files']) == 1 else 's'}")
180+
if op['failed_files']:
181+
click.echo(f"Failed to sync {len(op['failed_files'])} file{'' if len(op['failed_files']) == 1 else 's'}")
182+
if op['error']:
183+
click.echo(f"Error: {op['error']}")
184+
click.echo("----------------------")
165185

166186
if __name__ == "__main__":
167187
cli()

0 commit comments

Comments
 (0)