Skip to content
Merged
Show file tree
Hide file tree
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
20 changes: 19 additions & 1 deletion area_reader/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3901,7 +3901,25 @@ def __init__(self, *args, **kwargs):
)

def _unstructure_enum(self, obj):
name = obj.name if obj.name is not None else str(obj.value)
# Composite Flag values have no .name before Python 3.11; decompose
# into single-bit member names in ascending bit order, matching the
# names 3.11+ produces, so JSON output is identical on every version.
name = obj.name
if name is None and isinstance(obj, enum.Flag):
bits = {
member.value: member.name
for member in type(obj).__members__.values()
if member.value and not member.value & (member.value - 1)
}
names = [bits[bit] for bit in sorted(bits) if obj.value & bit]
covered = 0
for bit in bits:
if obj.value & bit:
covered |= bit
if names and covered == obj.value:
name = "|".join(names)
if name is None:
name = str(obj.value)
return obj.__class__.__name__ + "." + name


Expand Down
17 changes: 12 additions & 5 deletions test_jsonification.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,21 @@ def test_every_int_flag_type_jsonifies_zero(flag_type):
ids=lambda flag_type: flag_type.__name__,
)
def test_every_int_flag_type_jsonifies_named_combinations(flag_type):
members = list(flag_type)
if len(members) < 2:
pytest.skip("flag type has fewer than two iterable members")
value = members[0] | members[1]
bits = sorted(
{
member.value: member
for member in flag_type.__members__.values()
if member.value and not member.value & (member.value - 1)
}.values(),
key=lambda member: member.value,
)
if len(bits) < 2:
pytest.skip("flag type has fewer than two single-bit members")
value = bits[0] | bits[1]

result = area_reader.EnumNameConverter().unstructure(value)

assert result == f"{flag_type.__name__}.{value.name}"
assert result == f"{flag_type.__name__}.{bits[0].name}|{bits[1].name}"
assert json.loads(json.dumps(result)) == result


Expand Down
2 changes: 2 additions & 0 deletions test_swr_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ def test_swr_write_uses_the_canonical_rendering(tmp_path: Path) -> None:


def test_fuss_fields_are_editable_declaratively(tmp_path: Path) -> None:
if not swr_paths():
pytest.skip("upstream SWR/FUSS corpus is unavailable")
source = load_swr(UPSTREAM_SWR / "area" / "kashyyyk")
mob = next(iter(source.area.mobs.values()))
room = next(iter(source.area.rooms.values()))
Expand Down