Skip to main content

spasmlang

PyPI - Version PyPI - Python Version

Synopsis

spasmlang is a simple Python assembly language. It lets you generate CPython bytecode from a simple assembly-like syntax, and assembles it with a bundled C++ extension rather than a pure-Python bytecode library.

Supports CPython 3.10 through 3.14, and has no runtime dependencies.


Table of Contents

Installation

pip install spasmlang

Wheels are published for CPython 3.10–3.14 on Linux, macOS and Windows. Installing from source needs a C++17 compiler.

Usage

The spasmlang package provides a class, Assembly, that allows you to generate bytecode from a simple assembly-like syntax. See the examples below for a taste of its API. Where source-level assembly isn't practical, the low-level API lets you string instruction objects together directly.

You can also use the spasm command-line utility to compile assembly files directly to Python bytecode:

spasm example.pya  # generates example.pyc

Examples

This is how the classic "Hello, World!" program looks like, targeting the CPython 3.12 bytecode:

from spasm import Assembly

asm = Assembly()
asm.parse(
    r"""
    push_null
    load_const          print
    load_const          "Hello, World!"
    call                1
    return_value
    """
)
exec(asm.compile())

This is how you can compile the file example.pya to example.pyc to create a "Hello, World!" module, again targeting CPython 3.11:

# example.pya
    resume      0
    push_null
    load_name   $print
    load_const  "Hello, spasm!"
    precall     1
    call        1
    pop_top
    load_const  None
    return_value

Compile the assembly code with (assuming that you have installed spasmlang with CPython 3.11)

spasm example.pya

and then execute the generated module with e.g.

python3.11 -m example

This example shows how to create a module that exports a greet function that takes one argument, targeting CPython 3.11:

# greet.pya

code greet(who)
    resume                      0
    load_global                 (True, "print")
    load_const                  "Hello, "
    load_fast                   $who
    format_value                0
    build_string                2
    precall                     1
    call                        1
    return_value
end

    resume 0
    load_const                  .greet
    make_function               0
    store_name                  $greet
    load_const                  None
    return_value

Again, compile the assembly code with

spasm greet.pya

and test it with

$ python3.11 -c "from greet import greet; greet('spasmlang')"
Hello, spasmlang

Code blocks nest, and a block header can declare the variables the block shares with the one around it, which is what a closure needs:

code NAME(arguments)[cells]<frees>

The two trailing groups are optional and independent, so code f(x)<n> declares a free variable and no cells. Cells are this block's locals that a nested block captures; frees are the ones it captures from its own enclosing block. They have to be written down because nothing in the instruction stream tells the two apart — LOAD_DEREF $n looks the same either way.

This is lambda n: lambda: n in assembly, targeting CPython 3.12:

# adder.pya

code outer(n)[n]
    make_cell                   $n
    resume                      0

    code inner()<n>
        copy_free_vars          1
        resume                  0
        load_deref              $n
        return_value
    end

    load_closure                $n
    build_tuple                 1
    load_const                  .inner
    make_function               8
    return_value
end

    resume                      0
    load_const                  .outer
    make_function               0
    store_name                  $outer
    load_const                  None
    return_value
$ spasm adder.pya && python3.12 -c "from adder import outer; print(outer(42)())"
42

Note that n appears both as an argument of outer and in its cell list: from CPython 3.11 a captured parameter occupies a single frame slot that is at once a local and a cell, and MAKE_CELL is what turns it into one. inner is reachable only from outer, since a nested block is a constant of the block it is written in and not of the module.

Low-level API

Writing a snippet of assembly is the shortest way to get bytecode, but it is not always the right shape for the job. When the instruction stream is being computed rather than written — you are transforming an existing code object, generating a sequence whose length depends on runtime data, or injecting instrumentation into somebody else's function — you want to string instructions together as objects. That is what spasm.bytecode exposes, and it is the same layer the assembler itself is built on.

from spasm.bytecode import Bytecode, ExcEntry, Instr, Label

The data model

A Bytecode is a mutable, decoded code object. Bytecode.from_code(co) builds one from an existing code object and bc.to_code() encodes it back; the round trip is lossless, so decoding and re-encoding an untouched function gives back byte-identical co_code, line table and exception table.

