Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,6 @@ dist
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

#pycache__/
__pycache__/
*.pyc
4 changes: 2 additions & 2 deletions .hyf/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ task1_msg="missing src/cleaner.py or src/utils.py"
if [ -f task-1/src/cleaner.py ] && [ -f task-1/src/utils.py ]; then
task1=10
task1_msg="files exist but cleaner failed to run"
if ( cd task-1 && python3 src/cleaner.py --input data/messy_users.csv --output output/clean_users.json ) >/dev/null 2>&1; then
if ( cd task-1 && python src/cleaner.py --input data/messy_users.csv --output output/clean_users.json ) >/dev/null 2>&1; then
task1=20
task1_msg="cleaner ran but output failed structural checks"
if python3 - <<'PY' 2>/dev/null
if python - <<'PY' 2>/dev/null
import json
from pathlib import Path

Expand Down
86 changes: 86 additions & 0 deletions task-1/output/clean_users.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
[
{
"id": 1,
"name": "Alice Johnson",
"email": "alice.johnson@company.com",
"department": "Engineering",
"salary": 85000
},
{
"id": 2,
"name": "Bob Smith",
"email": "bob.smith@company.com",
"department": "Unknown",
"salary": 72000
},
{
"id": 3,
"name": "Carol Williams",
"email": "carol.williams@company.com",
"department": "Engineering",
"salary": null
},
{
"id": 4,
"name": "David, Jr.",
"email": "david.brown@company.com",
"department": "Sales",
"salary": 68000
},
{
"id": 5,
"name": "Caf\u00e9 Owner",
"email": "eva@company.com",
"department": "Engineering",
"salary": 88000
},
{
"id": 6,
"name": "FRANK WILSON",
"email": "frank@company.com",
"department": "marketing",
"salary": 95000
},
{
"id": 7,
"name": "Grace Lee",
"email": "grace.lee@company.com",
"department": "Engineering",
"salary": null
},
{
"id": 9,
"name": "Henry Davis",
"email": "henry.davis@company.com",
"department": "Sales",
"salary": 82000
},
{
"id": 11,
"name": "Linda Taylor",
"email": "linda.t@company.com",
"department": "HR",
"salary": 55000
},
{
"id": 12,
"name": "Mike Brown",
"email": "mike.b@company.com",
"department": "Sales",
"salary": null
},
{
"id": 13,
"name": "Sarah Connor",
"email": "s.connor@sky.net",
"department": "Unknown",
"salary": null
},
{
"id": 15,
"name": "John Doe",
"email": "john.doe@company.net",
"department": "Engineering",
"salary": 100000
}
]
22 changes: 18 additions & 4 deletions task-1/src/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,29 @@ def clean_name(raw: str) -> str:

Returns the cleaned string. An empty input returns "".
"""
raise NotImplementedError("Implement clean_name (Task 1)")
if not raw.strip():
return ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raw.strip() already returns "" when the string is empty or only whitespace, so the explicit if not raw.strip() check is redundant.

return raw.strip() would have been enough :)

return raw.strip()


def clean_email(raw: str) -> str:
"""Lowercase the email, strip surrounding whitespace.

Returns the cleaned string. An empty input returns "".
"""
raise NotImplementedError("Implement clean_email (Task 1)")
if not raw.strip():
return ""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

return raw.strip().lower()


def clean_department(raw: str) -> str:
"""Return the department, or 'Unknown' if missing/empty.

Strip whitespace; treat empty string as missing.
"""
raise NotImplementedError("Implement clean_department (Task 1)")
if not raw.strip():
return "Unknown"
return raw.strip()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: not wrong, but a more efficient version without calling strip twice could have been:

    department =raw.strip()
    if not department:
        return "Unknown"
    return department



def clean_salary(raw: str) -> int | None:
Expand All @@ -38,4 +44,12 @@ def clean_salary(raw: str) -> int | None:
Handles inputs like "85000", " 95000", '"68,000"', "N/A", "".
Returns None when the value cannot be parsed (missing or "N/A").
"""
raise NotImplementedError("Implement clean_salary (Task 1)")
if not raw.strip() or raw.strip().lower() == "n/a":
return None

