Skip to content

Commit cf217c4

Browse files
committed
Added a module on refactoring with IT use cases
1 parent 35be43a commit cf217c4

10 files changed

+532
-558
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55

66
gh-cp-venv/
77

8-
99-archive/
8+
99-archive/
9+
10+
*__pycache__/

04-refactoring/IT/mock_ping.py

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from typing import Union, Optional
2+
from dataclasses import dataclass
3+
from enum import Enum
4+
import time
5+
6+
class ServerStatus(Enum):
7+
UP = "UP"
8+
DOWN = "DOWN"
9+
TIMEOUT = "TIMEOUT"
10+
DNS_ERROR = "DNS_ERROR"
11+
UNAUTHORIZED = "UNAUTHORIZED"
12+
13+
@dataclass
14+
class PingResult:
15+
status: ServerStatus
16+
response_time: float
17+
error_message: Optional[str] = None
18+
19+
def __bool__(self):
20+
return self.status == ServerStatus.UP
21+
22+
class MockPingError(Exception):
23+
"""Base exception for mock ping errors"""
24+
pass
25+
26+
class MockDNSError(MockPingError):
27+
"""Raised when DNS resolution fails"""
28+
pass
29+
30+
class MockTimeoutError(MockPingError):
31+
"""Raised when ping times out"""
32+
pass
33+
34+
class MockAuthenticationError(MockPingError):
35+
"""Raised when authentication is required but not provided"""
36+
pass
37+
38+
def mock_ping(server: str, timeout: float = 1.0, require_auth: bool = False) -> PingResult:
39+
"""
40+
Simulates pinging a server with various realistic scenarios
41+
42+
Args:
43+
server: Server address to ping
44+
timeout: Maximum time to wait for response
45+
require_auth: Whether authentication is required
46+
47+
Returns:
48+
PingResult object containing status and response information
49+
50+
Raises:
51+
MockDNSError: If DNS resolution fails
52+
MockTimeoutError: If ping times out
53+
MockAuthenticationError: If authentication is required but not provided
54+
ValueError: If server parameter is invalid
55+
"""
56+
if not isinstance(server, str):
57+
raise ValueError(f"Server must be a string, got {type(server).__name__}")
58+
59+
if not server:
60+
raise ValueError("Server address cannot be empty")
61+
62+
if server.startswith("timeout"):
63+
time.sleep(timeout + 0.1)
64+
raise MockTimeoutError(f"Connection to {server} timed out after {timeout} seconds")
65+
66+
if server.startswith("auth") and not require_auth:
67+
raise MockAuthenticationError(f"Authentication required for {server}")
68+
69+
if ".invalid" in server:
70+
raise MockDNSError(f"Could not resolve hostname: {server}")
71+
72+
mock_responses = {
73+
"192.168.1.1": PingResult(ServerStatus.UP, 0.001),
74+
"example.com": PingResult(ServerStatus.DOWN, 0.0, "Connection refused"),
75+
"localhost": PingResult(ServerStatus.UP, 0.0001),
76+
"slow.server": PingResult(ServerStatus.UP, 0.8),
77+
"firewall.blocked": PingResult(ServerStatus.DOWN, 0.001, "Connection blocked by firewall")
78+
}
79+
80+
response_time = timeout * 0.1
81+
82+
return mock_responses.get(
83+
server,
84+
PingResult(ServerStatus.DOWN, response_time, f"Unknown host: {server}")
85+
)
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import datetime
2+
from mock_ping import mock_ping
3+
from io import StringIO
4+
5+
def check_server_availability(servers):
6+
output = StringIO()
7+
8+
# Write header with timestamp
9+
output.write(f"Time: {datetime.datetime.now()}\n")
10+
11+
# Check each server
12+
for server in servers:
13+
try:
14+
result = mock_ping(server)
15+
status = "UP" if result else "DOWN"
16+
output.write(f"{server} is {status}\n")
17+
except:
18+
output.write(f"Error checking server {server}\n")
19+
20+
# Print and return the complete output
21+
result = output.getvalue()
22+
print(result)
23+
return
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import datetime
2+
from mock_ping import mock_ping
3+
from io import StringIO
4+
5+
def check_server_availability(servers):
6+
# No input validation or type hints
7+
8+
try:
9+
output = StringIO()
10+
11+
# Write header with timestamp
12+
output.write(f"Time: {datetime.datetime.now()}\n")
13+
14+
for s in servers: # Poor variable naming
15+
try:
16+
# Ignores all the rich information from mock_ping
17+
# and reduces it to just True/False
18+
result = mock_ping(s)
19+
if result == True: # Non-pythonic comparison
20+
f.write(s + " is up\n")
21+
else:
22+
# Ambiguous error messaging
23+
f.write(s + " is down\n")
24+
except: # Bare except clause
25+
# Generic error message without context
26+
f.write("Error checking server\n")
27+
28+
f.close() # Manual file closing
29+
except: # Another bare except
30+
# Unhelpful error message
31+
print("Error writing to log file") # Inconsistent error reporting (print vs write)
32+
return # Silent return on error