Attribute Meaning
instrs The instruction list. Holds Instr objects and nothing else — no labels, no pseudo-entries.
end_labels Labels for the position one past the last instruction.
exc_entries The ExcEntry list making up the exception table (3.11+).
consts, names, varnames, freevars, cellvars The code object's tables, as plain lists.
argcount, flags, firstlineno, filename, name, qualname The remaining code object fields.

An Instr carries op (settable as an opname string or as an int), arg, and the position attributes lineno, col_offset, end_lineno and end_col.

There is no stacksize: co_stacksize is always computed from the instruction stream by to_code(), and is neither stored nor settable.

Bytecode() with no arguments is an empty template — no instructions, empty tables, argcount 0, flags 0, firstlineno 1, filename <string>, name and qualname <bytecode> — so building from scratch is a matter of filling in the fields you care about. Bytecode(instrs) seeds the instruction list in one go; either way bc.instrs is a live list you can mutate in place.

import sys
import types

from spasm.bytecode import Bytecode, Instr, infer_flags

bc = Bytecode()
if sys.version_info >= (3, 11):
    bc.instrs.append(Instr("RESUME", 0))
bc.instrs += [
    Instr("LOAD_FAST", "x"),
    Instr("LOAD_FAST", "y"),
    Instr("BINARY_OP" if sys.version_info >= (3, 11) else "BINARY_ADD", 0),
    Instr("RETURN_VALUE"),
]
bc.name = bc.qualname = "add"
bc.argcount = 2
bc.varnames = ["x", "y"]
bc.flags = infer_flags(bc, is_function=True)

add = types.FunctionType(bc.to_code(), {})
assert add(1, 2) == 3