# Ensure this line is aligned with the 'if' above it
cleaned = raw.strip().replace(",", "").replace('"', "")

# Ensure this block is aligned correctly
if cleaned.isdigit():

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens here if you had a value like "85000 "?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isdigit is too strict, and it won't handle properly numerical values like "85000 " or "85k" or "+8500"

return int(cleaned)
81 changes: 72 additions & 9 deletions task-2/AI_DEBUG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,84 @@ Document one debugging session you had during Task 1 where you used an LLM

## The Error

<!-- Paste the full traceback or describe the wrong behaviour. Include the
exact error message and the line of your code that triggered it. -->
python src/cleaner.py --input data/messy_users.csv --output output/clean_users.json
Traceback (most recent call last):
File "C:\Users\Bader\Desktop\d1\c55-data-week1\task-1\src\cleaner.py", line 17, in <module>
from utils import clean_department, clean_email, clean_name, clean_salary
File "C:\Users\Bader\Desktop\d1\c55-data-week1\task-1\src\utils.py", line 56
cleaned = raw.strip().replace(",", "").replace('"', "")
^
IndentationError: unindent does not match any outer indentation level

## The Prompt

<!-- The exact text you sent to the LLM. Include the code you pasted with
it. -->
if not raw.strip() or raw.strip().lower() == "n/a":

return None

cleaned = raw.strip().replace(",", "").replace('"', "")

if cleaned.isdigit():

return int(cleaned)

File "C:\Users\Bader\Desktop\d1\c55-data-week1\task-1\src\cleaner.py", line 17, in <module>

from utils import clean_department, clean_email, clean_name, clean_salary

File "C:\Users\Bader\Desktop\d1\c55-data-week1\task-1\src\utils.py", line 56

cleaned = raw.strip().replace(",", "").replace('"', "")

^

IndentationError: unindent does not match any outer indentation level

## The Solution

<!-- What did the LLM suggest? Did it work on the first try, or did you
need a follow-up? -->
It looks like you've hit one of the most common (and admittedly frustrating) rites of passage in Python: the IndentationError.

In Python, whitespace isn't just for readability; it's part of the syntax. This specific error means your code's spacing is inconsistent—likely a mix of tabs and spaces, or a line that shifted slightly out of alignment with the rest of its block.
The Fix

Looking at your snippet, the lines following the if statement need to be consistently indented. Here is the corrected structure:
Python

def clean_salary(raw):
if not raw.strip() or raw.strip().lower() == "n/a":
return None

# Ensure this line is aligned with the 'if' above it
cleaned = raw.strip().replace(",", "").replace('"', "")

# Ensure this block is aligned correctly
if cleaned.isdigit():
return int(cleaned)

Common Culprits

Tabs vs. Spaces: This is the #1 cause. If line 1 uses four spaces and line 2 uses one tab, Python will throw this error even if they look aligned on your screen.

Pro Tip: Set your editor (VS Code, PyCharm, etc.) to "Indent using Spaces" and "Render Whitespace" so you can see the invisible dots or arrows.

The "Ghost" Space: Sometimes a single accidental space creeps in at the start of a line.

Copy-Paste Issues: If you copied this logic from a website or another file, the indentation depth might have changed relative to the function it was pasted into.

How to Resolve This Quickly

If you are using VS Code:

Select all the text in utils.py.

Open the Command Palette (Ctrl+Shift+P).

Type "Convert Indentation to Spaces" and hit Enter.

Manually re-align the lines to ensure they sit at the same level.

Your logic itself—stripping commas and quotes to turn a string into an integer—is solid! Just give those margins a quick polish and you should be good to go.

## Reflection

<!-- A few sentences on: did you understand WHY the original code was
broken, or did you just accept the fix? What would you do differently next
time? -->
i did understand how indentation work (kind of! still alittle bit confusing) and it lead me to think of prettier for javascript and an alternative for python which lead me to "black / ruff" which i decided to install ruff [made my life much easier] and ask about both next lesson :D
Binary file added task-3/Screenshot 2026-05-06 214415.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.