diff --git a/scripts/generate_site.py b/scripts/generate_site.py index f21d5ebe2..e996cb6b0 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -6022,7 +6022,9 @@ def _system_file_card( name = f["name"] sha1_full = f.get("sha1", "unknown") md5_full = f.get("md5", "unknown") - size = _fmt_size(f.get("size", 0)) + # The size a card names is the file's own, exact: rounded, 44,348,015 + # and 44,356,548 bytes were one 42.3 MB. + size = _card_size(int(f.get("size", 0))) # Who reads this file, not who reads a file of this name plats = sorted(consumers.platforms.get(sha1_full, ())) emus = sorted(consumers.emulators.get(sha1_full, ())) @@ -8051,6 +8053,26 @@ def emulator_setups(coverages: dict, profiles: dict) -> dict[str, list[str]]: } +def _validation_names(validation: object) -> set[str]: + """The checks a `validation:` names, a list or one list per build.""" + if isinstance(validation, dict): + return {str(v) for checks in validation.values() for v in checks or []} + return {str(v) for v in validation or []} + + +def _card_size(size: int) -> str: + """A file's size, exact: in whole MB or KB when it is one, else in B.""" + for unit, scale in (("MB", 1024 * 1024), ("KB", 1024)): + if size >= scale and size % scale == 0: + return f"{size // scale:,} {unit}" + return f"{size:,} B" + + +def _exact_size(size: int) -> str: + """A rounded size with its bytes, where the bytes are not the same figure.""" + return _fmt_size(size) if size < 1024 else f"{_fmt_size(size)} ({size:,} bytes)" + + def _build_rows(profile: dict) -> list[str]: """Meta card rows for who ships the build, how its files are found, why its revision is held and where its releases are announced.""" @@ -8184,25 +8206,28 @@ def _render_emulator_file( details.append(f"Found by: {found}") if fsystem: details.append(f"System: {_named_system_link(fsystem, '../')}") + # Where the code compares the size, the exact bytes: raze tells three + # DUKE3D.GRP apart by size, all three shown as 42.3 MB. + sized = _exact_size if "size" in _validation_names(validation) else _fmt_size if size: if isinstance(size, list): - size_str = " / ".join(_fmt_size(s) for s in size) + size_str = " / ".join(sized(s) for s in size) else: - size_str = _fmt_size(size) + size_str = sized(size) if fmin or fmax: bounds = [] if fmin: - bounds.append(f"min {_fmt_size(fmin)}") + bounds.append(f"min {sized(fmin)}") if fmax: - bounds.append(f"max {_fmt_size(fmax)}") + bounds.append(f"max {sized(fmax)}") size_str += f" ({', '.join(bounds)})" details.append(f"Size: {size_str}") elif fmin or fmax: bounds = [] if fmin: - bounds.append(f"min {_fmt_size(fmin)}") + bounds.append(f"min {sized(fmin)}") if fmax: - bounds.append(f"max {_fmt_size(fmax)}") + bounds.append(f"max {sized(fmax)}") details.append(f"Size: {', '.join(bounds)}") # Starlight folds the hashes and gives each a copy button. copyable = markup.starlight() diff --git a/tests/test_site_density_cards.py b/tests/test_site_density_cards.py index 56ddd41c7..9c031adec 100644 --- a/tests/test_site_density_cards.py +++ b/tests/test_site_density_cards.py @@ -110,7 +110,7 @@ class ASystemCardShowsTheAnswerFirst(unittest.TestCase): self.shown = self.text.replace(self.fold, "") def test_the_open_part(self) -> None: - for fact in ("ppge_atlas.zim", ">650.9 KB<", ">Download", + for fact in ("ppge_atlas.zim", ">666,539 B<", ">Download", "
On the setup's list
", "
Packed for its emulators by
", "
Emulators
", f'
SHA1
{SHA1[:12]}
'): self.assertIn(fact, self.shown) diff --git a/tests/test_site_emulators.py b/tests/test_site_emulators.py index f15c91374..03f59f620 100644 --- a/tests/test_site_emulators.py +++ b/tests/test_site_emulators.py @@ -789,6 +789,22 @@ class AnEmulatorPageNamesItsSetups(unittest.TestCase): self.assertIn("EmuDeck", card[1].splitlines()[0]) +class SizesTheCodeComparesAreExact(unittest.TestCase): + """raze validates DUKE3D.GRP by size, and its page showed 42.3 MB for + 44,356,548 and 44,348,015 bytes alike.""" + + def test_a_validated_size_carries_its_bytes(self): + profile = {"emulator": "x", "type": "libretro", "systems": ["sony-playstation"], "files": [ + {"name": "DUKE3D.GRP", "size": 44348015, "validation": ["size", "crc32"]}, + {"name": "other.bin", "size": 44356548}, + {"name": "built.bin", "size": 2304, "validation": {"core": ["size"]}}, + ]} + page = _page("x", profile) + self.assertIn("Size: 42.3 MB (44,348,015 bytes)", page) + self.assertIn("Size: 2.2 KB (2,304 bytes)", page) + self.assertNotIn("44,356,548", page) + + class ADataDirectoryNamesAFetchableOrigin(unittest.TestCase): """pcee2's page linked github.com/PCSX2/pcsx2/archive/{version}.tar.gz, a 404, and buildbot zips showed `Revision: master (2047720058)`: a branch diff --git a/tests/test_site_systems.py b/tests/test_site_systems.py index 784c17092..9f8891799 100644 --- a/tests/test_site_systems.py +++ b/tests/test_site_systems.py @@ -184,6 +184,19 @@ class ThePermalinkIsAnIcon(unittest.TestCase): self.assertEqual(page.count('href="#rb-link-icon"'), 2) +class TheCardGivesTheSizeInBytes(unittest.TestCase): + """The badge rounded to 0.1 KB and no line of a system card gave the + bytes an emulator compares.""" + + def test_the_badge_is_exact(self): + for size, shown in ((524288, "512 KB"), (44348015, "44,348,015 B"), + (2 * 1024 * 1024, "2 MB"), (2304, "2,304 B"), (10, "10 B")): + with self.subTest(size=size): + card = {**_sony_file("scph5501.bin", "4"), "size": size} + title = gs._system_file_card(card, FileConsumers({"files": {}}))[2] + self.assertIn(f'{shown}', title) + + class TheCardLinesSayWhatTheyMean(unittest.TestCase): """"Platforms:" and "Also installed by:" listed different setups, as lower-case ids, and only a code comment told them apart."""