Libraries

pyc's standard library is ordinary Python, compiled with your program. Growing it is the most direct way to widen what pyc can compile.

How libraries work

There is no prebuilt runtime library to link against. import math resolves at compile time to pyc_lib/math.py, which is analysed and compiled along with the rest of the program. A function you never call is never emitted, and a library function is specialized for the types your program passes it, exactly like your own code.

The built-in types themselves (str, list, dict, set, exceptions, generators) are also Python, in __pyc__/, on top of a small C runtime.

Real or raise

The rule for every module:

a function either computes CPython's answer, or it raises the exception CPython would raise for something it cannot do. A stub that returns a plausible made-up value is a silent wrong answer, and silent wrong answers are bugs.

A name that doesn't exist yet is a compile error, never a wrong result.

Modules today

ModuleStatusCovers
mathpartialpi, e, tau, inf; sqrt, exp, log/log2/log10, pow, hypot, fabs, fmod, floor, ceil, trig and hyperbolic functions, radians, degrees
Bound straight to libc, so results match CPython's C-backed math.
randomcompleteseed, random, getrandbits, uniform, randrange, randint, choice, shuffle, sample, triangular
True MT19937 with CPython’s seeding, so seeded programs match CPython draw for draw.
collectionspartialdeque, defaultdict
heapqcompleteheappush, heappop, heapreplace, heappushpop, heapify
Mirrors CPython's heapq.py.
itertoolspartialcount, product
functoolspartialreduce
copycompletecopy, deepcopy
repartialcompile, match, fullmatch, search; classes, groups, alternation, greedy and lazy quantifiers, anchors
A backtracking engine written in Python. findall, sub and split are not implemented yet.
fnmatchcompletefnmatch, fnmatchcase, filter
stringcompleteascii_* constants, digits, punctuation, whitespace, printable, capwords
structpartialpack, unpack, unpack_from, calcsize for the integer formats
arraypartialarray with typecode; tobytes/frombytes for integer typecodes
hashlibpartialmd5 (RFC 1321)
The other algorithms raise NotImplementedError.
colorsyscompletergb/yiq/hls/hsv conversions
Ported from CPython's colorsys.py.
getoptcompletegetopt, gnu_getopt, GetoptError
Ported from CPython's getopt.py.
iopartialStringIO, BytesIO
syspartialargv, exit, maxsize, stdin/stdout/stderr, version, platform, setrecursionlimit
ospartiallistdir, walk, getcwd, chdir, mkdir, remove, rename, stat, system, path
timepartialtime, sleep
socketpartialsocket (bind, listen, accept, recv, send, setsockopt), gethostname
selectpartialselect
serialpartialThe pyserial API surface
Opening a port raises SerialException, as pyserial does for a port it cannot open.

“Complete” means the commonly used surface of the module is implemented with CPython's behaviour, not that every name in CPython's module exists.

Next up

These are the modules that real programs reach for most often and that pyc does not have yet. Each one is a self-contained contribution.

dataclasses

The idiomatic record type. A natural fit: fields and their types are fixed per class.

enum

Enumerations compile to integers with names, with no run-time cost.

typing

Accept annotations, and in strict mode check them against what inference found.

itertools (complete)

chain, islice, permutations, combinations, groupby, accumulate, zip_longest.

functools (complete)

partial, lru_cache, cache, cmp_to_key, total_ordering.

collections (complete)

Counter, OrderedDict, namedtuple.

re (complete)

findall, finditer, sub, split, named groups, flags.

bisect

Small, pure Python, widely used.

json

Serialization of typed records, and parsing into a declared shape.

asyncio

A CPython-compatible front end for the event loop async/await already compiles to.

pathlib / os.path

Modern file-system access.

statistics, fractions, decimal

Numeric work beyond math.

hashlib (complete)

sha1 and the sha2 family.

unittest

Test the compiled program with the same tests that run under CPython.

Writing a module

A module is a Python file in pyc_lib/. Write it in plain Python wherever possible. Porting CPython's own pure-Python implementation is often the right start. Where you need the C library, bind a function with __pyc_c_call__:

pyc_lib/math.py (excerpt)
pi = 3.141592653589793

def sqrt(x): return __pyc_c_call__(float, "sqrt", float, x)
def floor(x): ...   # returns int, as in CPython 3

Then:

  1. Add tests under tests/. The harness compares every test's output with CPython's, on both backends.
  2. Check the module under --strict. It should compile without any accommodation, so that strict programs can use it.
  3. Run make test.

The runtime guide, RUNTIME.md, has recipes for adding new runtime support.