Skip to content

Commit dfcff87

Browse files
authored
Merge branch 'master' into visualizing-python-plt-scatter
2 parents cde22af + 7b9fa03 commit dfcff87

30 files changed

Lines changed: 730 additions & 5 deletions

claude-api-python/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# How to Use the Claude API in Python
2+
3+
This folder contains supporting materials for the Real Python tutorial [How to Use the Claude API in Python](https://realpython.com/claude-api-python/).
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import anthropic
2+
3+
client = anthropic.Anthropic()
4+
5+
response = client.messages.create(
6+
model="claude-sonnet-4-6",
7+
max_tokens=1024,
8+
messages=[{"role": "user", "content": "What is the Zen of Python?"}],
9+
)
10+
11+
print(response.content[0].text)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import anthropic
2+
3+
client = anthropic.Anthropic()
4+
5+
system_prompt = """
6+
You are a Python coding assistant. You only answer questions about Python.
7+
If the user asks about any other programming language or unrelated topic,
8+
politely explain that you can only help with Python questions.
9+
"""
10+
11+
user_input = input("Ask me anything about Python: ")
12+
13+
response = client.messages.create(
14+
model="claude-sonnet-4-6",
15+
max_tokens=1024,
16+
system=system_prompt,
17+
messages=[{"role": "user", "content": user_input}],
18+
)
19+
20+
print(f"\n{response.content[0].text}")

claude-api-python/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
anthropic
2+
pydantic
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import anthropic
2+
import json
3+
4+
client = anthropic.Anthropic()
5+
6+
response = client.messages.create(
7+
model="claude-sonnet-4-6",
8+
max_tokens=1024,
9+
system="You are a Python coding assistant.",
10+
messages=[
11+
{
12+
"role": "user",
13+
"content": "Write a Python function that adds two numbers.",
14+
}
15+
],
16+
output_config={
17+
"format": {
18+
"type": "json_schema",
19+
"schema": {
20+
"type": "object",
21+
"properties": {
22+
"function_name": {"type": "string"},
23+
"code": {"type": "string"},
24+
"explanation": {"type": "string"},
25+
},
26+
"required": ["function_name", "code", "explanation"],
27+
"additionalProperties": False,
28+
},
29+
}
30+
},
31+
)
32+
33+
result = json.loads(response.content[0].text)
34+
35+
print("--- Approach 1: Handwritten JSON schema ---")
36+
print(f"Function: {result['function_name']}")
37+
print(f"\nCode:\n{result['code']}")
38+
print(f"\nExplanation: {result['explanation']}")
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import anthropic
2+
3+
from pydantic import BaseModel
4+
5+
6+
class FunctionDescription(BaseModel):
7+
function_name: str
8+
code: str
9+
explanation: str
10+
11+
12+
client = anthropic.Anthropic()
13+
14+
response = client.messages.parse(
15+
model="claude-sonnet-4-6",
16+
max_tokens=1024,
17+
system="You are a Python coding assistant.",
18+
messages=[
19+
{
20+
"role": "user",
21+
"content": "Write a Python function that adds two numbers.",
22+
}
23+
],
24+
output_format=FunctionDescription,
25+
)
26+
27+
result = response.parsed_output
28+
29+
print("--- Approach 2: Pydantic + client.messages.parse() ---")
30+
print(f"Function: {result.function_name}")
31+
print(f"\nCode:\n{result.code}")
32+
print(f"\nExplanation: {result.explanation}")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Cursor vs Windsurf: Which AI Code Editor Is Best for Python?
2+
3+
This folder provides the prompts and Cursor/Windsurf rules files used in the Real Python tutorial [Cursor vs Windsurf: Which AI Code Editor Is Best for Python?](https://realpython.com/cursor-vs-windsurf-python/)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
globs: "**/*.py"
3+
alwaysApply: false
4+
---
5+
# Instructions
6+
- Use type hints for all functions, return values, and dataclass fields
7+
- Use `httpx.AsyncClient` for HTTP requests; do not use `requests`
8+
or `aiohttp`
9+
- Use `await asyncio.sleep()` for delays; do not use `time.sleep()`
10+
- Return dataclasses for HTTP responses, not raw dictionaries
11+
- Follow PEP 8 style conventions
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Prompts
2+
3+
Copy-paste these into Cursor and Windsurf in order while following the tutorial.
4+
5+
## 1. Set up the project
6+
7+
```
8+
Set up a Python project in this directory following standard Python
9+
packaging conventions:
10+
- Create a virtual environment
11+
- Install httpx==0.28.1 and pytest==9.0.2
12+
- Add a tests/ directory
13+
- Use the directory name as the package name
14+
- Only include the dependencies explicitly listed here
15+
```
16+
17+
## 2. Write the async fetch function
18+
19+
```
20+
Create a file called `fetcher.py` and write an async function
21+
called fetch_json that:
22+
- Takes a URL string and an optional integer max_retries (default 3)
23+
- Uses httpx.AsyncClient to fetch JSON from the URL
24+
- Retries up to max_retries times with exponential backoff (1s, 2s, 4s)
25+
on any httpx.HTTPError
26+
- Returns the JSON response as a typed dataclass called FetchResult
27+
with fields: url (str), status_code (int), and data (dict[str, Any])
28+
- Uses proper type hints throughout
29+
```
30+
31+
## 3. Generate tests
32+
33+
Before sending this prompt, open `fetcher.py` and replace
34+
`await asyncio.sleep(delay)` with `time.sleep(delay)`, then add
35+
`import time` at the top. Save the file.
36+
37+
```
38+
Create tests/test_fetcher.py with pytest tests for fetch_json that:
39+
- Test successful fetch returns correct FetchResult
40+
- Test fetch retries twice then succeeds
41+
- Test fetch raises after exhausting retries
42+
- Test two concurrent fetches complete in <4s
43+
(one with 1s+2s retry delays, one instant)
44+
- Test fetch can be cancelled during retry delay
45+
Use httpx.MockTransport for mocking.
46+
```
47+
48+
## 4. Plan-mode prompt
49+
50+
Switch each editor to its Plan mode before sending:
51+
52+
```
53+
Add a retry_budget parameter to fetch_json that limits the total
54+
cumulative wait time across all retries.
55+
```
56+
57+
## 5. Autocomplete starter snippet
58+
59+
Type this into a file and let each editor complete it:
60+
61+
```python
62+
@dataclass
63+
class RetryMetadata:
64+
attempts_made: int
65+
# ...
66+
```
67+
68+
## 6. Manual review (Windsurf Ask mode)
69+
70+
```
71+
Review fetcher.py for bugs and lint issues and summarize what you find.
72+
```
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
trigger: glob
3+
globs: "**/*.py"
4+
---
5+
# Instructions
6+
- Use type hints for all functions, return values, and dataclass fields
7+
- Use `httpx.AsyncClient` for HTTP requests; do not use `requests` or `aiohttp`
8+
- Use `await asyncio.sleep()` for delays; do not use `time.sleep()`
9+
- Return dataclasses for HTTP responses, not raw dictionaries
10+
- Follow PEP 8 style conventions

0 commit comments

Comments
 (0)