Skip to content

Commit 9b95018

Browse files
authored
Merge pull request #4 from LexianDEV/copilot/fix-b0d0c987-905e-4993-921c-a4b95eee0759
Implement async foundation and modularize application structure
2 parents 1944678 + d0060bb commit 9b95018

6 files changed

Lines changed: 228 additions & 39 deletions

File tree

main.py

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,17 @@
1-
import helpers
1+
"""
2+
General Python Template - Main Entry Point
3+
Minimal async-coordinated entry point that delegates to modules.
4+
"""
5+
6+
import asyncio
7+
from modules import AppModule
8+
9+
10+
async def main():
11+
"""Main application entry point with async foundation."""
12+
app = AppModule()
13+
await app.start()
214

3-
def main():
4-
print("=== General Python Template ===")
5-
print(f"Current time: {helpers.time()}")
6-
print()
7-
8-
# Get basic app configuration
9-
app_name = helpers.get_config('app.name', 'Unknown App')
10-
app_version = helpers.get_config('app.version', '0.0.0')
11-
app_env = helpers.get_config('app.env', 'unknown')
12-
app_debug = helpers.get_config('app.debug', False)
13-
14-
print(f"App: {app_name} v{app_version}")
15-
print(f"Environment: {app_env} (Debug: {app_debug})")
16-
print()
17-
18-
# Demonstrate the configurable response number
19-
response_number = helpers.get_config('app.response_number', 0)
20-
message = helpers.get_config('app.message', 'Hello, World!')
21-
22-
print("=== App Response ===")
23-
print(f"Message: {message}")
24-
print(f"Response Number: {response_number}")
25-
print()
26-
27-
# Show environment variable overrides
28-
print("=== Configuration Source ===")
29-
env_number = helpers.env('APP_RESPONSE_NUMBER')
30-
if env_number:
31-
print(f"Response number is overridden by environment variable: {env_number}")
32-
else:
33-
print(f"Response number is from config file: {response_number}")
34-
35-
env_message = helpers.env('APP_MESSAGE')
36-
if env_message:
37-
print(f"Message is overridden by environment variable: {env_message}")
38-
else:
39-
print(f"Message is from config file: {message}")
4015

4116
if __name__ == '__main__':
42-
main()
17+
asyncio.run(main())

modules/.gitkeep

Whitespace-only changes.

modules/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""
2+
Modules package for the General Python Template.
3+
Contains organized functionality extracted from main application.
4+
"""
5+
6+
from .app import AppModule
7+
from .display import DisplayModule
8+
9+
__all__ = ['AppModule', 'DisplayModule']

modules/app.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""
2+
Main application module with async foundation.
3+
Coordinates application logic and flow.
4+
"""
5+
6+
import asyncio
7+
from .display import DisplayModule
8+
9+
10+
class AppModule:
11+
"""Main application module with async support."""
12+
13+
def __init__(self):
14+
"""Initialize the application module."""
15+
self.display = DisplayModule()
16+
17+
async def run(self):
18+
"""Run the main application logic asynchronously."""
19+
# Run all display sections
20+
await self.display.show_all()
21+
22+
async def initialize(self):
23+
"""Initialize the application (async setup)."""
24+
# Placeholder for any async initialization
25+
# This could include database connections, API setup, etc.
26+
pass
27+
28+
async def cleanup(self):
29+
"""Clean up resources (async teardown)."""
30+
# Placeholder for any async cleanup
31+
# This could include closing connections, saving state, etc.
32+
pass
33+
34+
async def start(self):
35+
"""Start the application with full lifecycle management."""
36+
try:
37+
await self.initialize()
38+
await self.run()
39+
finally:
40+
await self.cleanup()
41+
42+
async def start_with_async_demo(self):
43+
"""
44+
Start the application with async demonstration.
45+
Shows how the async foundation can be utilized.
46+
"""
47+
try:
48+
await self.initialize()
49+
# Use the async demo display method
50+
await self.display.show_with_delay(0.05)
51+
finally:
52+
await self.cleanup()

