Examples
This section points to working examples in the repository and groups them by current product areas.
Core Workflows
Structured operations and parsed results
#!/usr/bin/env python3
"""
Enhanced demo mode example showing realistic log streaming.
This example demonstrates:
1. Progressive log streaming like real Odoo
2. Error scenarios with detailed logging
3. Different module behaviors with realistic timing
4. Comparison between demo and real execution patterns
"""
from oduit.config_loader import ConfigLoader
from oduit.odoo_operations import ModuleUpdateError, OdooOperations
def test_streaming_logs():
"""Test the new streaming log functionality"""
print("=== Testing Enhanced Demo Mode with Log Streaming ===")
config_loader = ConfigLoader()
env_config = config_loader.load_demo_config()
ops = OdooOperations(env_config, verbose=True)
# Test successful module with log streaming
print("\n1. Testing successful module with streaming logs:")
print(" (Watch the progressive log output)")
result = ops.update_module("sale", suppress_output=True)
print(f" ✓ Success: {result['success']}")
print(f" Duration: {result['duration']:.2f}s")
# Test error module with detailed error logs
print("\n2. Testing error module with detailed error streaming:")
result = ops.update_module("module_error", suppress_output=True)
print(f" ✗ Success: {result['success']}")
print(f" Return code: {result['return_code']}")
# Test warning module
print("\n3. Testing warning module with streaming:")
result = ops.update_module("module_warning", suppress_output=True)
print(f" ⚠ Success: {result['success']} (with warnings)")
# Test unknown module
print("\n4. Testing unknown module (should show warning stream):")
result = ops.update_module("unknown_module", suppress_output=True)
print(f" ✗ Success: {result['success']} (module not found)")
# Test slow module to see extended processing
print("\n5. Testing slow module (extended processing time):")
result = ops.update_module("module_slow", suppress_output=True)
print(f" ✓ Success: {result['success']} (took longer)")
def compare_demo_vs_real():
"""Compare demo output patterns with real Odoo patterns"""
print("\n=== Demo vs Real Execution Comparison ===")
print("\n📊 Demo mode characteristics:")
print(" • Progressive log streaming with realistic timestamps")
print(" • Simulated processing delays")
print(" • Realistic error patterns and messages")
print(" • No actual odoo-bin process required")
print(" • Predictable outcomes for testing")
print("\n📊 Real mode characteristics:")
print(" • Actual Odoo process execution")
print(" • Real database operations")
print(" • Unpredictable timing based on system load")
print(" • Genuine error conditions")
print(" • Requires working Odoo installation")
def test_error_scenarios():
"""Test various error scenarios with detailed logging"""
print("\n=== Testing Error Scenarios ===")
config_loader = ConfigLoader()
env_config = config_loader.load_demo_config()
ops = OdooOperations(env_config, verbose=True)
# Test with exception handling
print("\n1. Testing exception handling with streaming:")
try:
ops.update_module("module_error", suppress_output=True, raise_on_error=True)
print(" This shouldn't print")
except ModuleUpdateError as e:
print(f" ✓ Caught expected error: {e}")
if e.operation_result:
print(f" Error details: {e.operation_result.get('error', 'No details')}")
# Test module installation error
print("\n2. Testing installation error:")
result = ops.install_module("module_error", suppress_output=True)
print(f" Install result: {result['success']}")
def main():
"""Main demo function"""
print("🚀 Enhanced ODUIT Demo Mode with Log Streaming")
print("=" * 60)
try:
test_streaming_logs()
compare_demo_vs_real()
test_error_scenarios()
print("\n✅ Enhanced demo completed successfully!")
print("\nNew features demonstrated:")
print("• 📡 Progressive log streaming with timestamps")
print("• ⏱️ Realistic processing delays")
print("• 🔍 Detailed error scenario simulation")
print("• 🎭 Multiple module behavior patterns")
print("• 🔄 Stream-based output like real Odoo")
return 0
except Exception as e:
print(f"\n❌ Demo failed with error: {e}")
import traceback
traceback.print_exc()
return 1
if __name__ == "__main__":
exit(main())
Streaming structured process output
#!/usr/bin/env python3
"""
Example demonstrating the run_command_yielding method in ProcessManager.
The run_command_yielding method is a generator that yields output lines as they arrive,
allowing for real-time processing of command output. This is useful for:
- Real-time log processing and filtering
- Building interactive applications that need to react to command output
- Creating custom progress indicators based on command output
- Processing large amounts of output without storing it all in memory
"""
import time
from oduit.process_manager import ProcessManager
def main():
# Initialize the process manager
pm = ProcessManager()
print("=== ProcessManager run_command_yielding Examples ===\n")
# Example 1: Basic usage with simple command
print("1. Basic yielding with echo command:")
print(" Running: echo -e 'Line 1\\nLine 2\\nLine 3'")
line_count = 0
for item in pm.run_command_yielding(
["echo", "-e", "Line 1\nLine 2\nLine 3"],
verbose=True,
suppress_output=True, # Suppress direct output to see yielded lines
):
if "line" in item:
line_count += 1
line_content = item["line"].strip()
if line_content: # Skip empty lines
print(f" 📝 Yielded line {line_count}: '{line_content}'")
print(
f" Should show: {item['should_show']}, "
f"Is error: {item['is_error']}"
)
else:
# Final result
result = item["result"]
print(
f" ✅ Final result: Success={result['success']}, "
f"Return code={result['return_code']}"
)
print()
# Example 2: Error detection with yielding
print("2. Error detection with yielding:")
print(
" Running: echo -e 'Normal line\\nERROR: Something went wrong\\nAnother line'"
)
error_count = 0
normal_count = 0
for item in pm.run_command_yielding(
["echo", "-e", "Normal line\nERROR: Something went wrong\nAnother line"],
verbose=True,
suppress_output=True,
):
if "line" in item:
line_content = item["line"].strip()
if line_content: # Skip empty lines
if item["is_error"]:
error_count += 1
print(f" 🚨 ERROR detected: '{line_content}'")
else:
normal_count += 1
print(f" ℹ️ Normal line: '{line_content}'")
else:
result = item["result"]
print(
f" 📊 Stats: {normal_count} normal lines, {error_count} error lines"
)
print(f" ✅ Command completed: Success={result['success']}")
print()
# Example 3: Real-time processing simulation
print("3. Real-time processing with longer command:")
print(" Running: python -c with multiple print statements")
python_code = """
import time
for i in range(5):
print(f"Processing step {i+1}/5...")
time.sleep(0.1)
print("Processing complete!")
"""
start_time = time.time()
for item in pm.run_command_yielding(
["python", "-c", python_code], verbose=False, suppress_output=True
):
if "line" in item:
line_content = item["line"].strip()
if line_content:
elapsed = time.time() - start_time
print(f" [{elapsed:.1f}s] {line_content}")
else:
result = item["result"]
total_time = time.time() - start_time
print(f" ⏱️ Total execution time: {total_time:.1f}s")
print(f" ✅ Success: {result['success']}")
print()
# Example 4: Custom output filtering
print("4. Custom output filtering:")
print(" Running command and filtering for specific patterns")
filter_cmd = [
"echo",
"-e",
"INFO: Starting process\nDEBUG: Detailed info\nWARNING: Minor issue\n"
"ERROR: Critical problem\nINFO: Process complete",
]
important_lines = []
for item in pm.run_command_yielding(filter_cmd, suppress_output=True):
if "line" in item:
line = item["line"].strip()
# Filter for INFO, WARNING, and ERROR lines only (skip DEBUG)
if any(level in line for level in ["INFO:", "WARNING:", "ERROR:"]):
important_lines.append(line)
level = (
"ERROR"
if "ERROR:" in line
else "WARNING"
if "WARNING:" in line
else "INFO"
)
emoji = "🚨" if level == "ERROR" else "⚠️" if level == "WARNING" else "ℹ️"
print(f" {emoji} [{level}] {line}")
else:
result = item["result"]
print(f" 📋 Filtered {len(important_lines)} important lines from output")
print()
# Example 5: Memory-efficient processing of large output
print("5. Memory-efficient processing (simulated large output):")
print(" Demonstrating how yielding prevents memory buildup")
# Simulate processing a command that produces lots of output
large_output_cmd = [
"python",
"-c",
"for i in range(50): print(f'Data line {i:03d}: Some content here')",
]
processed_lines = 0
memory_friendly_summary = []
for item in pm.run_command_yielding(large_output_cmd, suppress_output=True):
if "line" in item:
processed_lines += 1
line = item["line"].strip()
# Process line immediately without storing full content
if line and "Data line" in line:
# Extract just the line number for summary
try:
line_num = line.split("Data line ")[1].split(":")[0]
if int(line_num) % 10 == 0: # Every 10th line
memory_friendly_summary.append(f"Checkpoint at line {line_num}")
print(f" 📍 Processed line {line_num}")
except (IndexError, ValueError):
pass
else:
result = item["result"]
print(f" ✅ Processed {processed_lines} lines efficiently")
print(
f" 💾 Memory summary: {len(memory_friendly_summary)} "
f"checkpoints stored"
)
print("\n=== Summary ===")
print("✅ run_command_yielding provides:")
print(" • Real-time line-by-line output processing")
print(" • Memory-efficient handling of large outputs")
print(" • Custom filtering and analysis capabilities")
print(" • Error detection and immediate response")
print(" • Same error handling and cleanup as run_command")
if __name__ == "__main__":
main()
Addon and Manifest Workflows
Manifest inspection
#!/usr/bin/env python3
"""
Example script showing how to parse Odoo module manifests and build dependency
graphs using oduit.
This example demonstrates:
1. Parsing module manifest files
2. Getting module dependencies
3. Building complete dependency graphs
4. Creating hierarchical dependency trees
5. Getting proper module installation order
6. Finding missing dependencies
7. Finding reverse dependencies (modules that depend on a given module)
8. Error handling for missing or invalid manifests
"""
from oduit.config_loader import ConfigLoader
from oduit.module_manager import ModuleManager
def print_dependency_graph(
graph: dict[str, list[str]], title: str = "Dependency Graph"
):
"""Helper function to pretty print dependency graphs."""
print(f"\n{title}:")
print("-" * len(title))
for module, deps in graph.items():
if deps:
print(f" {module} → {', '.join(deps)}")
else:
print(f" {module} (no dependencies)")
def print_dependency_tree(tree: dict, indent: int = 0):
"""Helper function to pretty print dependency trees."""
for module, subtree in tree.items():
print(" " * indent + f"├─ {module}")
if subtree:
print_dependency_tree(subtree, indent + 1)
def main(): # noqa: C901
# Load configuration using ConfigLoader
config_loader = ConfigLoader()
try:
env_config = config_loader.load_local_config()
addons_path = env_config.get(
"addons_path", "/opt/odoo/addons,/opt/custom/addons"
)
print("Loaded configuration from local .oduit.toml")
print(f"Using addons_path: {addons_path}")
except Exception as e:
print(f"Could not load config: {e}")
print("Using default addons_path")
addons_path = "/opt/odoo/addons,/opt/custom/addons"
# Initialize the module manager
module_manager = ModuleManager(addons_path)
try:
# Example 1: Parse a module manifest
module_name = "base" # Base module should exist in most Odoo installations
print(f"Parsing manifest for module: {module_name}")
manifest = module_manager.parse_manifest(module_name)
if manifest:
print(f"✓ Successfully parsed manifest for {module_name}")
print(f" Name: {manifest.get('name', 'Unknown')}")
print(f" Version: {manifest.get('version', 'Unknown')}")
print(f" Installable: {manifest.get('installable', False)}")
print(f" Auto-install: {manifest.get('auto_install', False)}")
else:
print(f"✗ Module {module_name} not found or has no manifest")
# Example 2: Get direct manifest dependencies
print(f"\nGetting direct manifest dependencies for module: {module_name}")
codependencies = module_manager.get_module_codependencies(module_name)
if codependencies:
print(
f"✓ Module {module_name} has {len(codependencies)} direct dependencies:"
)
for dep in codependencies:
print(f" - {dep}")
else:
print(f"✓ Module {module_name} has no direct manifest dependencies")
# Example 3: Build complete dependency graph
print(f"\nBuilding dependency graph for module: {module_name}")
try:
graph = module_manager.build_dependency_graph(module_name)
print(f"✓ Successfully built dependency graph with {len(graph)} modules")
print_dependency_graph(
graph, f"Complete dependency graph for {module_name}"
)
except ValueError as e:
print(f"✗ Error building dependency graph: {e}")
# Example 4: Get hierarchical dependency tree
print(f"\nBuilding dependency tree for module: {module_name}")
try:
tree = module_manager.get_dependency_tree(module_name)
print("✓ Successfully built dependency tree")
print(f"\nHierarchical dependency tree for {module_name}:")
print("-" * 40)
print_dependency_tree(tree)
except ValueError as e:
print(f"✗ Error building dependency tree: {e}")
# Example 5: Test with a common module that has dependencies
common_modules = ["web", "sale", "account", "stock"]
print("\nChecking direct manifest dependencies for common modules...")
for mod in common_modules:
deps = module_manager.get_module_codependencies(mod)
if deps: # Only print if module exists and has dependencies
print(f" {mod}: {', '.join(deps)}")
# Example 6: Demonstrate graph building for a module with complex dependencies
complex_module = "sale" # Sale module typically has multiple dependencies
print(f"\nBuilding dependency graph for complex module: {complex_module}")
try:
complex_graph = module_manager.build_dependency_graph(complex_module)
print(f"✓ Built graph with {len(complex_graph)} total modules")
# Show only modules with dependencies
modules_with_deps = {k: v for k, v in complex_graph.items() if v}
if modules_with_deps:
print_dependency_graph(
modules_with_deps,
f"Modules with dependencies in {complex_module} graph",
)
except ValueError as e:
print(f"✗ Could not build dependency graph for {complex_module}: {e}")
# Example 7: Get installation order for modules
print("\n" + "=" * 60)
print("Installation Planning Features")
print("=" * 60)
test_modules = ["base", "web"]
print(f"\nGetting installation order for modules: {', '.join(test_modules)}")
try:
install_order = module_manager.get_install_order(*test_modules)
print(f"✓ Installation order: {' → '.join(install_order)}")
print(" (Install modules in this order to satisfy dependencies)")
except Exception as e:
print(f"✗ Could not determine install order: {type(e).__name__}: {e}")
import traceback
traceback.print_exc()
# Example 8: Find missing dependencies
print(f"\nChecking for missing dependencies in module: {complex_module}")
try:
missing_deps = module_manager.find_missing_dependencies(complex_module)
if missing_deps:
print(f"✗ Missing dependencies found: {', '.join(missing_deps)}")
print(" These modules are required but not found in addons_path")
else:
print(f"✓ All dependencies for {complex_module} are available")
except ValueError as e:
print(f"✗ Error checking dependencies: {e}")
# Example 9: Find reverse dependencies
base_module = "base"
print(f"\nFinding modules that depend on: {base_module}")
try:
reverse_deps = module_manager.get_reverse_dependencies(base_module)
if reverse_deps:
print(
f"✓ Found {len(reverse_deps)} modules that depend on {base_module}:"
)
# Show first 10 to avoid overwhelming output
for dep in reverse_deps[:10]:
print(f" - {dep}")
if len(reverse_deps) > 10:
print(f" ... and {len(reverse_deps) - 10} more modules")
else:
print(f"✓ No modules depend on {base_module}")
except Exception as e:
print(f"✗ Error finding reverse dependencies: {e}")
# Example 10: Demonstrate installation planning
planning_modules = ["account", "sale"]
print(
f"\nDemonstrating installation planning for: {', '.join(planning_modules)}"
)
try:
# Check for missing dependencies first
all_missing = set()
for mod in planning_modules:
try:
missing = module_manager.find_missing_dependencies(mod)
all_missing.update(missing)
except ValueError:
pass
if all_missing:
missing_list = ", ".join(sorted(all_missing))
print(f"⚠ Warning: Missing dependencies: {missing_list}")
# Get installation order
install_order = module_manager.get_install_order(*planning_modules)
print("✓ Recommended installation order:")
for i, module in enumerate(install_order, 1):
print(f" {i}. {module}")
except ValueError as e:
print(f"✗ Installation planning failed: {e}")
except ValueError as e:
print(f"✗ Error parsing manifest: {e}")
return 1
except Exception as e:
print(f"✗ Unexpected error: {e}")
return 1
return 0
if __name__ == "__main__":
exit(main())
Trusted Code Execution
Executing trusted Python through the Odoo shell interface
#!/usr/bin/env python3
"""
Example script showing the new execute_python_code function in OdooOperations.
This example demonstrates:
1. Using the simplified execute_python_code method with an explicit
shell_interface
2. Executing single Python commands in Odoo environment
3. Executing multiple Python commands
4. Error handling with the new function
5. Comparison with the manual approach
"""
from oduit.config_loader import ConfigLoader
from oduit.odoo_operations import OdooOperations
def main():
# Initialize configuration and operations
config_loader = ConfigLoader()
env_config = config_loader.load_local_config()
odoo_ops = OdooOperations(env_config, verbose=True)
odoo_ops_quiet = OdooOperations(env_config, verbose=False)
print("=== New execute_python_code Examples ===\n")
print("Using shell_interface='python' for all execute_python_code() calls.\n")
try:
# Run examples
run_simple_example(odoo_ops)
run_environment_info_example(odoo_ops_quiet)
run_query_data_example(odoo_ops_quiet)
run_error_handling_example(odoo_ops_quiet)
run_statistics_example(odoo_ops_quiet)
except FileNotFoundError as e:
print(f"Configuration file not found: {e}")
print("Available environments:", config_loader.get_available_environments())
return 1
except Exception as e:
print(f"Error: {e}")
return 1
print_summary()
return 0
def run_simple_example(odoo_ops):
"""Run simple Python code execution example"""
print("1. Simple Python code execution:")
python_code = "print('Partners found:', len(env['res.partner'].search([])))"
print(f" Code: {python_code}")
result = odoo_ops.execute_python_code(
python_code=python_code,
capture_output=True,
shell_interface="python",
)
if result["success"]:
print(" ✓ Output:")
for line in result["stdout"].strip().split("\n"):
if line.strip() and "Partners found:" in line:
print(f" {line}")
else:
print(f" ✗ Error: {result.get('error', 'Unknown error')}")
print()
def run_environment_info_example(odoo_ops):
"""Run environment information query example"""
print("2. Environment information query:")
env_info_code = """
print('=== Odoo Environment Info ===')
print('Database:', env.cr.dbname)
print('User:', env.user.name)
print('Company:', env.company.name)
partner_count = len(env['res.partner'].search([]))
print('Total partners:', partner_count)
print('=== Done ===')
"""
result = odoo_ops.execute_python_code(
python_code=env_info_code,
capture_output=True,
shell_interface="python",
)
if result["success"]:
print(" ✓ Output:")
for line in result["stdout"].strip().split("\n"):
if line.strip() and any(
keyword in line
for keyword in [
"Database:",
"User:",
"Company:",
"Total partners:",
"===",
]
):
print(f" {line}")
else:
print(f" ✗ Error: {result.get('error', 'Unknown error')}")
print()
def run_query_data_example(odoo_ops):
"""Run query specific data example"""
print("3. Query specific data:")
query_code = """
partners = env['res.partner'].search([('is_company', '=', True)], limit=3)
print('=== Company Partners ===')
for partner in partners:
print('-', partner.name, '(ID:', str(partner.id) + ')')
companies_total = len(env['res.partner'].search([('is_company', '=', True)]))
print('Total companies:', companies_total)
"""
result = odoo_ops.execute_python_code(
python_code=query_code,
capture_output=True,
shell_interface="python",
)
if result["success"]:
print(" ✓ Output:")
for line in result["stdout"].strip().split("\n"):
if line.strip() and (
"Company Partners" in line
or line.strip().startswith("-")
or "Total companies:" in line
):
print(f" {line}")
else:
print(f" ✗ Error: {result.get('error', 'Unknown error')}")
print()
def run_error_handling_example(odoo_ops):
"""Run error handling example"""
print("4. Error handling example:")
error_code = "print(nonexistent_variable)"
result = odoo_ops.execute_python_code(
python_code=error_code,
capture_output=True,
shell_interface="python",
)
if result["success"]:
print(" ✓ Unexpected success")
else:
print(" ✓ Expected error caught")
if "NameError" in result.get("stdout", "") or "NameError" in result.get(
"stderr", ""
):
print(" Error type: NameError (variable not defined)")
print()
def run_statistics_example(odoo_ops):
"""Run complex calculation example"""
print("5. Complex calculation example:")
calc_code = """
# Calculate some statistics
user_count = len(env['res.users'].search([]))
partner_count = len(env['res.partner'].search([]))
company_count = len(env['res.partner'].search([('is_company', '=', True)]))
print('=== Odoo Statistics ===')
print(f'Users: {user_count}')
print(f'Partners: {partner_count}')
print(f'Companies: {company_count}')
print(f'Individual contacts: {partner_count - company_count}')
print('=== End Statistics ===')
"""
result = odoo_ops.execute_python_code(
python_code=calc_code,
capture_output=True,
shell_interface="python",
)
if result["success"]:
print(" ✓ Statistics:")
for line in result["stdout"].strip().split("\n"):
if line.strip() and any(
keyword in line
for keyword in [
"Users:",
"Partners:",
"Companies:",
"Individual contacts:",
"===",
]
):
print(f" {line}")
else:
print(f" ✗ Error: {result.get('error', 'Unknown error')}")
print()
def print_summary():
"""Print summary of the examples"""
print("=== Summary ===")
print("✓ execute_python_code() simplifies Odoo shell interaction")
print("✓ A shell_interface must be passed or configured")
print("✓ No need to manually build commands or handle pipes")
print("✓ Built-in error handling and result parsing")
print("✓ Supports both simple and complex Python code execution")
print("✓ Consistent return format with other oduit operations")
if __name__ == "__main__":
exit(main())
Inspection and Database Workflows
oduit --env dev inspect ref base.action_partner_form
oduit --env dev inspect model res.partner
oduit --env dev inspect field res.partner email --with-db
oduit --env dev db table res_partner
oduit --env dev performance slow-queries --limit 10
oduit --env dev manifest check sale
Demo Mode
Demo-mode operations
#!/usr/bin/env python3
"""
Example script demonstrating the demo mode functionality in oduit.
This example shows:
1. Loading demo configuration without requiring a real Odoo installation
2. Testing different module behaviors (success, error, warning)
3. Using all operations in demo mode for development and testing
"""
from oduit.config_loader import ConfigLoader
from oduit.odoo_operations import ModuleInstallError, OdooOperations
def test_module_operations():
"""Test module install/update operations in demo mode"""
print("=== Testing Module Operations in Demo Mode ===")
config_loader = ConfigLoader()
env_config = config_loader.load_demo_config()
ops = OdooOperations(env_config, verbose=True)
# Test successful module update
print("\n1. Testing successful module update:")
result = ops.update_module("module_ok", suppress_output=True)
print(f" Success: {result['success']}")
print(f" Duration: {result['duration']:.2f}s")
print(f" Output: {result['stdout'][:100]}...")
# Test module with warnings
print("\n2. Testing module with warnings:")
result = ops.update_module("module_warning", suppress_output=True)
print(f" Success: {result['success']}")
print(f" Output: {result['stdout'][:100]}...")
# Test failing module
print("\n3. Testing failing module:")
result = ops.update_module("module_error", suppress_output=True)
print(f" Success: {result['success']}")
print(f" Error: {result.get('error', 'No error message')}")
# Test unknown module
print("\n4. Testing unknown module:")
result = ops.update_module("unknown_module", suppress_output=True)
print(f" Success: {result['success']}")
print(f" Output: {result['stdout']}")
# Test with exception handling
print("\n5. Testing with exception handling:")
try:
ops.install_module("module_error", suppress_output=True, raise_on_error=True)
print(" This shouldn't print")
except ModuleInstallError as e:
print(f" ✓ Caught expected error: {e}")
def test_other_operations():
"""Test other operations in demo mode"""
print("\n=== Testing Other Operations in Demo Mode ===")
config_loader = ConfigLoader()
env_config = config_loader.load_demo_config()
ops = OdooOperations(env_config, verbose=True)
# Test database creation
print("\n1. Testing database creation:")
result = ops.create_db(suppress_output=True)
print(f" Success: {result['success']}")
print(f" Database: {result['database']}")
# Test addon creation
print("\n2. Testing addon creation:")
ops.create_addon("test_addon", template="default")
# Test language export
print("\n3. Testing language export:")
ops.export_module_language(module="sale", filename="test.po", language="en_US")
# Test module tests
print("\n4. Testing module tests:")
result = ops.run_tests(module="sale", compact=True)
print(f" Test success: {result['success']}")
def test_demo_vs_real_mode():
"""Demonstrate difference between demo and real mode"""
print("\n=== Demo Mode vs Real Mode Comparison ===")
config_loader = ConfigLoader()
demo_config = config_loader.load_demo_config()
print(f"Demo mode enabled: {demo_config.get('demo_mode', False)}")
print(f"Available demo modules: {demo_config['available_modules']}")
# Regular config would look like this (commented out since we don't have
# real config)
# try:
# real_config = load_config("development") # Would load real config
# print(f"Real mode: {real_config.get('demo_mode', False)}")
# except:
# print("No real config available - that's fine for this demo")
ops = OdooOperations(demo_config, verbose=True)
# Show that the same operation behaves differently
print("\n1. Same operation, different behaviors:")
# In demo mode - will succeed
result1 = ops.update_module("sale", suppress_output=True)
print(f" Demo mode result: {result1['success']} (simulated)")
# In real mode - would try to execute actual odoo-bin command
# result2 = ops.update_module(
# real_config, "sale", verbose=True, suppress_output=True
# )
# print(f" Real mode result: {result2['success']} (would run real command)")
def main():
"""Main demo function"""
print("🚀 ODUIT Demo Mode Example")
print("=" * 50)
try:
test_module_operations()
test_other_operations()
test_demo_vs_real_mode()
print("\n✅ All demo tests completed successfully!")
print("\nDemo mode allows you to:")
print("• Test oduit functionality without Odoo installation")
print("• Simulate different module behaviors (success/error/warning)")
print("• Develop and test scripts safely")
print("• Run CI/CD tests without database dependencies")
return 0
except Exception as e:
print(f"\n❌ Demo failed with error: {e}")
import traceback
traceback.print_exc()
return 1
if __name__ == "__main__":
exit(main())
Configuration Examples
Preferred local config:
[binaries]
python_bin = "./venv/bin/python"
odoo_bin = "./odoo/odoo-bin"
[odoo_params]
addons_path = "./addons"
db_name = "project_dev"
Compatibility support still exists for YAML and flat config files, but new examples should prefer sectioned TOML.