Skip to content

Commit b2cc34c

Browse files
committed
feat(cli.py): add interactive dataline selection and retrieval commands to enhance user experience
fix(cli.py): update dataline name retrieval logic to prioritize schemaT name fix(models.py): add field validator to parse data_model from JSON string to dictionary format
1 parent 85b72d1 commit b2cc34c

File tree

2 files changed

+114
-2
lines changed

2 files changed

+114
-2
lines changed

infactory_client/cli.py

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,10 @@ def datalines_list(
637637
table.add_column("Name")
638638

639639
for dl in datalines:
640-
table.add_row(dl.id, dl.name)
640+
name = dl.name
641+
if dl.data_model.get("schemaT"):
642+
name = dl.data_model["schemaT"].get("name", name) or name
643+
table.add_row(dl.id, name)
641644

642645
console.print(table)
643646

@@ -646,6 +649,103 @@ def datalines_list(
646649
raise typer.Exit(1)
647650

648651

652+
@datalines_app.command(name="select")
653+
def datalines_select(
654+
model: bool = typer.Option(False, "--model", help="Show data model as JSON"),
655+
code: bool = typer.Option(False, "--code", help="Show schema code"),
656+
):
657+
"""Interactively select a dataline and show its details."""
658+
client = get_client()
659+
660+
if model and code:
661+
typer.echo("Error: --model and --code cannot be used together", err=True)
662+
raise typer.Exit(1)
663+
if not model and not code:
664+
model = True
665+
666+
try:
667+
if not client.state.project_id:
668+
typer.echo(
669+
"No project selected. Please select a project first with 'nf projects select'"
670+
)
671+
return
672+
673+
datalines = client.datalines.list(project_id=client.state.project_id)
674+
675+
if not datalines:
676+
typer.echo("No datalines found")
677+
return
678+
679+
# Create a list of choices
680+
choices = {str(i): dl for i, dl in enumerate(datalines, 1)}
681+
682+
# Display datalines with numbers
683+
table = Table()
684+
table.add_column("#")
685+
table.add_column("ID")
686+
table.add_column("Name")
687+
688+
for num, dl in choices.items():
689+
name = dl.name
690+
if dl.data_model.get("schemaT"):
691+
name = dl.data_model["schemaT"].get("name", name) or name
692+
table.add_row(num, dl.id, name)
693+
694+
console.print(table)
695+
696+
# Prompt for selection
697+
choice = Prompt.ask(
698+
"\nSelect dataline number",
699+
choices=list(choices.keys()),
700+
show_choices=False,
701+
)
702+
703+
selected_dataline = choices[choice]
704+
705+
if model and selected_dataline.data_model:
706+
typer.echo(json.dumps(selected_dataline.data_model, indent=2))
707+
elif code and selected_dataline.schema_code:
708+
typer.echo(selected_dataline.schema_code)
709+
else:
710+
typer.echo(
711+
f"Dataline: {selected_dataline.name} (ID: {selected_dataline.id})"
712+
)
713+
714+
except Exception as e:
715+
typer.echo(f"Failed to select dataline: {e}", err=True)
716+
raise typer.Exit(1)
717+
718+
719+
@datalines_app.command(name="get")
720+
def datalines_get(
721+
dataline_id: str,
722+
model: bool = typer.Option(False, "--model", help="Show data model as JSON"),
723+
code: bool = typer.Option(False, "--code", help="Show schema code"),
724+
):
725+
"""Get a dataline by ID."""
726+
client = get_client()
727+
728+
if model and code:
729+
typer.echo("Error: --model and --code cannot be used together", err=True)
730+
raise typer.Exit(1)
731+
if not model and not code:
732+
model = True
733+
734+
try:
735+
dataline = client.datalines.get(dataline_id)
736+
737+
if model and dataline.data_model:
738+
print(json.dumps(dataline.data_model, indent=2))
739+
elif code and dataline.schema_code:
740+
print(dataline.schema_code)
741+
else:
742+
typer.echo(f"Dataline: {dataline.name} (ID: {dataline.id})")
743+
744+
except Exception as e:
745+
typer.echo(f"Failed to get dataline: {e}", err=True)
746+
raise typer.Exit(1)
747+
748+
649749
@query_app.command(name="list")
650750
def query_programs_list(
651751
project_id: str | None = typer.Option(

infactory_client/models.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import json
12
from datetime import datetime
23
from typing import Any
34

4-
from pydantic import BaseModel
5+
from pydantic import BaseModel, field_validator
56

67

78
class Project(BaseModel):
@@ -44,6 +45,17 @@ class DataLine(BaseModel):
4445
deleted_at: datetime | None = None
4546
data_model: dict[str, Any] | None = None
4647

48+
@field_validator("data_model", mode="before")
49+
@classmethod
50+
def parse_data_model(cls, v):
51+
"""Parse data_model if it's a JSON string."""
52+
if isinstance(v, str):
53+
try:
54+
return json.loads(v)
55+
except json.JSONDecodeError:
56+
return None
57+
return v
58+
4759

4860
class Team(BaseModel):
4961
"""Team model."""

0 commit comments

Comments
 (0)