Skip to content

MMIO.write raises ValueError for IntEnum/IntFlag values #1540

@gweesip

Description

@gweesip
  • PYNQ version: all current versions
  • Board name: any, pure Python issue
  • Pull request type: bug fix
  • Pull request number: N/A
  • Description:

MMIO.write uses type(data) is int to check whether the supplied data is an integer, which excludes IntEnum and IntFlag values despite them being fully int-compatible (isinstance(data, int) returns True for both). This means that passing an IntEnum or IntFlag value directly raises a ValueError: Data type must be int or bytes, requiring an explicit int() cast at the call site as a workaround.

Reproduction:

from enum import IntEnum
from pynq import MMIO

class MyReg(IntEnum):
    ENABLE = 1

mmio = MMIO(0x40000000, 0x1000)
mmio.write(0x0, MyReg.ENABLE)      # raises ValueError: Data type must be int or bytes.
mmio.write(0x0, int(MyReg.ENABLE)) # workaround

The relevant check in mmio.py:

if type(data) is int:
    self.array[idx] = data
elif type(data) is bytes:
    self._hook.write(offset, data)
else:
    raise ValueError("Data type must be int or bytes.")

The numpy assignment (self.array[idx] = np.uint32(data)) on the integer path handles IntEnum/IntFlag values without issue, so there is no technical reason to exclude them. The fix is to replace the strict identity checks with isinstance checks:

if isinstance(data, int):
    self.array[idx] = data
elif isinstance(data, bytes):
    self._hook.write(offset, data)
else:
    raise ValueError("Data type must be int or bytes.")

This is consistent with Python's duck-typing conventions and would allow IntEnum and IntFlag values to be passed without requiring the caller to manually cast them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions