Skip to content

Commit

Permalink
fix parsing of unit strings with 2 letters (fixes #300) (#301)
Browse files Browse the repository at this point in the history
  • Loading branch information
jameslamb authored Feb 9, 2025
1 parent 127264d commit e8c87ba
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 5 deletions.
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/isort
rev: 5.13.2
rev: 6.0.0
hooks:
- id: isort
name: isort (python)
args: ["--settings-path", "pyproject.toml"]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.1
rev: v1.15.0
hooks:
- id: mypy
args: ["--config-file", "pyproject.toml"]
Expand All @@ -27,7 +27,7 @@ repos:
- types-requests
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.9.3
rev: v0.9.5
hooks:
# Run the linter.
- id: ruff
Expand Down Expand Up @@ -61,7 +61,7 @@ repos:
- id: yamllint
additional_dependencies: [pyyaml]
- repo: https://github.com/codespell-project/codespell
rev: v2.4.0
rev: v2.4.1
hooks:
- id: codespell
additional_dependencies: [tomli]
Expand Down
6 changes: 5 additions & 1 deletion src/pydistcheck/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
not specific to package distributions
"""

import re
from typing import Tuple

# references:
Expand Down Expand Up @@ -47,7 +48,10 @@ def from_number(cls, num: int) -> "_FileSize":

@classmethod
def from_string(cls, size_str: str) -> "_FileSize":
return cls(num=float(size_str[:-1]), unit_str=size_str[-1])
parsed = re.search(r"^([0-9\.]+)([A-Za-z]+)$", size_str.strip())
if parsed is None:
raise ValueError(f"Could not parse '{size_str}' as a file size.")
return cls(num=float(parsed.group(1)), unit_str=parsed.group(2))

@property
def total_size_bytes(self) -> int:
Expand Down
35 changes: 35 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ def test_check_respects_max_allowed_files(distro_file):
[
"1K",
"3.999K",
"0.005KB",
"0.0002M",
"0.00000008G",
"708B",
Expand Down Expand Up @@ -453,11 +454,45 @@ def test_check_respects_max_allowed_size_compressed(size_str, distro_file):
_assert_log_matches_pattern(result, "errors found while checking\\: 1")


@pytest.mark.parametrize(
"size_str",
[
"1",
"K",
"1-KB",
"GB1",
"1G-B",
],
)
@pytest.mark.parametrize(
"cli_arg",
[
"--max-allowed-size-compressed",
"--max-allowed-size-uncompressed",
],
)
def test_check_raises_informative_error_for_malformed_file_size_config(
cli_arg, size_str
):
with pytest.raises(
ValueError, match=rf"Could not parse '{size_str}' as a file size"
):
CliRunner().invoke(
check,
[
os.path.join(TEST_DATA_DIR, BASE_PACKAGES[0]),
f"{cli_arg}={size_str}",
],
catch_exceptions=False,
)


@pytest.mark.parametrize(
"size_str",
[
"1K",
"3.999K",
"0.005KB",
"0.0002M",
"0.00000008G",
"708B",
Expand Down
23 changes: 23 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,29 @@ def test_file_size_from_different_inputs_all_parsed_consistently(file_size):
assert file_size == _FileSize(num=3.0, unit_str="M")


def test_file_size_from_string_works():
# 1 letter
assert _FileSize.from_string("57B").total_size_bytes == 57
assert _FileSize.from_string("57K").total_size_bytes == 57 * 1024
assert _FileSize.from_string("57M").total_size_bytes == 57 * 1024**2
assert _FileSize.from_string("57G").total_size_bytes == 57 * 1024**3

# 2 letter
assert _FileSize.from_string("57KB").total_size_bytes == 57 * 1e3
assert _FileSize.from_string("57MB").total_size_bytes == 57 * 1e6
assert _FileSize.from_string("57GB").total_size_bytes == 57 * 1e9

# decimals
assert _FileSize.from_string("0.005GB").total_size_bytes == 0.005 * 1e9
assert _FileSize.from_string("0.05GB").total_size_bytes == 0.05 * 1e9
assert _FileSize.from_string("0.5GB").total_size_bytes == 0.5 * 1e9
assert _FileSize.from_string("5.0GB").total_size_bytes == 5 * 1e9
assert _FileSize.from_string("5.000GB").total_size_bytes == 5 * 1e9
assert _FileSize.from_string("5.1GB").total_size_bytes == 5.1 * 1e9
assert _FileSize.from_string("5.17GB").total_size_bytes == 5.17 * 1e9
assert _FileSize.from_string("5.234GB").total_size_bytes == 5.234 * 1e9


def test_file_size_from_number_switches_unit_str_based_on_size():
assert _FileSize.from_number(1.1) == _FileSize(num=1.1, unit_str="B")
# fractional bytes don't make sense here, so some rounding happens
Expand Down

0 comments on commit e8c87ba

Please sign in to comment.