use std::path::{Path, PathBuf};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::cache::hash_source;
use crate::common::{ExtractedDag, ParseError};
use crate::dynamic_markers::{DynamicMarker, detect_dynamic_markers};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ParseOutcome {
pub dags: Vec<ExtractedDag>,
pub dynamic_markers: Vec<DynamicMarker>,
pub source_hash: u64,
pub parsed_at: DateTime<Utc>,
pub source_path: Option<PathBuf>,
}
pub fn extract_static_dag(src: &str) -> Result<ExtractedDag, ParseError> {
extract_with_default_backend(src).map(|v| v.into_iter().next().unwrap_or_default())
}
pub fn extract_all_static_dags(src: &str) -> Result<Vec<ExtractedDag>, ParseError> {
extract_with_default_backend(src)
}
pub fn parse_dag_path(path: &Path) -> Result<ParseOutcome, ParseError> {
let source = std::fs::read_to_string(path).map_err(|e| ParseError::Io {
path: path.to_path_buf(),
source: e,
})?;
let hash = hash_source(&source);
parse_dag_file(path, &source, hash)
}
pub(crate) fn parse_dag_file(
path: &Path,
source: &str,
hash: u64,
) -> Result<ParseOutcome, ParseError> {
let dags = extract_with_default_backend(source)?;
let dynamic_markers = detect_dynamic_markers(source).unwrap_or_default();
Ok(ParseOutcome {
dags,
dynamic_markers,
source_hash: hash,
parsed_at: Utc::now(),
source_path: Some(path.to_path_buf()),
})
}
#[must_use]
pub fn dynamic_markers_for(src: &str) -> Vec<DynamicMarker> {
detect_dynamic_markers(src).unwrap_or_default()
}
#[cfg(feature = "parser-ruff")]
fn extract_with_default_backend(src: &str) -> Result<Vec<ExtractedDag>, ParseError> {
crate::ruff_impl::extract_all(src)
}