modules/display.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""
2+
Display module for managing application output and presentation.
3+
Handles all display-related functionality with async support.
4+
"""
5+
6+
import asyncio
7+
import helpers
8+
9+
10+
class DisplayModule:
11+
"""Handles application display and output functionality."""
12+
13+
def __init__(self):
14+
"""Initialize the display module."""
15+
pass
16+
17+
async def show_header(self):
18+
"""Display the application header."""
19+
print("=== General Python Template ===")
20+
print(f"Current time: {helpers.time()}")
21+
print()
22+
23+
async def show_app_info(self):
24+
"""Display application information."""
25+
# Get basic app configuration
26+
app_name = helpers.get_config('app.name', 'Unknown App')
27+
app_version = helpers.get_config('app.version', '0.0.0')
28+
app_env = helpers.get_config('app.env', 'unknown')
29+
app_debug = helpers.get_config('app.debug', False)
30+
31+
print(f"App: {app_name} v{app_version}")
32+
print(f"Environment: {app_env} (Debug: {app_debug})")
33+
print()
34+
35+
async def show_app_response(self):
36+
"""Display the application response section."""
37+
response_number = helpers.get_config('app.response_number', 0)
38+
message = helpers.get_config('app.message', 'Hello, World!')
39+
40+
print("=== App Response ===")
41+
print(f"Message: {message}")
42+
print(f"Response Number: {response_number}")
43+
print()
44+
45+
async def show_config_source(self):
46+
"""Display configuration source information."""
47+
response_number = helpers.get_config('app.response_number', 0)
48+
message = helpers.get_config('app.message', 'Hello, World!')
49+
50+
print("=== Configuration Source ===")
51+
52+
# Check response number source
53+
env_number = helpers.env('APP_RESPONSE_NUMBER')
54+
if env_number:
55+
print(f"Response number is overridden by environment variable: {env_number}")
56+
else:
57+
print(f"Response number is from config file: {response_number}")
58+
59+
# Check message source
60+
env_message = helpers.env('APP_MESSAGE')
61+
if env_message:
62+
print(f"Message is overridden by environment variable: {env_message}")
63+
else:
64+
print(f"Message is from config file: {message}")
65+
66+
async def show_all(self):
67+
"""Display all application information sections."""
68+
await self.show_header()
69+
await self.show_app_info()
70+
await self.show_app_response()
71+
await self.show_config_source()
72+
73+
async def show_with_delay(self, delay_seconds: float = 0.1):
74+
"""
75+
Example of async functionality - show all sections with small delays.
76+
This demonstrates the async foundation in action.
77+
"""
78+
await self.show_header()
79+
await asyncio.sleep(delay_seconds)
80+
81+
await self.show_app_info()
82+
await asyncio.sleep(delay_seconds)
83+
84+
await self.show_app_response()
85+
await asyncio.sleep(delay_seconds)
86+
87+
await self.show_config_source()

tests/test_async.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
Simple test for async functionality.
3+
"""
4+
5+
import asyncio
6+
import sys
7+
import os
8+
9+
# Add the project root to the path
10+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
11+
12+
from modules import AppModule, DisplayModule
13+
14+
15+
async def test_async_foundation():
16+
"""Test that async foundation works properly."""
17+
print("Testing async foundation...")
18+
19+
# Test display module async methods
20+
display = DisplayModule()
21+
22+
# These should run without error
23+
await display.show_header()
24+
await display.show_app_info()
25+
await display.show_app_response()
26+
await display.show_config_source()
27+
28+
print("✓ All async display methods work")
29+
30+
# Test app module
31+
app = AppModule()
32+
await app.initialize()
33+
await app.cleanup()
34+
35+
print("✓ App module lifecycle methods work")
36+
37+
return True
38+
39+
40+
async def test_main_functionality():
41+
"""Test the main app functionality through async interface."""
42+
print("Testing main app functionality through async...")
43+
44+
app = AppModule()
45+
# This should produce the same output as before
46+
await app.run()
47+
48+
print("✓ Main functionality works through async interface")
49+
return True
50+
51+
52+
async def run_async_tests():
53+
"""Run all async tests."""
54+
try:
55+
await test_async_foundation()
56+
await test_main_functionality()
57+
print("\n✅ All async tests passed!")
58+
return True
59+
except Exception as e:
60+
print(f"\n❌ Async test failed: {e}")
61+
return False
62+
63+
64+
if __name__ == "__main__":
65+
success = asyncio.run(run_async_tests())
66+
sys.exit(0 if success else 1)

0 commit comments

Comments
 (0)