Skip to content
Open
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
24 changes: 24 additions & 0 deletions analytics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
def parse_csv_line(line, delimiter=','):
parts = line.strip().split(delimiter)
Comment on lines +1 to +2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: Splitting on the raw delimiter without respecting quoted fields breaks on any CSV where a field value contains the delimiter — e.g. 'a,"b,c",d' splits into four parts instead of three, and the quote-stripping on line 3 doesn't recover because the split already happened.

Use csv.reader from the stdlib — it handles quoted fields, embedded delimiters, and escaped quotes correctly.

Suggested change
def parse_csv_line(line, delimiter=','):
parts = line.strip().split(delimiter)
import csv
import io
def parse_csv_line(line, delimiter=','):
reader = csv.reader(io.StringIO(line), delimiter=delimiter)
return next(reader)
  • Mark as noise

return [p.strip().strip('"') for p in parts]


def compute_moving_average(values, window):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing test coverage: compute_moving_average has the most complex business logic in this file — boundary validation, index arithmetic, and floating-point averaging. No tests cover:

  • Window equal to len(values) (should return a single average)
  • Window of 1 (should return the input unchanged)
  • An empty values list
  • Correct sliding behaviour (an off-by-one in range(len(values) - window + 1) would be invisible without a test)

A parametrized unit test over these cases would catch regressions here.

  • Mark as noise

if window <= 0 or window > len(values):
raise ValueError("window must be between 1 and len(values)")
result = []
for i in range(len(values) - window + 1):
result.append(sum(values[i:i + window]) / window)
return result


def group_by(items, key_fn):
groups = {}
for item in items:
k = key_fn(item)
groups.setdefault(k, []).append(item)
return groups


def clamp(value, minimum, maximum):
return max(minimum, min(maximum, value))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: When minimum > maximum the function silently returns minimum regardless of value — e.g. clamp(5, 10, 0) returns 10. An inverted range is almost certainly a caller mistake and should raise ValueError rather than silently producing a wrong result.

Suggested change
return max(minimum, min(maximum, value))
def clamp(value, minimum, maximum):
if minimum > maximum:
raise ValueError("minimum must be <= maximum")
return max(minimum, min(maximum, value))
  • Mark as noise

Loading