UserItem.CSVImport has some internal design smells worth cleaning up.
1. Use the csv module for parsing. Today the code does line.split(","), which misaligns whenever a field contains a comma - a password like "my,pa\$\$w0rd", a display name like "Smith, John". The column-1 mask added in #1829 only covers what lands in column 1; bytes that spill into column 2+ still leak (see test_password_with_comma_partially_masks). csv.reader also handles quoted values, CRLF, and BOM deliberately rather than coincidentally.
2. Consolidate two username extractions. validate_file_for_import uses line.partition(",")[0].strip(), while _validate_import_line_or_throw uses list(map(str.strip, line.split(",")))[USERNAME]. Same result today, but a maintenance hazard. A csv.reader migration collapses both.
3. Align error handling in create_user_from_line. It returns None for empty input but raises ValueError for too many columns. Pick one convention.
🤖 Generated with Claude Code
UserItem.CSVImporthas some internal design smells worth cleaning up.1. Use the
csvmodule for parsing. Today the code doesline.split(","), which misaligns whenever a field contains a comma - a password like"my,pa\$\$w0rd", a display name like"Smith, John". The column-1 mask added in #1829 only covers what lands in column 1; bytes that spill into column 2+ still leak (seetest_password_with_comma_partially_masks).csv.readeralso handles quoted values, CRLF, and BOM deliberately rather than coincidentally.2. Consolidate two username extractions.
validate_file_for_importusesline.partition(",")[0].strip(), while_validate_import_line_or_throwuseslist(map(str.strip, line.split(",")))[USERNAME]. Same result today, but a maintenance hazard. Acsv.readermigration collapses both.3. Align error handling in
create_user_from_line. It returnsNonefor empty input but raisesValueErrorfor too many columns. Pick one convention.🤖 Generated with Claude Code