From 3cb07c6bd9783519e1389d25ec614cdbe9c60c72 Mon Sep 17 00:00:00 2001 From: renardeinside Date: Mon, 2 Feb 2026 19:33:27 +0100 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20configurable=20uv?= =?UTF-8?q?icorn=20logging=20via=20pyproject.toml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../docs/reference/config-reference.mdx | 63 ++ src/common.rs | 6 + src/dev/process.rs | 85 +- src/lib.rs | 1 + src/python_logging.rs | 792 ++++++++++++++++++ 5 files changed, 876 insertions(+), 71 deletions(-) create mode 100644 src/python_logging.rs diff --git a/docs/content/docs/reference/config-reference.mdx b/docs/content/docs/reference/config-reference.mdx index e4aa01e..976805b 100644 --- a/docs/content/docs/reference/config-reference.mdx +++ b/docs/content/docs/reference/config-reference.mdx @@ -81,3 +81,66 @@ This allows you to run: ```bash apx add @animate-ui/fade-in ``` + +### `[tool.apx.dev]` + +Development server configuration options. + +- **log_config_file**: Path to an external Python logging configuration file (relative to pyproject.toml). Mutually exclusive with `[tool.apx.dev.logging]`. + +Example: + +```toml +[tool.apx.dev] +log_config_file = "logging_config.py" +``` + +### `[tool.apx.dev.logging]` + +Inline Python logging configuration using the standard [logging.dictConfig](https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig) format. This configuration is **merged** with the default uvicorn logging setup, allowing you to add custom loggers or override specific settings while preserving the standard uvicorn logging behavior. + +When you specify loggers, formatters, or handlers, they are merged with the defaults: + +- New entries are added +- Existing entries with the same name are overridden + +Example with inline tables: + +```toml +[tool.apx.dev.logging] +version = 1 +disable_existing_loggers = false + +[tool.apx.dev.logging.formatters] +default = { format = "%(levelname)s %(name)s %(message)s" } + +[tool.apx.dev.logging.handlers] +console = { class = "logging.StreamHandler", formatter = "default", stream = "ext://sys.stdout" } + +[tool.apx.dev.logging.loggers] +"uvicorn" = { level = "DEBUG", handlers = ["console"], propagate = false } +"myapp" = { level = "DEBUG", handlers = ["console"], propagate = false } +``` + +**Default loggers provided by apx:** + +| Logger | Level | Description | +| ---------------- | ----- | ------------------------- | +| `uvicorn` | INFO | Main uvicorn logger | +| `uvicorn.error` | INFO | Uvicorn error logger | +| `uvicorn.access` | INFO | HTTP access logs | +| `{app_slug}` | DEBUG | Your application's logger | + +**Configuration options:** + +- **version**: Must be `1` (required by Python's dictConfig) +- **disable_existing_loggers**: Whether to disable existing loggers (default: `false`) +- **formatters**: Log message formatters +- **handlers**: Output handlers (console, file, etc.) +- **loggers**: Logger configurations by name +- **root**: Root logger configuration + + + You cannot use both `log_config_file` and `[tool.apx.dev.logging]` at the same + time. + diff --git a/src/common.rs b/src/common.rs index 25d794d..9bc35f9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -9,6 +9,7 @@ use tokio::process::Command; use crate::bun_binary_path; use crate::generate_openapi; +use crate::python_logging::{DevConfig, parse_dev_config}; /// Dev dependencies required by apx frontend entrypoint.ts /// These must be installed before running any frontend command @@ -201,6 +202,7 @@ pub struct ProjectMetadata { pub metadata_path: PathBuf, pub ui_root: PathBuf, pub ui_registries: HashMap, + pub dev_config: DevConfig, } impl ProjectMetadata { @@ -261,6 +263,9 @@ pub fn read_project_metadata(project_root: &Path) -> Result Result>>, + dev_config: DevConfig, } impl ProcessManager { @@ -90,6 +92,7 @@ impl ProcessManager { let dotenv_vars = Arc::new(Mutex::new(dotenv.get_vars())); let app_slug = metadata.app_slug.clone(); let app_entrypoint = metadata.app_entrypoint.clone(); + let dev_config = metadata.dev_config.clone(); let dev_token = Self::generate_dev_token(); let db_password = Self::generate_dev_token(); // Random password for PGlite @@ -119,6 +122,7 @@ impl ProcessManager { app_slug, app_entrypoint, dotenv_vars, + dev_config, }) } @@ -301,8 +305,10 @@ impl ProcessManager { // 2026-01-28 14:09:02.413 | app | INFO: Uvicorn running... // ============================================================================ - // Create uvicorn logging config for consistent log format - let log_config = self.create_uvicorn_log_config(app_dir).await?; + // Resolve uvicorn logging config (inline TOML, external Python file, or default) + let log_config_result = + resolve_log_config(&self.dev_config, &self.app_slug, app_dir).await?; + let log_config = log_config_result.to_string_path(); // Run uvicorn via uv to ensure correct Python environment let mut cmd = UvCommand::new("uvicorn").tokio_command(); @@ -377,72 +383,6 @@ impl ProcessManager { Ok(()) } - /// Create a uvicorn logging config file (JSON format, no pyyaml dependency). - /// Always overwrites the existing config to ensure format updates are applied. - async fn create_uvicorn_log_config(&self, app_dir: &Path) -> Result { - let config_dir = app_dir.join(".apx"); - tokio::fs::create_dir_all(&config_dir) - .await - .map_err(|e| format!("Failed to create .apx directory: {e}"))?; - - let config_path = config_dir.join("uvicorn_logging.json"); - // APX adds: timestamp | source | channel | - // So we only need: location | message - // - // IMPORTANT: Uvicorn's access logger passes values as positional args, not named fields. - // Use %(message)s to get the pre-formatted message, not %(client_addr)s etc. - let config_content = r#"{ - "version": 1, - "disable_existing_loggers": false, - "formatters": { - "default": { - "format": "%(module)s.%(funcName)s | %(message)s" - }, - "access": { - "format": "%(message)s" - } - }, - "handlers": { - "default": { - "class": "logging.StreamHandler", - "stream": "ext://sys.stderr", - "formatter": "default" - }, - "access": { - "class": "logging.StreamHandler", - "stream": "ext://sys.stdout", - "formatter": "access" - } - }, - "loggers": { - "uvicorn": { - "handlers": ["default"], - "level": "INFO", - "propagate": false - }, - "uvicorn.error": { - "level": "INFO", - "propagate": true - }, - "uvicorn.access": { - "handlers": ["access"], - "level": "INFO", - "propagate": false - } - }, - "root": { - "level": "INFO", - "handlers": ["default"] - } -}"#; - - tokio::fs::write(&config_path, config_content) - .await - .map_err(|e| format!("Failed to write uvicorn logging config: {e}"))?; - - Ok(config_path.display().to_string()) - } - async fn spawn_pglite(&self, bun: &BunCommand) -> Result<(), String> { let child = self .spawn_process( @@ -581,6 +521,7 @@ impl ProcessManager { let dev_server_port = self.dev_server_port; let dev_token = self.dev_token.clone(); let db_password = self.db_password.clone(); + let dev_config = self.dev_config.clone(); tokio::spawn(async move { let (tx, mut rx) = tokio::sync::mpsc::channel::(100); @@ -700,6 +641,7 @@ impl ProcessManager { &db_password, &dotenv_vars, &backend_child, + &dev_config, ) .await { @@ -804,6 +746,7 @@ impl ProcessManager { db_password: &str, dotenv_vars: &Arc>>, backend_child: &Arc>>, + dev_config: &DevConfig, ) -> Result<(), String> { // ============================================================================ // Backend logs are captured via stdout/stderr and forwarded to flux. @@ -811,9 +754,9 @@ impl ProcessManager { // See spawn_uvicorn() for detailed explanation. // ============================================================================ - // Reuse the existing log config file (created by spawn_uvicorn) - let log_config = app_dir.join(".apx").join("uvicorn_logging.json"); - let log_config_str = log_config.display().to_string(); + // Resolve uvicorn logging config (inline TOML, external Python file, or default) + let log_config_result = resolve_log_config(dev_config, app_slug, app_dir).await?; + let log_config_str = log_config_result.to_string_path(); // Run uvicorn via uv to ensure correct Python environment let mut cmd = UvCommand::new("uvicorn").tokio_command(); diff --git a/src/lib.rs b/src/lib.rs index cc78587..62ba6c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ mod flux; mod interop; mod mcp; mod openapi; +mod python_logging; mod registry; mod search; mod sources; diff --git a/src/python_logging.rs b/src/python_logging.rs new file mode 100644 index 0000000..a1e789a --- /dev/null +++ b/src/python_logging.rs @@ -0,0 +1,792 @@ +//! Python logging configuration for uvicorn. +//! +//! Supports two configuration modes: +//! 1. Inline TOML config in [tool.apx.dev.logging] +//! 2. External Python file via log_config_file setting +//! +//! When neither is specified, generates a default logging configuration. + +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +/// Dev configuration from [tool.apx.dev] +#[derive(Debug, Clone, Default)] +pub struct DevConfig { + /// Inline TOML logging config + pub logging: Option, + /// External Python file for logging config + pub log_config_file: Option, +} + +/// Python logging.dictConfig format +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LoggingConfig { + pub version: i32, + #[serde(default)] + pub disable_existing_loggers: bool, + #[serde(default)] + pub formatters: HashMap, + #[serde(default)] + pub handlers: HashMap, + #[serde(default)] + pub loggers: HashMap, + #[serde(default)] + pub root: Option, +} + +/// Formatter configuration +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FormatterConfig { + #[serde(default)] + pub format: Option, + #[serde(default)] + pub datefmt: Option, + #[serde(default, rename = "class")] + pub class_name: Option, +} + +/// Handler configuration +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct HandlerConfig { + #[serde(rename = "class")] + pub class_name: String, + #[serde(default)] + pub level: Option, + #[serde(default)] + pub formatter: Option, + #[serde(default)] + pub stream: Option, + #[serde(default)] + pub filename: Option, + #[serde(default)] + pub filters: Option>, +} + +/// Logger configuration +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LoggerConfig { + #[serde(default)] + pub handlers: Option>, + #[serde(default)] + pub level: Option, + #[serde(default)] + pub propagate: Option, +} + +/// Root logger configuration +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct RootLoggerConfig { + #[serde(default)] + pub level: Option, + #[serde(default)] + pub handlers: Option>, +} + +/// Result of resolving log configuration +#[derive(Debug, Clone)] +pub enum LogConfigResult { + /// JSON config file path (.apx/uvicorn_logging.json) + JsonConfig(PathBuf), + /// External Python file path + PythonFile(PathBuf), +} + +impl LogConfigResult { + /// Get the path as a string for passing to uvicorn + pub fn to_string_path(&self) -> String { + match self { + LogConfigResult::JsonConfig(p) | LogConfigResult::PythonFile(p) => { + p.display().to_string() + } + } + } +} + +/// Parse [tool.apx.dev] section from pyproject.toml +pub fn parse_dev_config( + pyproject_value: &toml::Value, + project_root: &Path, +) -> Result { + let dev_section = pyproject_value + .get("tool") + .and_then(|tool| tool.get("apx")) + .and_then(|apx| apx.get("dev")); + + let Some(dev) = dev_section else { + return Ok(DevConfig::default()); + }; + + let logging = dev.get("logging").map(parse_logging_config).transpose()?; + + let log_config_file = dev + .get("log_config_file") + .and_then(|v| v.as_str()) + .map(|s| project_root.join(s)); + + // Validate mutual exclusivity + if logging.is_some() && log_config_file.is_some() { + return Err( + "Cannot specify both [tool.apx.dev.logging] and log_config_file in pyproject.toml" + .to_string(), + ); + } + + // Validate external file exists + if let Some(ref path) = log_config_file + && !path.exists() + { + return Err(format!("log_config_file not found: {}", path.display())); + } + + Ok(DevConfig { + logging, + log_config_file, + }) +} + +/// Parse inline logging configuration from TOML value +fn parse_logging_config(value: &toml::Value) -> Result { + let version = value + .get("version") + .and_then(|v| v.as_integer()) + .unwrap_or(1) as i32; + + let disable_existing_loggers = value + .get("disable_existing_loggers") + .and_then(|v| v.as_bool()) + .unwrap_or(false); + + let formatters = parse_formatters(value.get("formatters"))?; + let handlers = parse_handlers(value.get("handlers"))?; + let loggers = parse_loggers(value.get("loggers"))?; + let root = parse_root_logger(value.get("root"))?; + + Ok(LoggingConfig { + version, + disable_existing_loggers, + formatters, + handlers, + loggers, + root, + }) +} + +fn parse_formatters( + value: Option<&toml::Value>, +) -> Result, String> { + let Some(v) = value else { + return Ok(HashMap::new()); + }; + + let table = v.as_table().ok_or("formatters must be a table")?; + + let mut result = HashMap::new(); + for (name, formatter_value) in table { + let formatter_table = formatter_value + .as_table() + .ok_or_else(|| format!("formatter '{}' must be a table", name))?; + + let format = formatter_table + .get("format") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let datefmt = formatter_table + .get("datefmt") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let class_name = formatter_table + .get("class") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + result.insert( + name.clone(), + FormatterConfig { + format, + datefmt, + class_name, + }, + ); + } + + Ok(result) +} + +fn parse_handlers(value: Option<&toml::Value>) -> Result, String> { + let Some(v) = value else { + return Ok(HashMap::new()); + }; + + let table = v.as_table().ok_or("handlers must be a table")?; + + let mut result = HashMap::new(); + for (name, handler_value) in table { + let handler_table = handler_value + .as_table() + .ok_or_else(|| format!("handler '{}' must be a table", name))?; + + let class_name = handler_table + .get("class") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()) + .ok_or_else(|| format!("handler '{}' must have a 'class' field", name))?; + + let level = handler_table + .get("level") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let formatter = handler_table + .get("formatter") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let stream = handler_table + .get("stream") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let filename = handler_table + .get("filename") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let filters = handler_table.get("filters").and_then(|v| { + v.as_array().map(|arr| { + arr.iter() + .filter_map(|item| item.as_str().map(|s| s.to_string())) + .collect() + }) + }); + + result.insert( + name.clone(), + HandlerConfig { + class_name, + level, + formatter, + stream, + filename, + filters, + }, + ); + } + + Ok(result) +} + +fn parse_loggers(value: Option<&toml::Value>) -> Result, String> { + let Some(v) = value else { + return Ok(HashMap::new()); + }; + + let table = v.as_table().ok_or("loggers must be a table")?; + + let mut result = HashMap::new(); + for (name, logger_value) in table { + let logger_table = logger_value + .as_table() + .ok_or_else(|| format!("logger '{}' must be a table", name))?; + + let handlers = logger_table.get("handlers").and_then(|v| { + v.as_array().map(|arr| { + arr.iter() + .filter_map(|item| item.as_str().map(|s| s.to_string())) + .collect() + }) + }); + + let level = logger_table + .get("level") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let propagate = logger_table.get("propagate").and_then(|v| v.as_bool()); + + result.insert( + name.clone(), + LoggerConfig { + handlers, + level, + propagate, + }, + ); + } + + Ok(result) +} + +fn parse_root_logger(value: Option<&toml::Value>) -> Result, String> { + let Some(v) = value else { + return Ok(None); + }; + + let table = v.as_table().ok_or("root must be a table")?; + + let level = table + .get("level") + .and_then(|v| v.as_str()) + .map(|s| s.to_string()); + + let handlers = table.get("handlers").and_then(|v| { + v.as_array().map(|arr| { + arr.iter() + .filter_map(|item| item.as_str().map(|s| s.to_string())) + .collect() + }) + }); + + Ok(Some(RootLoggerConfig { level, handlers })) +} + +/// Generate the default logging configuration for uvicorn +pub fn default_logging_config(app_slug: &str) -> LoggingConfig { + let mut formatters = HashMap::new(); + formatters.insert( + "default".to_string(), + FormatterConfig { + format: Some("%(module)s.%(funcName)s | %(message)s".to_string()), + datefmt: None, + class_name: None, + }, + ); + formatters.insert( + "access".to_string(), + FormatterConfig { + format: Some("%(message)s".to_string()), + datefmt: None, + class_name: None, + }, + ); + + let mut handlers = HashMap::new(); + handlers.insert( + "default".to_string(), + HandlerConfig { + class_name: "logging.StreamHandler".to_string(), + level: None, + formatter: Some("default".to_string()), + stream: Some("ext://sys.stderr".to_string()), + filename: None, + filters: None, + }, + ); + handlers.insert( + "access".to_string(), + HandlerConfig { + class_name: "logging.StreamHandler".to_string(), + level: None, + formatter: Some("access".to_string()), + stream: Some("ext://sys.stdout".to_string()), + filename: None, + filters: None, + }, + ); + + let mut loggers = HashMap::new(); + loggers.insert( + "uvicorn".to_string(), + LoggerConfig { + handlers: Some(vec!["default".to_string()]), + level: Some("INFO".to_string()), + propagate: Some(false), + }, + ); + loggers.insert( + "uvicorn.error".to_string(), + LoggerConfig { + handlers: None, + level: Some("INFO".to_string()), + propagate: Some(true), + }, + ); + loggers.insert( + "uvicorn.access".to_string(), + LoggerConfig { + handlers: Some(vec!["access".to_string()]), + level: Some("INFO".to_string()), + propagate: Some(false), + }, + ); + // App-specific logger at DEBUG level + loggers.insert( + app_slug.to_string(), + LoggerConfig { + handlers: Some(vec!["default".to_string()]), + level: Some("DEBUG".to_string()), + propagate: Some(false), + }, + ); + + let root = Some(RootLoggerConfig { + level: Some("INFO".to_string()), + handlers: Some(vec!["default".to_string()]), + }); + + LoggingConfig { + version: 1, + disable_existing_loggers: false, + formatters, + handlers, + loggers, + root, + } +} + +/// Write logging configuration to JSON file in .apx directory +pub async fn write_logging_config_json( + config: &LoggingConfig, + app_dir: &Path, +) -> Result { + let config_dir = app_dir.join(".apx"); + tokio::fs::create_dir_all(&config_dir) + .await + .map_err(|e| format!("Failed to create .apx directory: {e}"))?; + + let config_path = config_dir.join("uvicorn_logging.json"); + + let json = serde_json::to_string_pretty(config) + .map_err(|e| format!("Failed to serialize logging config: {e}"))?; + + tokio::fs::write(&config_path, json) + .await + .map_err(|e| format!("Failed to write uvicorn logging config: {e}"))?; + + Ok(config_path) +} + +/// Merge user-provided logging config with the default config. +/// +/// User-provided formatters, handlers, and loggers are merged into the defaults, +/// with user values taking precedence over defaults for any overlapping keys. +pub fn merge_with_default(user_config: &LoggingConfig, app_slug: &str) -> LoggingConfig { + let mut config = default_logging_config(app_slug); + + // Merge formatters (user overrides defaults) + for (name, formatter) in &user_config.formatters { + config.formatters.insert(name.clone(), formatter.clone()); + } + + // Merge handlers (user overrides defaults) + for (name, handler) in &user_config.handlers { + config.handlers.insert(name.clone(), handler.clone()); + } + + // Merge loggers (user overrides defaults) + for (name, logger) in &user_config.loggers { + config.loggers.insert(name.clone(), logger.clone()); + } + + // Override root if user provided one + if user_config.root.is_some() { + config.root = user_config.root.clone(); + } + + // Use user's disable_existing_loggers if they explicitly set it + // (We can't distinguish "not set" from "set to false" in TOML, but + // since false is the sensible default for uvicorn, this is fine) + config.disable_existing_loggers = user_config.disable_existing_loggers; + + config +} + +/// Resolve the logging configuration to use for uvicorn +/// +/// Priority: +/// 1. External Python file (log_config_file) +/// 2. Inline TOML config merged with defaults ([tool.apx.dev.logging]) +/// 3. Default config +pub async fn resolve_log_config( + dev_config: &DevConfig, + app_slug: &str, + app_dir: &Path, +) -> Result { + // External Python file takes precedence + if let Some(ref py_file) = dev_config.log_config_file { + return Ok(LogConfigResult::PythonFile(py_file.clone())); + } + + // Merge inline config with defaults, or use defaults alone + let config = match &dev_config.logging { + Some(user_cfg) => merge_with_default(user_cfg, app_slug), + None => default_logging_config(app_slug), + }; + + let json_path = write_logging_config_json(&config, app_dir).await?; + Ok(LogConfigResult::JsonConfig(json_path)) +} + +#[cfg(test)] +#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] +mod tests { + use super::*; + + #[test] + fn test_default_logging_config() { + let config = default_logging_config("myapp"); + + assert_eq!(config.version, 1); + assert!(!config.disable_existing_loggers); + assert!(config.formatters.contains_key("default")); + assert!(config.formatters.contains_key("access")); + assert!(config.handlers.contains_key("default")); + assert!(config.handlers.contains_key("access")); + assert!(config.loggers.contains_key("uvicorn")); + assert!(config.loggers.contains_key("uvicorn.error")); + assert!(config.loggers.contains_key("uvicorn.access")); + assert!(config.loggers.contains_key("myapp")); + + // App logger should be at DEBUG level + if let Some(app_logger) = config.loggers.get("myapp") { + assert_eq!(app_logger.level, Some("DEBUG".to_string())); + } else { + panic!("myapp logger should exist"); + } + } + + #[test] + fn test_parse_dev_config_empty() { + let toml_str = r#" +[tool.apx.metadata] +app-name = "Test" +"#; + let Ok(value) = toml_str.parse::() else { + panic!("failed to parse TOML"); + }; + let Ok(config) = parse_dev_config(&value, Path::new("/test")) else { + panic!("failed to parse dev config"); + }; + + assert!(config.logging.is_none()); + assert!(config.log_config_file.is_none()); + } + + #[test] + fn test_parse_dev_config_inline_logging() { + let toml_str = r#" +[tool.apx.dev.logging] +version = 1 +disable_existing_loggers = true + +[tool.apx.dev.logging.formatters.custom] +format = "%(levelname)s - %(message)s" + +[tool.apx.dev.logging.handlers.console] +class = "logging.StreamHandler" +stream = "ext://sys.stdout" +formatter = "custom" + +[tool.apx.dev.logging.loggers.mylogger] +handlers = ["console"] +level = "DEBUG" +propagate = false +"#; + let Ok(value) = toml_str.parse::() else { + panic!("failed to parse TOML"); + }; + let Ok(config) = parse_dev_config(&value, Path::new("/test")) else { + panic!("failed to parse dev config"); + }; + + assert!(config.logging.is_some()); + assert!(config.log_config_file.is_none()); + + let Some(logging) = config.logging else { + panic!("logging config should exist"); + }; + assert_eq!(logging.version, 1); + assert!(logging.disable_existing_loggers); + assert!(logging.formatters.contains_key("custom")); + assert!(logging.handlers.contains_key("console")); + assert!(logging.loggers.contains_key("mylogger")); + + if let Some(mylogger) = logging.loggers.get("mylogger") { + assert_eq!(mylogger.level, Some("DEBUG".to_string())); + assert_eq!(mylogger.propagate, Some(false)); + } else { + panic!("mylogger should exist"); + } + } + + #[test] + fn test_parse_dev_config_mutual_exclusivity() { + let toml_str = r#" +[tool.apx.dev] +log_config_file = "logging.py" + +[tool.apx.dev.logging] +version = 1 +"#; + let Ok(value) = toml_str.parse::() else { + panic!("failed to parse TOML"); + }; + // Create a temp file to simulate the external config existing + let temp_dir = std::env::temp_dir(); + let temp_file = temp_dir.join("logging.py"); + if std::fs::write(&temp_file, "# logging config").is_err() { + panic!("failed to write temp file"); + } + + let result = parse_dev_config(&value, &temp_dir); + assert!(result.is_err()); + if let Err(err) = result { + assert!(err.contains("Cannot specify both")); + } + + std::fs::remove_file(temp_file).ok(); + } + + #[test] + fn test_logging_config_serialization() { + let config = default_logging_config("testapp"); + let Ok(json) = serde_json::to_string_pretty(&config) else { + panic!("failed to serialize"); + }; + + assert!(json.contains("\"version\": 1")); + assert!(json.contains("\"disable_existing_loggers\": false")); + assert!(json.contains("\"testapp\"")); + assert!(json.contains("\"DEBUG\"")); + } + + #[test] + fn test_log_config_result_to_string() { + let json_result = LogConfigResult::JsonConfig(PathBuf::from("/app/.apx/logging.json")); + assert_eq!(json_result.to_string_path(), "/app/.apx/logging.json"); + + let py_result = LogConfigResult::PythonFile(PathBuf::from("/app/logging_config.py")); + assert_eq!(py_result.to_string_path(), "/app/logging_config.py"); + } + + #[test] + fn test_merge_with_default_preserves_defaults() { + // User config with just one custom logger + let mut user_config = LoggingConfig { + version: 1, + disable_existing_loggers: false, + formatters: HashMap::new(), + handlers: HashMap::new(), + loggers: HashMap::new(), + root: None, + }; + user_config.loggers.insert( + "myapp.custom".to_string(), + LoggerConfig { + handlers: Some(vec!["default".to_string()]), + level: Some("DEBUG".to_string()), + propagate: Some(false), + }, + ); + + let merged = merge_with_default(&user_config, "myapp"); + + // Default formatters should be present + assert!(merged.formatters.contains_key("default")); + assert!(merged.formatters.contains_key("access")); + + // Default handlers should be present + assert!(merged.handlers.contains_key("default")); + assert!(merged.handlers.contains_key("access")); + + // Default loggers should be present + assert!(merged.loggers.contains_key("uvicorn")); + assert!(merged.loggers.contains_key("uvicorn.error")); + assert!(merged.loggers.contains_key("uvicorn.access")); + assert!(merged.loggers.contains_key("myapp")); + + // User's custom logger should also be present + assert!(merged.loggers.contains_key("myapp.custom")); + } + + #[test] + fn test_merge_with_default_overrides_existing() { + // User config that overrides the uvicorn logger level + let mut user_config = LoggingConfig { + version: 1, + disable_existing_loggers: false, + formatters: HashMap::new(), + handlers: HashMap::new(), + loggers: HashMap::new(), + root: None, + }; + user_config.loggers.insert( + "uvicorn".to_string(), + LoggerConfig { + handlers: Some(vec!["default".to_string()]), + level: Some("DEBUG".to_string()), + propagate: Some(false), + }, + ); + + let merged = merge_with_default(&user_config, "myapp"); + + // uvicorn logger should have user's DEBUG level, not default INFO + if let Some(uvicorn_logger) = merged.loggers.get("uvicorn") { + assert_eq!(uvicorn_logger.level, Some("DEBUG".to_string())); + } else { + panic!("uvicorn logger should exist"); + } + + // Other default loggers should still be present + assert!(merged.loggers.contains_key("uvicorn.error")); + assert!(merged.loggers.contains_key("uvicorn.access")); + assert!(merged.loggers.contains_key("myapp")); + } + + #[test] + fn test_merge_with_default_inline_table_syntax() { + // Test parsing inline table syntax as shown in documentation + let toml_str = r#" +[tool.apx.dev.logging] +version = 1 +disable_existing_loggers = false + +[tool.apx.dev.logging.formatters] +custom = { format = "%(levelname)s %(name)s %(message)s" } + +[tool.apx.dev.logging.handlers] +console = { class = "logging.StreamHandler", formatter = "custom", stream = "ext://sys.stdout" } + +[tool.apx.dev.logging.loggers] +"uvicorn" = { level = "DEBUG", handlers = ["console"], propagate = false } +"myapp" = { level = "DEBUG", handlers = ["console"], propagate = false } +"#; + let Ok(value) = toml_str.parse::() else { + panic!("failed to parse TOML"); + }; + let Ok(dev_config) = parse_dev_config(&value, Path::new("/test")) else { + panic!("failed to parse dev config"); + }; + + assert!(dev_config.logging.is_some()); + let Some(user_config) = dev_config.logging else { + panic!("logging config should exist"); + }; + + let merged = merge_with_default(&user_config, "testapp"); + + // User's custom formatter should be present alongside defaults + assert!(merged.formatters.contains_key("custom")); + assert!(merged.formatters.contains_key("default")); + assert!(merged.formatters.contains_key("access")); + + // User's console handler should override default + assert!(merged.handlers.contains_key("console")); + + // User's uvicorn logger should override default (DEBUG instead of INFO) + if let Some(uvicorn_logger) = merged.loggers.get("uvicorn") { + assert_eq!(uvicorn_logger.level, Some("DEBUG".to_string())); + } else { + panic!("uvicorn logger should exist"); + } + + // Default app logger (testapp) should still be present + assert!(merged.loggers.contains_key("testapp")); + + // User's myapp logger should also be present + assert!(merged.loggers.contains_key("myapp")); + } +} From bcef244a0dbf8a3a547bbaf66df189fb86b6628b Mon Sep 17 00:00:00 2001 From: renardeinside Date: Mon, 2 Feb 2026 19:40:37 +0100 Subject: [PATCH 2/4] bun up --- bun.lockb | Bin 227413 -> 121085 bytes package.json | 18 +++++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bun.lockb b/bun.lockb index 5311effa2cf7737f0be1c75192ba58e89599ac15..d9daa399de239431f43236569df5800bf8e8715c 100755 GIT binary patch delta 33460 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
  • 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 literal 227413 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

    N(xgW>UL{wJ@o5;gCF5t_Ccl$+w(+t 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 diff --git a/package.json b/package.json index 374a044..8eff92b 100644 --- a/package.json +++ b/package.json @@ -14,18 +14,18 @@ "@opentelemetry/exporter-logs-otlp-http": "^0.211.0", "@opentelemetry/resources": "^2.5.0", "@opentelemetry/sdk-logs": "^0.211.0", - "@tailwindcss/vite": "^4.1.15", + "@tailwindcss/vite": "^4.1.18", "@tanstack/react-query": "^5.90.20", - "@tanstack/react-router": "^1.157.16", - "@tanstack/router-plugin": "^1.133.21", + "@tanstack/react-router": "^1.157.18", + "@tanstack/router-plugin": "^1.157.18", "@types/bun": "latest", - "@types/node": "^24.7.2", - "@vitejs/plugin-react": "^5.0.4", - "axios": "^1.13.1", - "react": "^19.2.0", - "smol-toml": "^1.4.2", + "@types/node": "^24.10.9", + "@vitejs/plugin-react": "^5.1.3", + "axios": "^1.13.4", + "react": "^19.2.4", + "smol-toml": "^1.6.0", "typescript": "^5.9.3", - "vite": "^7.1.9" + "vite": "^7.3.1" }, "peerDependencies": { "typescript": "^5.9.3" From 777e05df3190ec2984548530e7d97424f0c1f3e7 Mon Sep 17 00:00:00 2001 From: renardeinside Date: Mon, 2 Feb 2026 19:44:16 +0100 Subject: [PATCH 3/4] fix tsgen tests --- src/openapi/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/openapi/mod.rs b/src/openapi/mod.rs index 35917f5..4a88c45 100644 --- a/src/openapi/mod.rs +++ b/src/openapi/mod.rs @@ -2096,7 +2096,8 @@ mod tests { "name": "apx-ts-typecheck", "private": true, "dependencies": { - "@tanstack/react-query": "^5" + "@tanstack/react-query": "^5", + "typescript": "^5" } } "#; @@ -2152,7 +2153,7 @@ mod tests { // Run tsc from the test environment directory with explicit compiler options // Using `bun x` which is equivalent to `bunx` let output = Command::new("bun") - .arg("x") + .arg("run") .args([ "tsc", "--noEmit", From baa8c909de0687906bd9c12b16fdec265e96e162 Mon Sep 17 00:00:00 2001 From: renardeinside Date: Tue, 3 Feb 2026 11:24:27 +0100 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=A7=20improv=20customize=20+=20pas?= =?UTF-8?q?s=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 6 +++++- src/apx/__init__.py | 4 +--- src/apx/_core.pyi | 2 ++ src/dev/process.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fb09335..d94b6dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,6 +85,9 @@ biome_css_syntax = "0.5.8" biome_rowan = "0.5.8" schemars = "1.2.0" +# Temporary files +tempfile = "3.15" + [package] name = "apx" version = "0.2.3" @@ -152,6 +155,7 @@ rusqlite.workspace = true opentelemetry-proto.workspace = true prost.workspace = true similar.workspace = true +tempfile.workspace = true [dev-dependencies] -tempfile = "3.15" +tempfile.workspace = true \ No newline at end of file diff --git a/src/apx/__init__.py b/src/apx/__init__.py index 049c5b2..684079a 100644 --- a/src/apx/__init__.py +++ b/src/apx/__init__.py @@ -1,8 +1,6 @@ import sys -from apx._core import get_bun_binary_path, run_cli - -__version__ = "0.1.0" +from apx._core import get_bun_binary_path, run_cli, __version__ def main() -> None: diff --git a/src/apx/_core.pyi b/src/apx/_core.pyi index 9ed00b6..0747486 100644 --- a/src/apx/_core.pyi +++ b/src/apx/_core.pyi @@ -1,5 +1,7 @@ from pathlib import Path +__version__: str + def run_cli(args: list[str]) -> int: ... def get_bun_binary_path() -> Path: ... def generate_openapi(project_root: Path) -> bool: ... diff --git a/src/dev/process.rs b/src/dev/process.rs index 3419e5f..3b9cd1f 100644 --- a/src/dev/process.rs +++ b/src/dev/process.rs @@ -55,6 +55,30 @@ fn format_log_line(source: LogSource, message: &str) -> String { format!("{timestamp} | {source:>4} | {message}") } +/// Setup sitecustomize.py for Databricks SDK user-agent tracking. +/// This is non-critical telemetry - failures are silently ignored. +/// Returns the temp directory path if successful, None otherwise. +fn setup_sitecustomize() -> Option { + let temp_dir = tempfile::tempdir().ok()?; + let sitecustomize_path = temp_dir.path().join("sitecustomize.py"); + std::fs::write( + &sitecustomize_path, + r#"import os +try: + from databricks.sdk.core import with_user_agent_extra, with_product + from apx import __version__ + if os.getenv('APX_UVICORN') == '1': + with_user_agent_extra('apx', __version__) + with_product('apx', __version__) +except Exception: + pass +"#, + ) + .ok()?; + // Use into_path() to prevent automatic cleanup - dir persists for uvicorn's lifetime + Some(temp_dir.keep()) +} + #[derive(Debug)] pub struct ProcessManager { frontend_child: Arc>>, @@ -310,6 +334,9 @@ impl ProcessManager { resolve_log_config(&self.dev_config, &self.app_slug, app_dir).await?; let log_config = log_config_result.to_string_path(); + // Setup sitecustomize.py for user-agent tracking (non-critical, best-effort) + let sitecustomize_dir = setup_sitecustomize(); + // Run uvicorn via uv to ensure correct Python environment let mut cmd = UvCommand::new("uvicorn").tokio_command(); cmd.args([ @@ -336,9 +363,20 @@ impl ProcessManager { cmd.env("APX_DEV_SERVER_PORT", self.dev_server_port.to_string()); cmd.env("APX_DEV_SERVER_HOST", &self.host); cmd.env("APX_DEV_TOKEN", &self.dev_token); + cmd.env("APX_UVICORN", "1"); + // Force Python to flush stdout/stderr immediately (no buffering) cmd.env("PYTHONUNBUFFERED", "1"); + // Prepend sitecustomize dir to PYTHONPATH if setup succeeded (non-critical) + if let Some(sitecustomize_path) = sitecustomize_dir { + let pythonpath = match std::env::var("PYTHONPATH") { + Ok(existing) => format!("{}:{}", sitecustomize_path.display(), existing), + Err(_) => sitecustomize_path.display().to_string(), + }; + cmd.env("PYTHONPATH", pythonpath); + } + // Apply dotenv variables let vars = self.dotenv_vars.lock().await; for (key, value) in vars.iter() { diff --git a/src/lib.rs b/src/lib.rs index 62ba6c2..c298774 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -341,6 +341,7 @@ fn get_dotenv_vars() -> PyResult> { #[pymodule] fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> { init_tracing(); + m.add("__version__", env!("CARGO_PKG_VERSION"))?; m.add_function(wrap_pyfunction!(run_cli, m)?)?; m.add_function(wrap_pyfunction!(get_bun_binary_path, m)?)?; m.add_function(wrap_pyfunction!(generate_openapi_py, m)?)?;