1
0
mirror of synced 2025-02-22 05:09:39 +01:00

Fix crash of guess_format on valid empty jbsq file

This commit is contained in:
Stepland 2022-09-21 13:14:27 +02:00
parent ba6599a645
commit 571c596e3f
7 changed files with 68 additions and 27 deletions

View File

@ -5,8 +5,12 @@ each version
Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
I try to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
sometimes.
I try to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## v2.0.1
### Fixed
- `guess_format()` would raise an exception when called on a specially crafted
empty jbsq file, not anymore !
## v2.0.0
### BREAKING CHANGE

View File

@ -1,6 +1,8 @@
import json
import re
from functools import wraps
from pathlib import Path
from typing import Any, Callable, Type
from .format_names import Format
@ -108,17 +110,29 @@ def recognize_jubeat_analyser_format(path: Path) -> Format:
raise ValueError("Unrecognized file format")
def false_if_raises(
*exceptions: Type[Exception],
) -> Callable[[Callable[..., bool]], Callable[..., bool]]:
def decorator(f: Callable[..., bool]) -> Callable[..., bool]:
@wraps(f)
def wrapper(*a: Any, **kw: Any) -> bool:
try:
return f(*a, **kw)
except Exception as e:
if exceptions and not isinstance(e, exceptions):
raise
else:
return False
return wrapper
return decorator
@false_if_raises(UnicodeDecodeError, StopIteration)
def looks_like_eve(path: Path) -> bool:
with path.open(encoding="ascii") as f:
try:
line = f.readline()
except UnicodeDecodeError:
return False
if line.strip():
return looks_like_eve_line(next(f))
return False
return looks_like_eve_line(f.readline())
EVE_COMMANDS = {
@ -154,5 +168,6 @@ def looks_like_eve_line(line: str) -> bool:
def looks_like_jbsq(path: Path) -> bool:
magic = path.open(mode="rb").read(4)
return magic in (b"IJBQ", b"IJSQ", b"JBSQ")
with path.open(mode="rb") as f:
magic = f.read(4)
return magic in (b"IJBQ", b"IJSQ", b"JBSQ")

View File

@ -0,0 +1,23 @@
from decimal import Decimal
from fractions import Fraction
from jubeatools.song import *
data = Song(
metadata=Metadata(
title=None, artist=None, audio=None, cover=None, preview=None, preview_file=None
),
charts={
"BSC": Chart(
level=Decimal("0"),
timing=Timing(
events=(BPMEvent(time=Fraction(0, 1), BPM=Decimal("288.11")),),
beat_zero_offset=Decimal("0.04"),
),
hakus=set(),
notes=[],
)
},
common_timing=None,
common_hakus=None,
)

View File

@ -1,13 +1,14 @@
from enum import Enum
from hypothesis import given
from hypothesis import example, given
from jubeatools import song
from jubeatools.formats import Format
from jubeatools.formats.konami.testutils import eve_compatible_song
from jubeatools.testutils.test_patterns import dump_and_load, dump_and_load_then_compare
from .construct import jbsq
from ..construct import jbsq
from . import example1
@given(eve_compatible_song())
@ -21,6 +22,7 @@ def test_that_full_chart_roundtrips(song: song.Song) -> None:
@given(eve_compatible_song())
@example(example1.data)
def test_that_difficulty_name_is_loaded_properly(original_song: song.Song) -> None:
recovered_song = dump_and_load(
Format.JBSQ,

21
poetry.lock generated
View File

@ -22,7 +22,7 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>
[[package]]
name = "autoflake"
version = "1.5.3"
version = "1.6.0"
description = "Removes unused imports and unused variables"
category = "dev"
optional = false
@ -30,11 +30,11 @@ python-versions = ">=3.7"
[package.dependencies]
pyflakes = ">=1.1.0"
toml = ">=0.10.2"
tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
[[package]]
name = "autoimport"
version = "1.2.2"
version = "1.2.3"
description = "Autoimport missing python libraries."
category = "dev"
optional = false
@ -137,7 +137,7 @@ pyflakes = ">=2.3.0,<2.4.0"
[[package]]
name = "hypothesis"
version = "6.54.5"
version = "6.54.6"
description = "A library for property-based testing"
category = "dev"
optional = false
@ -201,7 +201,7 @@ toml = ">=0.10.2,<0.11.0"
[[package]]
name = "marshmallow"
version = "3.17.1"
version = "3.18.0"
description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
category = "main"
optional = false
@ -211,9 +211,9 @@ python-versions = ">=3.7"
packaging = ">=17.0"
[package.extras]
dev = ["pytest", "pytz", "simplejson", "mypy (==0.971)", "flake8 (==5.0.4)", "flake8-bugbear (==22.8.22)", "pre-commit (>=2.4,<3.0)", "tox"]
dev = ["pytest", "pytz", "simplejson", "mypy (==0.971)", "flake8 (==5.0.4)", "flake8-bugbear (==22.9.11)", "pre-commit (>=2.4,<3.0)", "tox"]
docs = ["sphinx (==5.1.1)", "sphinx-issues (==3.0.1)", "alabaster (==0.7.12)", "sphinx-version-warning (==1.1.2)", "autodocsumm (==0.2.9)"]
lint = ["mypy (==0.971)", "flake8 (==5.0.4)", "flake8-bugbear (==22.8.22)", "pre-commit (>=2.4,<3.0)"]
lint = ["mypy (==0.971)", "flake8 (==5.0.4)", "flake8-bugbear (==22.9.11)", "pre-commit (>=2.4,<3.0)"]
tests = ["pytest", "pytz", "simplejson"]
[[package]]
@ -362,7 +362,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pydantic"
version = "1.10.1"
version = "1.10.2"
description = "Data validation and settings management using python type hints"
category = "dev"
optional = false
@ -559,10 +559,7 @@ content-hash = "a94015b3d8ca8a0e27556df0eb4697f7b4765510b89b49466ffc2a1a92174616
atomicwrites = []
attrs = []
autoflake = []
autoimport = [
{file = "autoimport-1.2.2-py3-none-any.whl", hash = "sha256:cf8982a621df199eff0e88f3f1190dc4f72093395f6bf478e544fac10217f160"},
{file = "autoimport-1.2.2.tar.gz", hash = "sha256:ae58d93b1b71529f78bcf06733e60170600620c903740f5745f928cc8f1243f3"},
]
autoimport = []
black = []
click = [
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},

0
test Normal file
View File