Project
Function
Sample CLI
gway clock to-download
Full Code
def to_download(filesize):
"""
Prompt: Create a python function that takes a file size such as 100 MB or 1.76 GB
(pick a wide array of units) and then calculates the possible time to download
it within 4 ranges. You choose the ranges logarithmically. Then, perform a quick
check against google to let the user know what their current range is.
"""
# 1. Size parsing
def parse_size(size_str):
"""
Parse a size string like '1.76 GB', '500kb', '1024 B', '3.2 GiB'
into a number of bytes (float).
Accepts decimal (k=1e3) or binary (Ki=2**10) prefixes.
"""
size_str = size_str.strip()
# Handle plain bytes (e.g. '123 B')
plain_b_match = re.match(r"^([\d\.]+)\s*(bytes?|b)$", size_str, re.IGNORECASE)
if plain_b_match:
return float(plain_b_match.group(1))
# Handle KB/MB/etc
pattern = r"^([\d\.]+)\s*([kKmMgGtTpP])([iI])?[bB]?$"
m = re.match(pattern, size_str)
if not m:
raise ValueError(f"Unrecognized size format: {size_str!r}")
num, prefix, binary = m.group(1, 2, 3)
num = float(num)
exp = {"k": 1, "m": 2, "g": 3, "t": 4, "p": 5}[prefix.lower()]
if binary:
factor = 2 ** (10 * exp)
else:
factor = 10 ** (3 * exp)
return num * factor
# 2. Human-friendly duration
def format_duration(seconds):
if seconds < 1:
return f"{seconds*1000:.1f} ms"
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
parts = []
if h: parts.append(f"{int(h)} h")
if m: parts.append(f"{int(m)} m")
if s or not parts: parts.append(f"{s:.1f} s")
return " ".join(parts)
# 3. Estimate times at four speeds
SPEED_BRACKETS = [
(1e3, "1 kB/s (≈8 kbps)"),
(1e5, "100 kB/s (≈0.8 Mbps)"),
(1e7, "10 MB/s (≈80 Mbps)"),
(1e9, "1 GB/s (≈8 Gbps)"),
]
def estimate_download_times(size_str):
size_bytes = parse_size(size_str)
return [(label, format_duration(size_bytes / speed))
for speed, label in SPEED_BRACKETS]
# 4. Quick live check against Google
def measure_current_speed(test_url=None):
if test_url is None:
test_url = ("https://www.google.com/images/branding/"
"googlelogo/2x/googlelogo_color_272x92dp.png")
start = time.time()
r = requests.get(test_url, stream=True, timeout=10)
total = 0
for chunk in r.iter_content(1024):
total += len(chunk)
elapsed = time.time() - start
return total / elapsed # bytes per second
def classify_speed(bps):
for i, (speed, label) in enumerate(SPEED_BRACKETS):
# slower than midpoint to next bracket → this bracket
if i == len(SPEED_BRACKETS)-1 or \
bps < speed * ((SPEED_BRACKETS[i+1][0]/speed)**0.5):
return label
return SPEED_BRACKETS[-1][1]
# 5. Putting it all together
def download_time_report(size_str):
print(f"Estimating download times for {size_str!r}:\n")
for label, t in estimate_download_times(size_str):
print(f" • At {label}: {t}")
try:
print("\nMeasuring your current download speed…")
speed = measure_current_speed()
# human = time to download 1 B
human = format_duration(parse_size('1 B') / speed)
print(f" → Detected ≈{speed/1024:.1f}\u00A0kB/s ({human})")
bracket = classify_speed(speed)
print(f" You’re in the **{bracket}** range.")
except Exception as e:
print(f" (Could not measure live speed: {e})")
raise
download_time_report(filesize)