04-refactoring/IT/server_availability_refactored.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Server Availability Testing Scenarios\n",
8+
"\n",
9+
"This notebook contains various test scenarios for the server availability script. Each scenario tests different aspects of error handling and edge cases. After refactoring the code, you can rerun these cells to see how the error handling has improved."
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": 12,
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"from server_availability import check_server_availability"
19+
]
20+
},
21+
{
22+
"cell_type": "markdown",
23+
"metadata": {},
24+
"source": [
25+
"## Scenario 1: Basic Server Checks\n",
26+
"Testing basic server availability checks with known servers."
27+
]
28+
},
29+
{
30+
"cell_type": "code",
31+
"execution_count": null,
32+
"metadata": {},
33+
"outputs": [],
34+
"source": [
35+
"basic_servers = [\n",
36+
" \"192.168.1.1\", # Should be up\n",
37+
" \"example.com\", # Should be down\n",
38+
" \"localhost\" # Should be up\n",
39+
"]\n",
40+
"\n",
41+
"check_server_availability(basic_servers)"
42+
]
43+
},
44+
{
45+
"cell_type": "markdown",
46+
"metadata": {},
47+
"source": [
48+
"## Scenario 2: Network Issues\n",
49+
"Testing how the script handles various network-related issues."
50+
]
51+
},
52+
{
53+
"cell_type": "code",
54+
"execution_count": null,
55+
"metadata": {},
56+
"outputs": [],
57+
"source": [
58+
"network_test_servers = [\n",
59+
" \"timeout.example.com\", # Should timeout\n",
60+
" \"auth.internal.network\", # Requires authentication\n",
61+
" \"nonexistent.invalid\", # DNS resolution failure\n",
62+
" \"firewall.blocked\", # Blocked by firewall\n",
63+
" \"timeout.server\" # High latency\n",
64+
"]\n",
65+
"\n",
66+
"check_server_availability(network_test_servers)"
67+
]
68+
},
69+
{
70+
"cell_type": "markdown",
71+
"metadata": {},
72+
"source": [
73+
"## Scenario 3: Input Validation\n",
74+
"Testing how the script handles invalid inputs."
75+
]
76+
},
77+
{
78+
"cell_type": "code",
79+
"execution_count": null,
80+
"metadata": {},
81+
"outputs": [],
82+
"source": [
83+
"edge_case_servers = [\n",
84+
" \"\", # Empty string\n",
85+
" 123, # Wrong type\n",
86+
" \"localhost\", # Valid server\n",
87+
" \"서버.example.com\", # Unicode\n",
88+
" None, # None value\n",
89+
" \" \" # Whitespace only\n",
90+
"]\n",
91+
"\n",
92+
"check_server_availability(edge_case_servers)"
93+
]
94+
},
95+
{
96+
"cell_type": "markdown",
97+
"metadata": {},
98+
"source": [
99+
"## Scenario 4: Multiple Failures\n",
100+
"Testing how the script handles multiple failing cases in sequence."
101+
]
102+
},
103+
{
104+
"cell_type": "code",
105+
"execution_count": null,
106+
"metadata": {},
107+
"outputs": [],
108+
"source": [
109+
"recovery_test_servers = [\n",
110+
" \"192.168.1.1\", # Should succeed\n",
111+
" None, # Should fail\n",
112+
" \"localhost\", # Should succeed\n",
113+
" \"timeout.example.com\", # Should timeout\n",
114+
" \"example.com\", # Should fail\n",
115+
" \"slow.server\" # Should succeed but slow\n",
116+
"]\n",
117+
"\n",
118+
"check_server_availability(recovery_test_servers)"
119+
]
120+
}
121+
],
122+
"metadata": {
123+
"kernelspec": {
124+
"display_name": "gh-cp-venv",
125+
"language": "python",
126+
"name": "python3"
127+
},
128+
"language_info": {
129+
"codemirror_mode": {
130+
"name": "ipython",
131+
"version": 3
132+
},
133+
"file_extension": ".py",
134+
"mimetype": "text/x-python",
135+
"name": "python",
136+
"nbconvert_exporter": "python",
137+
"pygments_lexer": "ipython3",
138+
"version": "3.12.3"
139+
}
140+
},
141+
"nbformat": 4,
142+
"nbformat_minor": 4
143+
}

0 commit comments

Comments
 (0)