def murmur3_x86_32(data: Union[bytes, bytearray], seed: int = 0) -> int:
    """
    Pure 32-bit Python implementation of MurmurHash3; see
    http://stackoverflow.com/questions/13305290/is-there-a-pure-python-implementation-of-murmurhash.
     
    Args:
        data: data to hash 
        seed: seed

    Returns:
        integer hash

    """  # noqa
    c1 = 0xcc9e2d51
    c2 = 0x1b873593

    length = len(data)
    h1 = seed
    rounded_end = (length & 0xfffffffc)  # round down to 4 byte block
    for i in range(0, rounded_end, 4):
        # little endian load order
        # RNC: removed ord() calls
        k1 = (data[i] & 0xff) | ((data[i + 1] & 0xff) << 8) | \
             ((data[i + 2] & 0xff) << 16) | (data[i + 3] << 24)
        k1 *= c1
        k1 = (k1 << 15) | ((k1 & 0xffffffff) >> 17)  # ROTL32(k1, 15)
        k1 *= c2

        h1 ^= k1
        h1 = (h1 << 13) | ((h1 & 0xffffffff) >> 19)  # ROTL32(h1, 13)
        h1 = h1 * 5 + 0xe6546b64

    # tail
    k1 = 0

    val = length & 0x03
    if val == 3:
        k1 = (data[rounded_end + 2] & 0xff) << 16
    # fallthrough
    if val in (2, 3):
        k1 |= (data[rounded_end + 1] & 0xff) << 8
    # fallthrough
    if val in (1, 2, 3):
        k1 |= data[rounded_end] & 0xff
        k1 *= c1
        k1 = (k1 << 15) | ((k1 & 0xffffffff) >> 17)  # ROTL32(k1, 15)
        k1 *= c2
        h1 ^= k1

    # finalization
    h1 ^= length

    # fmix(h1)
    h1 ^= ((h1 & 0xffffffff) >> 16)
    h1 *= 0x85ebca6b
    h1 ^= ((h1 & 0xffffffff) >> 13)
    h1 *= 0xc2b2ae35
    h1 ^= ((h1 & 0xffffffff) >> 16)

    return h1 & 0xffffffff