Skip to content

Commit 945cb51

Browse files
committed
refactor: update spec retrieval to use enum for concise/verbose outputs
1 parent ab49815 commit 945cb51

File tree

3 files changed

+90
-133
lines changed

3 files changed

+90
-133
lines changed

python/cocoindex/flow.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ def _render_spec(self, verbose: bool = False) -> Tree:
493493
return tree
494494

495495
def _get_spec(self, verbose: bool = False) -> list[tuple[str, str, int]]:
496-
return self._lazy_engine_flow().get_spec(verbose=verbose)
496+
return self._lazy_engine_flow().get_spec(format_mode="verbose" if verbose else "concise")
497497

498498
def _get_schema(self) -> list[tuple[str, str, str]]:
499499
return self._lazy_engine_flow().get_schema()

src/base/spec.rs

+75-88
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,23 @@ use serde_json::Value;
66
use std::fmt;
77
use std::ops::Deref;
88

9+
// Define SpecFormatMode enum for type-safe formatting
10+
#[derive(Debug, Clone, Copy, PartialEq)]
11+
pub enum SpecFormatMode {
12+
Concise,
13+
Verbose,
14+
}
15+
16+
impl SpecFormatMode {
17+
pub fn from_str(s: &str) -> Result<Self, String> {
18+
match s.to_lowercase().as_str() {
19+
"concise" => Ok(SpecFormatMode::Concise),
20+
"verbose" => Ok(SpecFormatMode::Verbose),
21+
_ => Err(format!("Invalid format mode: {}", s)),
22+
}
23+
}
24+
}
25+
926
#[derive(Debug, Clone, Serialize, Deserialize)]
1027
#[serde(tag = "kind")]
1128
pub enum SpecString {
@@ -264,6 +281,13 @@ impl OpSpec {
264281
.unwrap_or("#serde_error".to_string());
265282
format!("{}({})", self.kind, spec_str)
266283
}
284+
285+
pub fn format(&self, mode: SpecFormatMode) -> String {
286+
match mode {
287+
SpecFormatMode::Concise => self.format_concise(),
288+
SpecFormatMode::Verbose => self.format_verbose(),
289+
}
290+
}
267291
}
268292

269293
impl fmt::Display for OpSpec {
@@ -296,27 +320,18 @@ pub struct ImportOpSpec {
296320
}
297321

298322
impl ImportOpSpec {
299-
fn format(&self, verbose: bool) -> String {
300-
let source = if verbose {
301-
self.source.format_verbose()
302-
} else {
303-
self.source.format_concise()
323+
pub fn format(&self, mode: SpecFormatMode) -> String {
324+
let source = match mode {
325+
SpecFormatMode::Concise => self.source.format_concise(),
326+
SpecFormatMode::Verbose => self.source.format_verbose(),
304327
};
305328
format!("source={}, refresh={}", source, self.refresh_options)
306329
}
307-
308-
pub fn format_concise(&self) -> String {
309-
self.format(false)
310-
}
311-
312-
pub fn format_verbose(&self) -> String {
313-
self.format(true)
314-
}
315330
}
316331

317332
impl fmt::Display for ImportOpSpec {
318333
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
319-
write!(f, "{}", self.format_concise())
334+
write!(f, "{}", self.format(SpecFormatMode::Concise))
320335
}
321336
}
322337

@@ -327,39 +342,27 @@ pub struct TransformOpSpec {
327342
}
328343

329344
impl TransformOpSpec {
330-
fn format(&self, verbose: bool) -> String {
345+
pub fn format(&self, mode: SpecFormatMode) -> String {
331346
let inputs = self
332347
.inputs
333348
.iter()
334349
.map(ToString::to_string)
335350
.collect::<Vec<_>>()
336351
.join(",");
337-
338-
let op_str = if verbose {
339-
self.op.format_verbose()
340-
} else {
341-
self.op.format_concise()
352+
let op_str = match mode {
353+
SpecFormatMode::Concise => self.op.format_concise(),
354+
SpecFormatMode::Verbose => self.op.format_verbose(),
342355
};
343-
344-
if verbose {
345-
format!("op={}, inputs=[{}]", op_str, inputs)
346-
} else {
347-
format!("op={}, inputs={}", op_str, inputs)
356+
match mode {
357+
SpecFormatMode::Concise => format!("op={}, inputs={}", op_str, inputs),
358+
SpecFormatMode::Verbose => format!("op={}, inputs=[{}]", op_str, inputs),
348359
}
349360
}
350-
351-
pub fn format_concise(&self) -> String {
352-
self.format(false)
353-
}
354-
355-
pub fn format_verbose(&self) -> String {
356-
self.format(true)
357-
}
358361
}
359362

360363
impl fmt::Display for TransformOpSpec {
361364
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362-
write!(f, "{}", self.format_concise())
365+
write!(f, "{}", self.format(SpecFormatMode::Concise))
363366
}
364367
}
365368

@@ -374,6 +377,13 @@ impl ForEachOpSpec {
374377
pub fn get_label(&self) -> String {
375378
format!("Loop over {}", self.field_path)
376379
}
380+
381+
pub fn format(&self, mode: SpecFormatMode) -> String {
382+
match mode {
383+
SpecFormatMode::Concise => self.get_label(),
384+
SpecFormatMode::Verbose => format!("field={}", self.field_path),
385+
}
386+
}
377387
}
378388

379389
impl fmt::Display for ForEachOpSpec {
@@ -396,34 +406,28 @@ pub struct CollectOpSpec {
396406
}
397407

398408
impl CollectOpSpec {
399-
fn format(&self, verbose: bool) -> String {
409+
pub fn format(&self, mode: SpecFormatMode) -> String {
400410
let uuid = self.auto_uuid_field.as_deref().unwrap_or("none");
401-
402-
if verbose {
403-
format!(
404-
"scope={}, collector={}, input=[{}], uuid={}",
405-
self.scope_name, self.collector_name, self.input, uuid
406-
)
407-
} else {
408-
format!(
409-
"collector={}, input={}, uuid={}",
410-
self.collector_name, self.input, uuid
411-
)
411+
match mode {
412+
SpecFormatMode::Concise => {
413+
format!(
414+
"collector={}, input={}, uuid={}",
415+
self.collector_name, self.input, uuid
416+
)
417+
}
418+
SpecFormatMode::Verbose => {
419+
format!(
420+
"scope={}, collector={}, input=[{}], uuid={}",
421+
self.scope_name, self.collector_name, self.input, uuid
422+
)
423+
}
412424
}
413425
}
414-
415-
pub fn format_concise(&self) -> String {
416-
self.format(false)
417-
}
418-
419-
pub fn format_verbose(&self) -> String {
420-
self.format(true)
421-
}
422426
}
423427

424428
impl fmt::Display for CollectOpSpec {
425429
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
426-
write!(f, "{}", self.format_concise())
430+
write!(f, "{}", self.format(SpecFormatMode::Concise))
427431
}
428432
}
429433

@@ -490,37 +494,25 @@ pub struct ExportOpSpec {
490494
}
491495

492496
impl ExportOpSpec {
493-
fn format(&self, verbose: bool) -> String {
494-
let target_str = if verbose {
495-
self.target.format_verbose()
496-
} else {
497-
self.target.format_concise()
497+
pub fn format(&self, mode: SpecFormatMode) -> String {
498+
let target_str = match mode {
499+
SpecFormatMode::Concise => self.target.format_concise(),
500+
SpecFormatMode::Verbose => self.target.format_verbose(),
498501
};
499-
500502
let base = format!(
501503
"collector={}, target={}, {}",
502504
self.collector_name, target_str, self.index_options
503505
);
504-
505-
if verbose {
506-
format!("{}, setup_by_user={}", base, self.setup_by_user)
507-
} else {
508-
base
506+
match mode {
507+
SpecFormatMode::Concise => base,
508+
SpecFormatMode::Verbose => format!("{}, setup_by_user={}", base, self.setup_by_user),
509509
}
510510
}
511-
512-
pub fn format_concise(&self) -> String {
513-
self.format(false)
514-
}
515-
516-
pub fn format_verbose(&self) -> String {
517-
self.format(true)
518-
}
519511
}
520512

521513
impl fmt::Display for ExportOpSpec {
522514
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523-
write!(f, "{}", self.format_concise())
515+
write!(f, "{}", self.format(SpecFormatMode::Concise))
524516
}
525517
}
526518

@@ -533,26 +525,21 @@ pub enum ReactiveOpSpec {
533525
}
534526

535527
impl ReactiveOpSpec {
536-
pub fn format_concise(&self) -> String {
528+
pub fn format(&self, mode: SpecFormatMode) -> String {
537529
match self {
538-
ReactiveOpSpec::Transform(t) => format!("Transform: {}", t.format_concise()),
539-
ReactiveOpSpec::ForEach(fe) => format!("{}", fe.get_label()),
540-
ReactiveOpSpec::Collect(c) => c.format_concise(),
541-
}
542-
}
543-
544-
pub fn format_verbose(&self) -> String {
545-
match self {
546-
ReactiveOpSpec::Transform(t) => format!("Transform: {}", t.format_verbose()),
547-
ReactiveOpSpec::ForEach(fe) => format!("ForEach: {}", fe),
548-
ReactiveOpSpec::Collect(c) => format!("Collect: {}", c.format_verbose()),
530+
ReactiveOpSpec::Transform(t) => format!("Transform: {}", t.format(mode)),
531+
ReactiveOpSpec::ForEach(fe) => match mode {
532+
SpecFormatMode::Concise => format!("{}", fe.get_label()),
533+
SpecFormatMode::Verbose => format!("ForEach: {}", fe.format(mode)),
534+
},
535+
ReactiveOpSpec::Collect(c) => format!("Collect: {}", c.format(mode)),
549536
}
550537
}
551538
}
552539

553540
impl fmt::Display for ReactiveOpSpec {
554541
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
555-
write!(f, "{}", self.format_concise())
542+
write!(f, "{}", self.format(SpecFormatMode::Concise))
556543
}
557544
}
558545

src/py/mod.rs

+14-44
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::prelude::*;
22

33
use crate::base::schema::{FieldSchema, ValueType};
4+
use crate::base::spec::SpecFormatMode;
45
use crate::base::spec::VectorSimilarityMetric;
56
use crate::base::spec::{NamedSpec, ReactiveOpSpec};
67
use crate::execution::query;
@@ -197,8 +198,10 @@ impl Flow {
197198
})
198199
}
199200

200-
#[pyo3(signature = (verbose=false))]
201-
pub fn get_spec(&self, verbose: bool) -> Vec<(String, String, u32)> {
201+
#[pyo3(signature = (format_mode="concise"))]
202+
pub fn get_spec(&self, format_mode: &str) -> PyResult<Vec<(String, String, u32)>> {
203+
let mode = SpecFormatMode::from_str(format_mode)
204+
.map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(e))?;
202205
let spec = &self.0.flow.flow_instance;
203206
let mut result = Vec::with_capacity(
204207
1 + spec.import_ops.len()
@@ -224,81 +227,48 @@ impl Flow {
224227

225228
// Sources
226229
extend_with(&mut result, "Sources", spec.import_ops.iter(), |op| {
227-
format!(
228-
"Import: name={}, {}",
229-
op.name,
230-
if verbose {
231-
op.spec.format_verbose()
232-
} else {
233-
op.spec.format_concise()
234-
}
235-
)
230+
format!("Import: name={}, {}", op.name, op.spec.format(mode))
236231
});
237232

238233
// Processing
239234
fn walk(
240235
op: &NamedSpec<ReactiveOpSpec>,
241236
indent: u32,
242-
verbose: bool,
237+
mode: SpecFormatMode,
243238
out: &mut Vec<(String, String, u32)>,
244239
) {
245240
out.push((
246241
"Processing".into(),
247-
format!(
248-
"{}: {}",
249-
op.name,
250-
if verbose {
251-
op.spec.format_verbose()
252-
} else {
253-
op.spec.format_concise()
254-
}
255-
),
242+
format!("{}: {}", op.name, op.spec.format(mode)),
256243
indent,
257244
));
258245

259246
if let ReactiveOpSpec::ForEach(fe) = &op.spec {
260247
out.push(("Processing".into(), fe.op_scope.to_string(), indent + 1));
261248
for nested in &fe.op_scope.ops {
262-
walk(nested, indent + 2, verbose, out);
249+
walk(nested, indent + 2, mode, out);
263250
}
264251
}
265252
}
266253

267254
for op in &spec.reactive_ops {
268-
walk(op, 0, verbose, &mut result);
255+
walk(op, 0, mode, &mut result);
269256
}
270257

271258
// Targets
272259
extend_with(&mut result, "Targets", spec.export_ops.iter(), |op| {
273-
format!(
274-
"Export: name={}, {}",
275-
op.name,
276-
if verbose {
277-
op.spec.format_verbose()
278-
} else {
279-
op.spec.format_concise()
280-
}
281-
)
260+
format!("Export: name={}, {}", op.name, op.spec.format(mode))
282261
});
283262

284263
// Declarations
285264
extend_with(
286265
&mut result,
287266
"Declarations",
288267
spec.declarations.iter(),
289-
|decl| {
290-
format!(
291-
"Declaration: {}",
292-
if verbose {
293-
decl.format_verbose()
294-
} else {
295-
decl.format_concise()
296-
}
297-
)
298-
},
268+
|decl| format!("Declaration: {}", decl.format(mode)),
299269
);
300270

301-
result
271+
Ok(result)
302272
}
303273

304274
pub fn get_schema(&self) -> Vec<(String, String, String)> {
@@ -316,7 +286,7 @@ impl Flow {
316286
let mut field_type = match &field.value_type.typ {
317287
ValueType::Basic(basic) => format!("{}", basic),
318288
ValueType::Table(t) => format!("{}", t.kind),
319-
ValueType::Struct(s) => format!("{}", s),
289+
ValueType::Struct(_) => "Struct".to_string(),
320290
};
321291

322292
if field.value_type.nullable {

0 commit comments

Comments
 (0)