spasmlang
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.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spasmlang-0.3.0.tar.gz.
File metadata
- Download URL: spasmlang-0.3.0.tar.gz
- Upload date:
- Size: 94.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a049c129b52600236b275e1b1561c0d8d3a887479b477a256bcf5360fecab90
|
|
| MD5 |
4149c8f7fdb3983a48c44c1dfab16a9a
|
|
| BLAKE2b-256 |
e1c0434c4d784381299d7c9da9c4078521cd96400054a76b53f0ca6569e92eed
|
File details
Details for the file spasmlang-0.3.0-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 72.2 kB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
450efe1acc5c19da42557e1ca481b3956e03001deb0175b1df040e897a5a0312
|
|
| MD5 |
fc606e39b56033ea69669ba58b4da1fb
|
|
| BLAKE2b-256 |
88b74d832f75776f5ce3f938136c207195e995864a49bd615711825d330616a4
|
File details
Details for the file spasmlang-0.3.0-cp313-cp313-win32.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp313-cp313-win32.whl
- Upload date:
- Size: 61.7 kB
- Tags: CPython 3.13, Windows x86
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d96a327d6102ff4850b952f06b0b8d044b4ea5da9d06b16943bd5865832baeca
|
|
| MD5 |
f81257c58df1fb35af9bd1872bfde9e7
|
|
| BLAKE2b-256 |
b1fb9d93ab94031995ff586f28557d65c54c696d65007237ae48275a97549874
|
File details
Details for the file spasmlang-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.13, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3d6eb8a9aaf438ae7f719cd8155c47e898e374e1aff7eb35de5f57c746beaf2
|
|
| MD5 |
48e354aca12f7790af3da6176ec8eddf
|
|
| BLAKE2b-256 |
3218a336153896e78ca48d2978ad24c1394a49355679d80eb4be03d2bb791265
|
File details
Details for the file spasmlang-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 801.0 kB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2e68bf22736a10c3c2ed71464cee3939772025486e4613a2a41dcffbd472124
|
|
| MD5 |
ec24312d338c522c8142046e14844088
|
|
| BLAKE2b-256 |
08e1ac84b2dbceb060a4cdb49c7ae5f09b4a92387bb04455cd201bf656c9cd18
|
File details
Details for the file spasmlang-0.3.0-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 68.0 kB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d1a20977b6c29a20b559f2b0f1c98265c598a1078d17d6359e14642324377cb
|
|
| MD5 |
f013607ebc5d24ea23e8cb80d49ea0a7
|
|
| BLAKE2b-256 |
dc861fcee234d81fd7a1bc47908666345a139f614c7267da1ea361c3bee52cca
|
File details
Details for the file spasmlang-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl
- Upload date:
- Size: 70.4 kB
- Tags: CPython 3.13, macOS 10.13+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e9f189346433fb9788242e6a0d4d60e0d18b14ca1eae4962aa01dc925dbdfc4
|
|
| MD5 |
4cc3abbc75d286e5a6927a8169242551
|
|
| BLAKE2b-256 |
0a298a0da5b2be5532742abe8332f7e9be3a042a31aa5bdb58a5232b85513d8a
|
File details
Details for the file spasmlang-0.3.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 71.8 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ec8c6e898e7f54be9a30424dada6adcb1e5f98c74d6ed02ecd6bb5d48eab471
|
|
| MD5 |
1557713a457f9635bdf205f5bbbd5137
|
|
| BLAKE2b-256 |
e7bb56c961f9dcb071bcdac4142fcaa0a2d2b03d8f68da7ffc951758661d0e77
|
File details
Details for the file spasmlang-0.3.0-cp312-cp312-win32.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp312-cp312-win32.whl
- Upload date:
- Size: 61.3 kB
- Tags: CPython 3.12, Windows x86
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18c78e7ffecb7126b4018881a88e1bf78850230478ee8ad2a9fe16979f9cebb4
|
|
| MD5 |
7b331c5b6977352a34d740ddf1138257
|
|
| BLAKE2b-256 |
ddea685253d525bf4de5eb90c06edf322b76234936fd27123d2acb30670297a3
|
File details
Details for the file spasmlang-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.12, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e8d01c7fc110a3320c1cb70154716bc576a4a59b3a5f58230e52c73d890fc29
|
|
| MD5 |
2737436483ac2f8c114ec10ba7471c10
|
|
| BLAKE2b-256 |
07865de7b1f43aa35632094e40c15dfb4bd14e5131e432487c4581afba9f830e
|
File details
Details for the file spasmlang-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 800.3 kB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a03389dd61275fcb8e215c4896b8d6753289cc8ab5a5ef8a4353b56de516803b
|
|
| MD5 |
5ef8a67129f0ec67662945d39c9b88ff
|
|
| BLAKE2b-256 |
534c07ef59f27fb4d162ed9787b49f847103fcad274bbc528f169f2398c9065c
|
File details
Details for the file spasmlang-0.3.0-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 68.0 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d995a9fdd4ec066b6a353174abbe488d9ca22f5cc966dca61689451eda6b7813
|
|
| MD5 |
662c8260ca4544307a98f36083b03a40
|
|
| BLAKE2b-256 |
dbeeb33d4204f34a02db6f8b6e04d795fa512c25046f0eeb5eb8186383577253
|
File details
Details for the file spasmlang-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl
- Upload date:
- Size: 70.4 kB
- Tags: CPython 3.12, macOS 10.13+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e48afc91fe3fc14b469c831afeff794d6b848d655dd545d9838821159ea2211
|
|
| MD5 |
6166cc06d9835ab164feb5e3269dde38
|
|
| BLAKE2b-256 |
a684478954e9c4290a17aecb6b8620152ad99214847b5a0d367637b38a2127eb
|
File details
Details for the file spasmlang-0.3.0-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 70.7 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a16a68480e76454de539de0d9d12e1fb9f04223a4017f820efb47f242ee74c93
|
|
| MD5 |
307c357b843bd7f5e2e83a5757fca94e
|
|
| BLAKE2b-256 |
50e693df269a396d2021fc6fa9a5fe88ae3b5ae5cb62cd1dd745426ce0ac691a
|
File details
Details for the file spasmlang-0.3.0-cp311-cp311-win32.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp311-cp311-win32.whl
- Upload date:
- Size: 59.6 kB
- Tags: CPython 3.11, Windows x86
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78b95906ff470a48cf87e8c23f3f6821eecb4a009b0dc5905d61abca95d1e157
|
|
| MD5 |
6403a1cef42076ba802bd2e5ad51ded2
|
|
| BLAKE2b-256 |
ccbc5b6ecdbc369464f6fc576d53af6b302e26f970d7985cf4607d4a24919380
|
File details
Details for the file spasmlang-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.11, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
35a9f6b05c25627f5fd34e92128bc3f1dc717f83d638e15420e70b7a0d217b12
|
|
| MD5 |
6f874757484cabe553a6f927b12eb4a2
|
|
| BLAKE2b-256 |
07086b50cc4e4d1b37e1f83a07f46bfb6af3ad166b81fd671201e8b6a7742fa1
|
File details
Details for the file spasmlang-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 791.6 kB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
918f5880c6ea2e0e4fa4625b07f90ef93f09796f559236bfafccabb9edac6888
|
|
| MD5 |
ff72565c87093076764a999c4a68efb8
|
|
| BLAKE2b-256 |
15337c285f8629e0fbb9a7ae263611393cb1fd66cb80f3da9b0aec69b71808a5
|
File details
Details for the file spasmlang-0.3.0-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 66.9 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1af10438075f9324810cacc4f0a02f9970c9f88423b0b40eb17cf2c3d854935a
|
|
| MD5 |
2799edc78084ca9a923d54bfa4c9d96a
|
|
| BLAKE2b-256 |
79cccc31dc3a9c30de1b4975fa6a04b72e0c71164a257c9b33c640118ae93f51
|
File details
Details for the file spasmlang-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl
- Upload date:
- Size: 69.4 kB
- Tags: CPython 3.11, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17c670bed981e0a0c311a3f2ec1b0b02bd352fd88c02a39a07d59d24194daec7
|
|
| MD5 |
07d87c2453616e91728406e1a6b4e7db
|
|
| BLAKE2b-256 |
022b7f62f509a43636ef4c581cc9bd29fa4efbbc425aaabb80f4723e4f126449
|
File details
Details for the file spasmlang-0.3.0-cp310-cp310-win_amd64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 60.4 kB
- Tags: CPython 3.10, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96ad2f577a7cbd1246b97c71d8eebb5c427ad97ff77f17ab0a3440642a1a5c58
|
|
| MD5 |
9ede295470326c42ca4111b5f7693f05
|
|
| BLAKE2b-256 |
c3c991c5999d472c4ed95e252a3250b71130cf04b158b530f5a1b7daea4e46af
|
File details
Details for the file spasmlang-0.3.0-cp310-cp310-win32.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp310-cp310-win32.whl
- Upload date:
- Size: 53.1 kB
- Tags: CPython 3.10, Windows x86
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41b405df281355161c1f7b87bbdc5324df4f4feef56f937d658b3e7ab108dc48
|
|
| MD5 |
276b064e8c826bae9beab70912eba105
|
|
| BLAKE2b-256 |
a2135b992170da9675e2a0f567be2854308a89808c70fde63c96e73be11d35e2
|
File details
Details for the file spasmlang-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.10, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f77e90630da7da2aadc05922be12e6ed232dd07c37e7475f1f5fad5df8257247
|
|
| MD5 |
da3c9baf0f23b670c8176bd6cb554e0d
|
|
| BLAKE2b-256 |
6870b34d523a8629f04b59a8c42deb73f49e3528a23f55cab717fcda975153ea
|
File details
Details for the file spasmlang-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 653.1 kB
- Tags: CPython 3.10, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
934b62ead54d224c0dc4cf80b8c9f39a4c415578380a2f4381f6dc8bdf164d6d
|
|
| MD5 |
56804ed1f593d8d38d8d2644ed76b804
|
|
| BLAKE2b-256 |
99fe43d521d569973bf85e321cbbae2b445f0070f77ee3cf3ca4d5f4c2c30283
|
File details
Details for the file spasmlang-0.3.0-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 57.9 kB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ad3156932da000c4c8fbc2361dc780a741292dd6459cffb80db833a824afc5e
|
|
| MD5 |
e33a43a6668016be97dff9ad9260fd94
|
|
| BLAKE2b-256 |
93ab266c071f930d08fbadbd3385f371fe01b1f860c8f89da374ebbc7aaa5648
|
File details
Details for the file spasmlang-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl.
File metadata
- Download URL: spasmlang-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl
- Upload date:
- Size: 59.0 kB
- Tags: CPython 3.10, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fad3ca8d986ddcaa33d6374e70ed9b4275001d46476b78555e0a155590a8b6e5
|
|
| MD5 |
c82eacb6f60c54f7d09b7298d9156768
|
|
| BLAKE2b-256 |
d39b0c4887d97ed1dcccddc76a12092ec451116dec09007ae40e69a16f445e56
|