📊 5.12 Interpret a Unified Diff
Overview
A unified diff shows the differences between two versions of a file. It's the standard format used by Git, SVN, and other version control systems. Understanding unified diff format is essential for code reviews, merges, and tracking changes.
1. Understanding Unified Diff Format
📄 Basic Diff Structure
Example: A simple unified diff showing a bug fix
--- a/network_config.py
+++ b/network_config.py
@@ -15,10 +15,12 @@ def configure_interface(device, interface):
device.connect()
# Configure interface
- config = f"interface {interface}\n"
- config += "ip address 192.168.1.1 255.255.255.0\n"
- config += "no shutdown"
+ config = [
+ f"interface {interface}",
+ "ip address 192.168.1.1 255.255.255.0",
+ "description Configured by automation",
+ "no shutdown"
+ ]
- device.send_config(config)
+ device.send_config_set(config)
device.disconnect()
# INTERPRETATION:
# - File: network_config.py (modified)
# - Function: configure_interface()
# - Lines affected: 15-25 (hunk starting at line 15)
#
# Changes Made:
# 1. REMOVED: String concatenation for config (lines 18-20)
# - Old: config = f"interface..." + "ip address..." + "no shutdown"
# 2. ADDED: List-based configuration (lines 18-23)
# - New: config = ["interface...", "ip address...", "description...", "no shutdown"]
# 3. ADDED: Description line for documentation
# 4. CHANGED: Method name from send_config() to send_config_set()
# - This accepts list instead of string
#
# Reason: More robust configuration handlingUnified Diff Symbols
| Symbol | Meaning | Example |
|---|---|---|
| --- | Original file | --- a/file.py |
| +++ | Modified file | +++ b/file.py |
| @@ | Hunk header (line ranges) | @@ -15,10 +15,12 @@ |
| - | Line removed | - config = "old" |
| + | Line added | + config = "new" |
| (space) | Unchanged line (context) | device.connect() |
2. Reading Hunk Headers
🔢 Understanding @@ Line Ranges @@
Format: @@ -old_start,old_count +new_start,new_count @@
@@ -15,10 +15,12 @@ def configure_interface(device, interface): BREAKDOWN: -15,10 Old file: Starting at line 15, showing 10 lines +15,12 New file: Starting at line 15, showing 12 lines INTERPRETATION: - The change starts at line 15 in both versions - Old version had 10 lines in this section - New version has 12 lines (2 lines added) - Net change: +2 lines (12 - 10 = 2) OTHER EXAMPLES: @@ -1,5 +1,3 @@ Removed 2 lines (5-3=2) @@ -20,7 +20,7 @@ Same number of lines (modification only) @@ -100,0 +102,3 @@ Added 3 new lines at line 102
Hunk Header Components
| Component | Meaning | Example |
|---|---|---|
| -15,10 | Old file: start line 15, count 10 | Lines 15-24 in original |
| +15,12 | New file: start line 15, count 12 | Lines 15-26 in modified |
| @@...@@ | Hunk delimiter | Marks start of change section |
| Function name | Context (after @@) | def configure_interface(...) |
3. Complex Diff Example - Security Fix
🔒 Multiple Changes in One Diff
Example: Security vulnerability fix with authentication improvement
--- a/api_client.py
+++ b/api_client.py
@@ -8,7 +8,8 @@ import requests
class APIClient:
def __init__(self, base_url, api_key):
- self.base_url = base_url
+ self.base_url = base_url.rstrip('/')
+ self.session = requests.Session()
self.api_key = api_key
def get_devices(self):
@@ -22,12 +23,18 @@ class APIClient:
'X-API-Key': self.api_key
}
- response = requests.get(url, headers=headers)
- return response.json()
+ response = self.session.get(url, headers=headers, timeout=30)
+
+ if response.status_code != 200:
+ raise Exception(f"API Error: {response.status_code}")
+
+ return response.json()
def update_device(self, device_id, config):
- url = f"{self.base_url}/devices/{device_id}"
- response = requests.patch(url, json=config)
+ url = f"{self.base_url}/api/devices/{device_id}"
+ headers = {'X-API-Key': self.api_key}
+
+ response = self.session.patch(url, json=config, headers=headers, timeout=30)
return response.status_code == 200
# INTERPRETATION:
# Changes in __init__ method:
# + Added .rstrip('/') to normalize base_url
# + Added session object for connection reuse
#
# Changes in get_devices():
# - Removed direct requests.get(), using self.session
# + Added timeout parameter (30 seconds)
# + Added error handling for non-200 status codes
# + Raises exception with descriptive error message
#
# Changes in update_device():
# - Old URL: /devices/{id}
# + New URL: /api/devices/{id} (more specific)
# + Added headers with API key (was missing!)
# + Using session instead of direct requests
# + Added timeout
#
# Summary: Fixed 3 security issues
# 1. URL normalization
# 2. Missing authentication headers
# 3. Added error handling and timeoutsCommon Diff Patterns
| Pattern | What It Means |
|---|---|
| - line + line |
Line was modified (removed old, added new) |
| + new line | Line was added (no corresponding - line) |
| - old line | Line was deleted (no corresponding + line) |
| Space + line | Unchanged line (context) |
| Multiple hunks | Changes in different parts of file |
4. Git Diff Examples
🔄 Real-World Git Diff Scenarios
Scenario 1: Bug Fix
diff --git a/utils.py b/utils.py
index 1a2b3c4..5d6e7f8 100644
--- a/utils.py
+++ b/utils.py
@@ -45,7 +45,7 @@ def calculate_total(items):
total = 0
for item in items:
- total += item.price * item.quantity
+ total += item.price * item.quantity * (1 - item.discount)
return total
# INTERPRETATION:
# - File: utils.py
# - Function: calculate_total()
# - Change: Added discount calculation
# - Old behavior: Ignored discounts
# - New behavior: Applies discounts to pricing
# - Impact: Bug fix for pricing calculationScenario 2: Feature Addition
diff --git a/config.yaml b/config.yaml
index abc123..def456 100644
--- a/config.yaml
+++ b/config.yaml
@@ -10,6 +10,12 @@ database:
password: ${DB_PASSWORD}
port: 5432
+cache:
+ enabled: true
+ type: redis
+ host: localhost
+ port: 6379
+ ttl: 3600
+
logging:
level: INFO
# INTERPRETATION:
# - File: config.yaml (configuration file)
# - Addition: New "cache" section
# - Features added:
# * Redis caching enabled
# * Cache configuration (host, port, TTL)
# - No lines removed (pure addition)
# - Impact: Adding caching layer to applicationScenario 3: Refactoring
diff --git a/auth.py b/auth.py
index 111222..333444 100644
--- a/auth.py
+++ b/auth.py
@@ -5,15 +5,20 @@ import hashlib
def authenticate_user(username, password):
- user = database.query("SELECT * FROM users WHERE username = '" + username + "'")
- if user:
- hashed = hashlib.md5(password.encode()).hexdigest()
- if user.password == hashed:
- return True
- return False
+ # Use parameterized query to prevent SQL injection
+ user = database.query(
+ "SELECT * FROM users WHERE username = ?",
+ (username,)
+ )
+
+ if not user:
+ return False
+
+ # Use bcrypt instead of MD5 for password hashing
+ return bcrypt.checkpw(password.encode(), user.password)
# INTERPRETATION:
# - File: auth.py (authentication module)
# - Security fixes applied:
# 1. SQL Injection: Changed from string concatenation to parameterized query
# 2. Weak Hashing: Changed from MD5 to bcrypt
# 3. Code structure: Simplified logic flow
# - Lines removed: 6 lines of insecure code
# - Lines added: 9 lines of secure code
# - Net change: +3 lines
# - Impact: Critical security vulnerability fixedInterpreting Change Impact
| Type of Change | Indicators in Diff |
|---|---|
| Bug Fix | Small modification, similar logic, corrected values |
| Feature Add | Many + lines, few or no - lines, new functions |
| Refactoring | Similar number of +/- lines, same functionality |
| Security Fix | Authentication/validation changes, sanitization added |
| Deletion | Mostly - lines, removing unused code |
👥 5.13 Code Review Process Principles & Benefits
Overview
Code review is a systematic examination of source code by peers before it's merged into the main codebase. It ensures quality, catches bugs early, shares knowledge, and maintains coding standards across the team.
1. Core Principles of Code Review
🎯 Fundamental Principles
Key Principles: Effective code reviews follow established best practices
| Principle | Description |
|---|---|
| Be Constructive | Focus on improving code, not criticizing the person |
| Be Specific | Point to exact lines, provide examples and suggestions |
| Be Thorough | Check functionality, security, performance, and style |
| Be Timely | Review promptly to avoid blocking team members |
| Ask Questions | Understand intent before suggesting changes |
| Praise Good Code | Acknowledge clever solutions and improvements |
| Test the Code | Pull branch locally and verify it works |
| Follow Standards | Ensure code follows team conventions |
2. Benefits of Code Review
✅ Why Code Reviews Matter
Key Benefits: Code reviews provide value far beyond catching bugs
| Benefit | Description | Impact |
|---|---|---|
| Bug Detection | Catch errors before production | Reduced bugs, fewer hotfixes |
| Knowledge Sharing | Team learns from each other's code | Improved team skills, cross-training |
| Code Quality | Maintain high standards | Better maintainability, readability |
| Security | Identify vulnerabilities early | Reduced security risks |
| Consistency | Enforce coding standards | Uniform codebase |
| Mentoring | Senior developers guide juniors | Faster team growth |
| Documentation | Ensure code is well-commented | Easier onboarding, maintenance |
| Collaboration | Team ownership of code | Reduced silos, shared responsibility |
3. Code Review Checklist
🔍 What to Look For
Comprehensive Review Areas: Key aspects to evaluate during review
- Functionality: Does the code do what it's supposed to?
- Logic: Are there any logical errors or edge cases missed?
- Security: SQL injection, XSS, authentication issues?
- Performance: Inefficient loops, unnecessary API calls?
- Error Handling: try/except blocks, proper validation?
- Testing: Unit tests included? Test coverage sufficient?
- Readability: Clear variable names, proper comments?
- Standards: Follows team coding conventions?
- Dependencies: New libraries justified and secure?
- Documentation: Docstrings, README updates?
- Scalability: Will it handle growth?
- Complexity: Is it overly complex? Can it be simplified?
4. Code Review Best Practices
💡 Effective Review Practices
For Reviewers:
- ✅ Review small pull requests (< 400 lines)
- ✅ Leave constructive, actionable comments
- ✅ Suggest improvements with code examples
- ✅ Ask questions to understand design decisions
- ✅ Approve when requirements are met
- ✅ Request changes with clear explanations
- ✅ Use a respectful, collaborative tone
For Authors:
- ✅ Keep pull requests small and focused
- ✅ Write clear PR descriptions
- ✅ Self-review before requesting review
- ✅ Include tests with code changes
- ✅ Respond promptly to feedback
- ✅ Be open to suggestions
- ✅ Update documentation when needed
# Example Pull Request Description ## What does this PR do? Adds error handling and retry logic to Meraki API client ## Why is this change needed? Current implementation fails when API rate limits are hit. This adds exponential backoff retry mechanism. ## How was this tested? - Unit tests added (test_api_retry.py) - Tested against Meraki sandbox with rate limiting - All existing tests pass ## Checklist - [x] Tests included - [x] Documentation updated - [x] No security issues - [x] Follows coding standards ## Related Issues Fixes #123
5. Code Review Tools
🔧 Platform Features
| Platform | Key Features |
|---|---|
| GitHub | Pull Requests, inline comments, status checks, branch protection |
| GitLab | Merge Requests, approval rules, code quality reports |
| Bitbucket | Pull Requests, required reviewers, merge checks |
| Gerrit | Change-based reviews, voting system, automated testing |
Automated Tools
- Linters: pylint, eslint, flake8 (code style)
- Security Scanners: Snyk, SonarQube, Bandit
- Test Coverage: pytest-cov, coverage.py
- Static Analysis: mypy, pytype (type checking)
🔄 5.14 Interpret Sequence Diagrams with API Calls
Overview
Sequence diagrams visualize how different components interact over time through API calls. They show the flow of messages, the order of operations, and the responses between systems, making complex workflows easy to understand.
- Time flows from top to bottom
- Solid arrows (→) are requests/calls
- Dashed arrows (-->) are responses/returns
- Boxes at top represent participants/systems
1. RESTful API Authentication Flow
🔐 User Login with JWT Token Authentication
Workflow: How a user authenticates and makes authorized API calls using tokens
This sequence diagram shows a two-phase process:
- Phase 1 (Lines 1-6): User logs in with username/password, receives a JWT token
- Phase 2 (Lines 7-12): User makes API requests using the token instead of password
Step-by-Step Interpretation
PHASE 1: LOGIN AND GET TOKEN Step 1: User enters username and password into Client App Step 2: Client sends POST request to /api/v1/auth/login with credentials Step 3: Auth API queries Database to verify username and password Step 4: Database confirms user is valid Step 5: Auth API returns 200 OK with JWT token (e.g., "abc123...") Step 6: Client App stores the token locally (memory, localStorage, etc.) PHASE 2: USE TOKEN FOR API CALLS Step 7: User requests to see device list Step 8: Client sends GET /api/v1/devices with "Authorization: Bearer abc123" header Step 9: Device API validates the token is authentic and not expired Step 10: Device API queries Database for device records Step 11: Database returns list of devices Step 12: Device API returns 200 OK with JSON array of devices Step 13: Client App displays devices to User KEY INSIGHTS: ✅ Password is only sent ONCE during login (Step 2) ✅ Token is used for ALL subsequent API calls (Step 8, etc.) ✅ Token can expire and requires re-authentication ✅ More secure than sending password with every request
2. Cisco Meraki API - Network Creation Workflow
☁️ Creating Network and Configuring Wireless SSID
Workflow: Python script automates creation of a new branch network and WiFi configuration
This shows cloud-managed networking where API calls flow through the Meraki Dashboard to cloud controllers, which then push configs to physical devices.
Step-by-Step Interpretation
Step 1-2: Script retrieves organization list using API key authentication → Response: Organization ID 123 named "Corp" Step 3-6: Script creates new wireless network in organization 123 → POST request with network name and type → Meraki provisions network in cloud → Response: Network ID "net-456" created (HTTP 201) Step 7-12: Script configures WiFi SSID on the new network → PUT request to update SSID 0 → Cloud controller receives config update → Config is pushed to physical Access Point → AP applies the configuration → Success confirmation flows back through cloud to API → Response: 200 OK WORKFLOW PATTERN: 1. GET (retrieve org ID) 2. POST (create new resource) 3. PUT/PATCH (configure resource) KEY INSIGHT: • Cloud-managed: Changes go through API → Cloud → Device • No direct device access needed • Centralized management
3. DNA Center Device Provisioning
🎯 Template-Based Device Configuration
Workflow: Automating device discovery and configuration using DNA Center API
Shows how DNA Center discovers devices, assigns them to sites, and deploys configuration templates.
Step-by-Step Interpretation
AUTHENTICATION:
Step 1-4: Script authenticates to DNA Center
→ POST to /auth/token with credentials
→ DNAC validates user in database
→ Returns authentication token (xyz789)
DEVICE DISCOVERY:
Step 5-9: Script initiates device discovery
→ POST device IP address (10.1.1.1)
→ DNAC uses CDP/LLDP to discover device
→ Router responds with device information
→ DNAC stores device in inventory database
→ Returns task ID (202 Accepted - async operation)
TASK MONITORING:
Step 10-11: Script polls for task completion
→ GET /task/{taskId} to check status
→ Returns progress update
TEMPLATE DEPLOYMENT:
Step 12-15: Script deploys configuration template
→ POST with device ID and template ID
→ DNAC pushes config to router via NETCONF
→ Router applies configuration
→ Returns 200 OK (success)
PATTERN:
• Asynchronous operations (discovery returns task ID)
• Polling required for long-running tasks
• Uses NETCONF for device configuration4. RESTCONF Configuration Update with Error Handling
🔧 Device Configuration via RESTCONF
Workflow: Updating interface configuration with error handling and rollback
Demonstrates error handling in API calls - what happens when configuration fails and how to handle rollback scenarios.
Step-by-Step Interpretation
SUCCESSFUL CONFIGURATION (Steps 1-8): Step 1-4: Script reads current interface configuration → GET interface Gi1 current state → Device OS retrieves config → Returns interface is disabled (enabled: false) Step 5-8: Script updates interface configuration → PATCH to enable interface and add description → Device OS applies the changes → Returns 204 No Content (successful, no body needed) ERROR SCENARIO (Steps 9-13): Step 9-12: Script attempts to configure non-existent interface → PATCH interface Gi99 (which doesn't exist) → Device OS checks interface existence → Interface not found in configuration → Returns 404 Not Found with error message Step 13: Script handles error gracefully → Logs the error for troubleshooting → Continues with next operation (doesn't crash) KEY INSIGHTS: ✅ Always GET before PATCH to verify resource exists ✅ Handle HTTP error codes (404, 400, 500) ✅ Implement try/except in scripts ✅ Log errors for debugging
5. Reading Sequence Diagrams - Quick Reference
📚 Sequence Diagram Symbols and Notation
Reference Guide: Understanding all sequence diagram elements
| Symbol/Notation | Meaning | Example |
|---|---|---|
| participant | Actor/system in diagram | participant S as Script |
| ->> | Synchronous call (solid line) | A->>B: Request |
| -->> | Response (dashed line) | B-->>A: Response |
| ->>+ | Call activates participant | A->>+B: Start |
| -->>- | Response deactivates | B-->>-A: End |
| Note over A,B | Add notes/comments | Note over: Phase 1 |
| alt/else/end | Conditional logic | alt success / else fail |
| loop/end | Repeated operations | loop Every 5 seconds |
Common API Patterns in Sequence Diagrams
| Pattern | Description | APIs |
|---|---|---|
| Authentication | Login → Get token → Use token | DNA Center, ACI, Custom APIs |
| CRUD Operations | GET → POST → PUT → DELETE | REST APIs, RESTCONF |
| Async Processing | POST → Get task ID → Poll status | DNA Center, NSO |
| Error Handling | Request → Error response → Retry/Log | All APIs |
| Multi-tier | Client → API → Controller → Device | Meraki, DNA Center |
🐍 Interactive Python Interpreter
- Write Python code in the editor
- Click "▶ Run Code" to execute
- Try sample code buttons