infer_flags derives the co_flags a code object being built from scratch needs, as far as that can be done from the code alone: it cannot see *args/**kwargs or lexical nesting, so CO_VARARGS, CO_VARKEYWORDS and CO_NESTED are left to the caller.

Instruction arguments

Arguments that name a table entry are given as the value, not as the index, and the entry is created if it isn't there already:

Argument kind What to pass
co_consts (LOAD_CONST, …) The constant itself.
co_varnames (LOAD_FAST, STORE_FAST, …) The variable name, as a string.
free/cell variables (LOAD_DEREF, …) The variable name, as a string.
Jump targets A Label.
co_names (LOAD_GLOBAL, LOAD_ATTR, STORE_NAME, …) An int, from encode_name_arg().
Everything else The raw int oparg.

Name arguments are the one exception, because they are not just an index: from 3.11 LOAD_GLOBAL and from 3.12 LOAD_ATTR pack a flag bit alongside it. encode_name_arg(bc, opname, name, flag=False) interns the name and returns the oparg, shifting the index where the version calls for it.

Two more helpers cover opargs that are conceptually symbolic: compare_oparg(Compare.LT) for COMPARE_OP, whose encoding moved twice between 3.10 and 3.13, and the BinaryOp enum for BINARY_OP on 3.11+, whose members are used as the oparg directly.

If you would rather work with indices, add_const(), add_name() and add_varname() intern a value and hand back its index.

The superinstructions that pack two variable indices into a single oparg — LOAD_FAST_LOAD_FAST and friends — take a plain int, since a single name cannot express what they encode.

Jumps and labels

Jump targets are Label objects rather than offsets, which is what makes an instruction list editable: inserting or removing instructions shifts every offset in the code object, but a label stays attached to the instruction it points at.

Make one with bc.new_label(), append it to the labels list of the instruction it should land on, and pass it as the argument of the jump. For a target one past the end of the code, append it to bc.end_labels instead. bc.label_positions() maps every label to the index in instrs it currently resolves to.

bc = Bytecode()
falsy = bc.new_label()

instrs = [Instr("LOAD_FAST", "x")]
if sys.version_info >= (3, 13):
    instrs.append(Instr("TO_BOOL"))  # 3.13+ POP_JUMP_IF_* only accepts a bool
instrs += [
    Instr("POP_JUMP_IF_FALSE", falsy),
    Instr("LOAD_CONST", "truthy"),
    Instr("RETURN_VALUE"),
    Instr("LOAD_CONST", "falsy"),
    Instr("RETURN_VALUE"),
]
instrs[-2].labels.append(falsy)
bc.instrs += instrs

Nothing here needs to know how far the jump reaches: the encoder picks the relative or absolute form the opcode wants, and grows EXTENDED_ARG prefixes to a fixed point when an oparg does not fit in a byte — which it has to iterate, since growing one prefix moves every target after it.

Transforming an existing code object

Instrumentation is the case the API is really shaped for: decode, splice, and encode back.

import sys

from spasm.bytecode import Bytecode, Instr, encode_name_arg

PY311 = sys.version_info >= (3, 11)


def f(a, b):
    return a * b


bc = Bytecode.from_code(f.__code__)

# The flag bit makes LOAD_GLOBAL push the NULL that the call sequence wants,
# in whichever order this version expects it; before 3.11 there is no NULL.
flag = {"flag": True} if PY311 else {}
trace = [
    Instr("LOAD_GLOBAL", encode_name_arg(bc, "LOAD_GLOBAL", "print", **flag)),
    Instr("LOAD_CONST", "called!"),
    Instr("CALL" if PY311 else "CALL_FUNCTION", 1),
    Instr("POP_TOP"),
]

# RESUME has to stay the first instruction of a 3.11+ code object.
at = 1 if PY311 else 0
for instr in trace:
    instr.lineno = bc.instrs[at].lineno
bc.instrs[at:at] = trace

f.__code__ = bc.to_code()
f(3, 4)  # prints "called!" and returns 12

Give inserted instructions a lineno explicitly. Nothing forces you to, but the line table is what tracebacks and debuggers read, and an instrumented function whose lines have drifted is unpleasant to debug.

Exception table entries

From 3.11 on, exception handling is table-driven rather than done with block instructions, and bc.exc_entries is that table. An ExcEntry is three labels — the protected region's start and (exclusive) stop, and the handler — plus the stack depth the handler is entered at and whether the interpreter should push lasti before the exception.

from spasm.bytecode import Bytecode, ExcEntry, Instr


def risky(x):
    return 1 / x


bc = Bytecode.from_code(risky.__code__)

start = bc.new_label()
handler = bc.new_label()
bc.instrs[1].labels.append(start)  # everything after RESUME is protected

recover = [
    Instr("POP_TOP"),  # the exception the interpreter pushed for us
    Instr("LOAD_CONST", None),
    Instr("RETURN_VALUE"),
]
recover[0].labels.append(handler)
for instr in recover:
    instr.lineno = bc.instrs[-1].lineno
bc.instrs += recover

# stop is exclusive, so the handler's own label doubles as the end of the
# region it handles.
bc.exc_entries.append(ExcEntry(start, handler, handler))

risky.__code__ = bc.to_code()
assert risky(0) is None

depth defaults to being inferred, which works whenever the depth at the start of the protected region follows from normal control flow. Where it does not — a handler reachable only through another handler's cleanup path, say — to_code() raises instead of guessing, and you pass the depth yourself.

What is checked, and what is not

to_code() computes co_stacksize, resolves labels, encodes the line and exception tables and rejects opcodes the interpreter reserves for itself: the INSTRUMENTED_* family, ENTER_EXECUTOR, CACHE and the pseudo-opcodes. That last check exists because handing some of them to PyCode_New does not raise, it crashes.

Beyond that, this is an assembly language: it will faithfully encode a stack effect that does not balance, a LOAD_FAST reading a variable that was never stored, or a jump into the middle of an instruction's inline caches, and the interpreter will fault on it. Bytecode that is valid runs; bytecode that merely assembles need not.

Finally, opcodes and calling conventions move between releases — RESUME and BINARY_OP arrived in 3.11, POP_JUMP_IF_FALSE wants a real bool on the stack from 3.13, the NULL a call needs is pushed in a different order in 3.13 than in 3.12 — so code written against this API targets an interpreter version in a way that source-level spasm snippets partly hide. The dis module for the version you are targeting is the reference.

Architecture

spasmlang is two layers.

spasm._core is a C++ extension implementing the bytecode data model — Bytecode, Instr, Label, ExcEntry — along with code object decoding and encoding, line table and exception table handling, and stack depth computation. It carries opcode tables generated at build time for the exact interpreter it is compiled against (see setup.py), which is why there is one wheel per Python minor version rather than a single abi3 wheel.

spasm.bytecode is a thin Python layer over it holding the parts that are version-dependent bookkeeping rather than data structure: the Compare and BinaryOp symbolic opargs and their per-version encodings, name-argument packing for LOAD_GLOBAL/LOAD_ATTR, and co_flags inference. spasm.asm builds on both and stays concerned with parsing and assembly.

Stack depth (co_stacksize) is computed for you. Exception table entry depths are inferred too, but only where that can be done exactly — see the note in spasm/bytecode.py and src/stackdepth.cpp; to_code() raises rather than emit a depth it cannot derive correctly.

This code was previously developed as a separate bytecode-native package and has since been absorbed here.

License

spasmlang is distributed under the terms of the MIT license.

Metadata

Release files for spasmlang 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spasmlang 0.3.0
File Size Uploaded Provenance
spasmlang-0.3.0.tar.gz 94.6 kB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for spasmlang 0.3.0
File
spasmlang-0.3.0-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
spasmlang-0.3.0-cp313-cp313-win32.whl CPython 3.13 CPython 3.13 Windows x86-32 Details
spasmlang-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl CPython 3.13 CPython 3.13 Linux musl 1.2+ x86-64 Details
spasmlang-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64 Details
spasmlang-0.3.0-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
spasmlang-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl CPython 3.13 CPython 3.13 macOS 10.13+ x86-64 Details
spasmlang-0.3.0-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
spasmlang-0.3.0-cp312-cp312-win32.whl CPython 3.12 CPython 3.12 Windows x86-32 Details
spasmlang-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl CPython 3.12 CPython 3.12 Linux musl 1.2+ x86-64 Details
spasmlang-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64 Details
spasmlang-0.3.0-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
spasmlang-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl CPython 3.12 CPython 3.12 macOS 10.13+ x86-64 Details
spasmlang-0.3.0-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
spasmlang-0.3.0-cp311-cp311-win32.whl CPython 3.11 CPython 3.11 Windows x86-32 Details
spasmlang-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl CPython 3.11 CPython 3.11 Linux musl 1.2+ x86-64 Details
spasmlang-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64 Details
spasmlang-0.3.0-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
spasmlang-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl CPython 3.11 CPython 3.11 macOS 10.9+ x86-64 Details
spasmlang-0.3.0-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details
spasmlang-0.3.0-cp310-cp310-win32.whl CPython 3.10 CPython 3.10 Windows x86-32 Details
spasmlang-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl CPython 3.10 CPython 3.10 Linux musl 1.2+ x86-64 Details
spasmlang-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64 Details
spasmlang-0.3.0-cp310-cp310-macosx_11_0_arm64.whl CPython 3.10 CPython 3.10 macOS 11.0+ ARM64 Details
spasmlang-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl CPython 3.10 CPython 3.10 macOS 10.9+ x86-64 Details

Total release size: 11.0 MB

Release files / spasmlang-0.3.0.tar.gz

Download URL spasmlang-0.3.0.tar.gz
Size 94.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5a049c129b52600236b275e1b1561c0d8d3a887479b477a256bcf5360fecab90
BLAKE2b-256 checksum
How to use checksums
e1c0434c4d784381299d7c9da9c4078521cd96400054a76b53f0ca6569e92eed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp313-cp313-win_amd64.whl

Download URL spasmlang-0.3.0-cp313-cp313-win_amd64.whl
Size 72.2 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
450efe1acc5c19da42557e1ca481b3956e03001deb0175b1df040e897a5a0312
BLAKE2b-256 checksum
How to use checksums
88b74d832f75776f5ce3f938136c207195e995864a49bd615711825d330616a4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp313-cp313-win32.whl

Download URL spasmlang-0.3.0-cp313-cp313-win32.whl
Size 61.7 kB
Tags CPython 3.13 Windows x86-32
SHA-256 checksum
How to use checksums
d96a327d6102ff4850b952f06b0b8d044b4ea5da9d06b16943bd5865832baeca
BLAKE2b-256 checksum
How to use checksums
b1fb9d93ab94031995ff586f28557d65c54c696d65007237ae48275a97549874
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl

Download URL spasmlang-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl
Size 1.7 MB
Tags CPython 3.13 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
d3d6eb8a9aaf438ae7f719cd8155c47e898e374e1aff7eb35de5f57c746beaf2
BLAKE2b-256 checksum
How to use checksums
3218a336153896e78ca48d2978ad24c1394a49355679d80eb4be03d2bb791265
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL spasmlang-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 801.0 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
d2e68bf22736a10c3c2ed71464cee3939772025486e4613a2a41dcffbd472124
BLAKE2b-256 checksum
How to use checksums
08e1ac84b2dbceb060a4cdb49c7ae5f09b4a92387bb04455cd201bf656c9cd18
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp313-cp313-macosx_11_0_arm64.whl

Download URL spasmlang-0.3.0-cp313-cp313-macosx_11_0_arm64.whl
Size 68.0 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
1d1a20977b6c29a20b559f2b0f1c98265c598a1078d17d6359e14642324377cb
BLAKE2b-256 checksum
How to use checksums
dc861fcee234d81fd7a1bc47908666345a139f614c7267da1ea361c3bee52cca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl

Download URL spasmlang-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl
Size 70.4 kB
Tags CPython 3.13 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
1e9f189346433fb9788242e6a0d4d60e0d18b14ca1eae4962aa01dc925dbdfc4
BLAKE2b-256 checksum
How to use checksums
0a298a0da5b2be5532742abe8332f7e9be3a042a31aa5bdb58a5232b85513d8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp312-cp312-win_amd64.whl

Download URL spasmlang-0.3.0-cp312-cp312-win_amd64.whl
Size 71.8 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
4ec8c6e898e7f54be9a30424dada6adcb1e5f98c74d6ed02ecd6bb5d48eab471
BLAKE2b-256 checksum
How to use checksums
e7bb56c961f9dcb071bcdac4142fcaa0a2d2b03d8f68da7ffc951758661d0e77
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp312-cp312-win32.whl

Download URL spasmlang-0.3.0-cp312-cp312-win32.whl
Size 61.3 kB
Tags CPython 3.12 Windows x86-32
SHA-256 checksum
How to use checksums
18c78e7ffecb7126b4018881a88e1bf78850230478ee8ad2a9fe16979f9cebb4
BLAKE2b-256 checksum
How to use checksums
ddea685253d525bf4de5eb90c06edf322b76234936fd27123d2acb30670297a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl

Download URL spasmlang-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl
Size 1.7 MB
Tags CPython 3.12 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
9e8d01c7fc110a3320c1cb70154716bc576a4a59b3a5f58230e52c73d890fc29
BLAKE2b-256 checksum
How to use checksums
07865de7b1f43aa35632094e40c15dfb4bd14e5131e432487c4581afba9f830e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL spasmlang-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 800.3 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
a03389dd61275fcb8e215c4896b8d6753289cc8ab5a5ef8a4353b56de516803b
BLAKE2b-256 checksum
How to use checksums
534c07ef59f27fb4d162ed9787b49f847103fcad274bbc528f169f2398c9065c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp312-cp312-macosx_11_0_arm64.whl

Download URL spasmlang-0.3.0-cp312-cp312-macosx_11_0_arm64.whl
Size 68.0 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
d995a9fdd4ec066b6a353174abbe488d9ca22f5cc966dca61689451eda6b7813
BLAKE2b-256 checksum
How to use checksums
dbeeb33d4204f34a02db6f8b6e04d795fa512c25046f0eeb5eb8186383577253
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl

Download URL spasmlang-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl
Size 70.4 kB
Tags CPython 3.12 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
2e48afc91fe3fc14b469c831afeff794d6b848d655dd545d9838821159ea2211
BLAKE2b-256 checksum
How to use checksums
a684478954e9c4290a17aecb6b8620152ad99214847b5a0d367637b38a2127eb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp311-cp311-win_amd64.whl

Download URL spasmlang-0.3.0-cp311-cp311-win_amd64.whl
Size 70.7 kB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
a16a68480e76454de539de0d9d12e1fb9f04223a4017f820efb47f242ee74c93
BLAKE2b-256 checksum
How to use checksums
50e693df269a396d2021fc6fa9a5fe88ae3b5ae5cb62cd1dd745426ce0ac691a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp311-cp311-win32.whl

Download URL spasmlang-0.3.0-cp311-cp311-win32.whl
Size 59.6 kB
Tags CPython 3.11 Windows x86-32
SHA-256 checksum
How to use checksums
78b95906ff470a48cf87e8c23f3f6821eecb4a009b0dc5905d61abca95d1e157
BLAKE2b-256 checksum
How to use checksums
ccbc5b6ecdbc369464f6fc576d53af6b302e26f970d7985cf4607d4a24919380
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl

Download URL spasmlang-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl
Size 1.7 MB
Tags CPython 3.11 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
35a9f6b05c25627f5fd34e92128bc3f1dc717f83d638e15420e70b7a0d217b12
BLAKE2b-256 checksum
How to use checksums
07086b50cc4e4d1b37e1f83a07f46bfb6af3ad166b81fd671201e8b6a7742fa1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL spasmlang-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 791.6 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
918f5880c6ea2e0e4fa4625b07f90ef93f09796f559236bfafccabb9edac6888
BLAKE2b-256 checksum
How to use checksums
15337c285f8629e0fbb9a7ae263611393cb1fd66cb80f3da9b0aec69b71808a5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp311-cp311-macosx_11_0_arm64.whl

Download URL spasmlang-0.3.0-cp311-cp311-macosx_11_0_arm64.whl
Size 66.9 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
1af10438075f9324810cacc4f0a02f9970c9f88423b0b40eb17cf2c3d854935a
BLAKE2b-256 checksum
How to use checksums
79cccc31dc3a9c30de1b4975fa6a04b72e0c71164a257c9b33c640118ae93f51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl

Download URL spasmlang-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl
Size 69.4 kB
Tags CPython 3.11 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
17c670bed981e0a0c311a3f2ec1b0b02bd352fd88c02a39a07d59d24194daec7
BLAKE2b-256 checksum
How to use checksums
022b7f62f509a43636ef4c581cc9bd29fa4efbbc425aaabb80f4723e4f126449
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp310-cp310-win_amd64.whl

Download URL spasmlang-0.3.0-cp310-cp310-win_amd64.whl
Size 60.4 kB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
96ad2f577a7cbd1246b97c71d8eebb5c427ad97ff77f17ab0a3440642a1a5c58
BLAKE2b-256 checksum
How to use checksums
c3c991c5999d472c4ed95e252a3250b71130cf04b158b530f5a1b7daea4e46af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp310-cp310-win32.whl

Download URL spasmlang-0.3.0-cp310-cp310-win32.whl
Size 53.1 kB
Tags CPython 3.10 Windows x86-32
SHA-256 checksum
How to use checksums
41b405df281355161c1f7b87bbdc5324df4f4feef56f937d658b3e7ab108dc48
BLAKE2b-256 checksum
How to use checksums
a2135b992170da9675e2a0f567be2854308a89808c70fde63c96e73be11d35e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl

Download URL spasmlang-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl
Size 1.6 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
f77e90630da7da2aadc05922be12e6ed232dd07c37e7475f1f5fad5df8257247
BLAKE2b-256 checksum
How to use checksums
6870b34d523a8629f04b59a8c42deb73f49e3528a23f55cab717fcda975153ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL spasmlang-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 653.1 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
934b62ead54d224c0dc4cf80b8c9f39a4c415578380a2f4381f6dc8bdf164d6d
BLAKE2b-256 checksum
How to use checksums
99fe43d521d569973bf85e321cbbae2b445f0070f77ee3cf3ca4d5f4c2c30283
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp310-cp310-macosx_11_0_arm64.whl

Download URL spasmlang-0.3.0-cp310-cp310-macosx_11_0_arm64.whl
Size 57.9 kB
Tags CPython 3.10 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
0ad3156932da000c4c8fbc2361dc780a741292dd6459cffb80db833a824afc5e
BLAKE2b-256 checksum
How to use checksums
93ab266c071f930d08fbadbd3385f371fe01b1f860c8f89da374ebbc7aaa5648
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / spasmlang-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl

Download URL spasmlang-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl
Size 59.0 kB
Tags CPython 3.10 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
fad3ca8d986ddcaa33d6374e70ed9b4275001d46476b78555e0a155590a8b6e5
BLAKE2b-256 checksum
How to use checksums
d39b0c4887d97ed1dcccddc76a12092ec451116dec09007ae40e69a16f445e56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for spasmlang 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page