Changelog#
Full project changelog (mirrored from the repository root).
Changelog#
[2.1.0] — 2026-09-06 — systems call and buffer helpers#
Add
cycallzero-, one-, and two-argument CPython call helpers, including a cimport-only vectorcall primitive.Add public buffer and memoryview metadata inspection helpers.
Prefer
cyerrraised-exception get/set lifecycle helpers on Python 3.14+.
[2.0.0] — 2026-08-06 — rename import package to picop (soft cypy alias)#
Move implementation tree to
src/picop/(preferred import:from picop…/from picop… cimport).Keep
src/cypy/as a soft shim: re-exportspicop, emitsDeprecationWarningon import; Cythoncimportshims mirror the same surface.PyPI distribution name was already
picop(pip install picop); version 2.0.0.Fix
cycevalcimport helper:PyEval_ThreadsInitializedremoved on 3.14 —eval_threads_initializedalways returns true so barrel cimport builds.3.0 plan: remove the
cypyimport package and cimport shims entirely — migrate call sites topicopbefore then.
[1.44.16] — 2026-08-06 — PyPI name picop + publish CI#
PyPI distribution name is
picop(pip install picop); import package remainscypy.Add Trusted Publishing workflow
.github/workflows/publish.yml(tagv*→ PyPI; manual → TestPyPI/PyPI).Publish sdist only (PyPI rejects untagged
linux_x86_64wheels; manylinux via cibuildwheel is follow-up).
[1.44.15] — 2026-08-02 — expand pytest suite beyond UUID#
Add focused pytest modules for
cypy.hot, Core containers,cypy.protocols, export gates, and examplemain()smokes (no API change).
[1.44.14] — 2026-08-02 — stub-hide Tier A losers in cytype#
Omit
type_is_subtypefromcytype.pyi(Tier A>1.02x; stillcpdef).
[1.44.13] — 2026-08-02 — stub-hide Tier A losers in cytime#
Omit
time_wallfromcytime.pyi(Tier A>1.02x; stillcpdef).
[1.44.12] — 2026-08-02 — stub-hide Tier A losers in cyset#
Omit
set_popfromcyset.pyi(Tier A>1.02x; stillcpdef).
[1.44.11] — 2026-08-02 — stub-hide Tier A losers in cymethod#
Omit
method_newfromcymethod.pyi(Tier A>1.02x; stillcpdef).
[1.44.10] — 2026-08-02 — stub-hide Tier A losers in cyiterator#
Omit
iter_nextfromcyiterator.pyi(Tier A>1.02x; stillcpdef).
[1.44.9] — 2026-08-02 — stub-hide Tier A losers in cycodecs#
Omit
codec_encode,codec_decodefromcycodecs.pyi(Tier A>1.02x; stillcpdef).
[1.44.8] — 2026-08-02 — stub-hide Tier A losers in cyiterobject#
Omit
seqiter_new,calliter_newfromcyiterobject.pyi(Tier A>1.02x; stillcpdef).
[1.44.7] — 2026-08-02 — stub-hide Tier A losers in cyfloat#
Omit
float_from_double,float_from_cstr,float_as_doublefromcyfloat.pyi(Tier A>1.02x; stillcpdef).
[1.44.6] — 2026-08-02 — stub-hide Tier A losers in cylong#
Omit
long_from_long,long_from_ssize,long_from_double,long_as_long,long_as_ssize,long_as_doublefromcylong.pyi(Tier A>1.02x; stillcpdef).
[1.44.5] — 2026-08-02 — stub-hide Tier A losers in cymapping#
Omit
map_lenfromcymapping.pyi/cypy.protocols(Tier A>1.02xvslen).
[1.44.4] — 2026-08-02 — stub-hide Tier A losers in cysequence#
Omit
seq_len/seq_size/seq_countfromcysequence.pyi(Tier A>1.02x).Drop
seq_len/seq_sizefromcypy.protocols; keep winning sequence helpers stubbed.
[1.44.3] — 2026-08-02 — stub-hide Tier A losers in cynumber#
Omit measured Tier A losers from
cynumber.pyi(num_add/mul/neg/ …).Keep stubbed:
num_check*/num_eq/num_floordiv/num_inplace_add(+ unmeasured siblings).
[1.44.2] — 2026-08-02 — stub-hide Tier A losers in cyobject#
Omit Tier A losers (
ratio > 1.02vs builtins) fromcyobject.pyi(obj_hasattr/getattr/type/len/ …); keepcpdeffor Cython.Keep stubbed equality winners:
obj_richcompare,obj_richcompare_bool,obj_eq.Drop
obj_len/obj_sizefromcypy.protocols; example smoke uses equality helpers.
[1.44.1] — 2026-08-01 — GCC 14 / 3.14 pxd compile fixes#
Declare
_PySet_Updatevia a local prototype incyset.pxd(exported from libpython but absent from publicPython.hon 3.14).Type
PyType_*externs astype/unsigned longincytype.pxdand cast at call sites so GCC 14+ does not rejectPyObject*vsPyTypeObject*.
[1.44.0] — 2026-07-23 — C-backed UUID values and generation#
Move the optimized UUID implementation from Cycel into
cypy.uuid.Add
UUID,uuid4(), anduuid4_bytes()to the Python and Cython package barrels while retaining stdlibuuid.UUIDinteroperability.Preserve thread-local buffered OpenSSL entropy, fork reset behavior, type declarations, benchmarks, and CPython 3.14t compatibility coverage.
Carry the upstream asyncpg attribution and Apache-2.0 terms for the adapted UUID portions; cypy remains MIT as a whole.
[1.43.1] — 2026-07-22 — package-barrel from cypy cimport fix#
Drop unused wchar
Py_Get/SetProgramNameexterns fromcypylifecycle.pxd(undeclaredwchar_tbroke__init__.pxdre-exports).Remove
nogilfromthread_get_ident(Cython marksPyThread_get_thread_identas GIL-requiring).Fix
longrepr_digitsfor Python 3.14long_value.ob_digitlayout (barrel consumers compile all inlined pxds).Add out-of-tree smoke:
examples/cimport_ext/+scripts/smoke_barrel_cimport.sh.
All notable changes to cypy are documented here. Version from
src/cypy/__about__.py.
[1.43.0] — 2026-07-22 — full public-ops inventory (Tier A + rollups)#
Docs / benches#
Close public-barrel coverage:
cystr_order/cyaccessors/cyruntimeinventory harnesses (+cystr_orderTier B).OPS_INVENTORY.mdnow 0 pending (427 compares / 11 explicitn/a). Rollup:docs/OPS_INVENTORY_TIERB.md. Coverage gate:python3.14 scripts/ops_inventory_coverage.py --strict.Notable:
str_cmpTier B 0.26x;conv_strnicmpTier A ~0.27x; honest loses includemod_import_object(~2x) andcodec_strict_errors(exception path). Stale “leave off hot until measured” tracker notes refreshed.
[1.42.5] — 2026-07-22 — ne/search ops inventory (Tier A+B)#
Docs / benches#
bench/cyne_search_inventory_bench.py+ Tier Bbench/tier_b/cyne_search*forbytes_ne/bytes_startswith/bytes_endswith,bytearray_ne/bytearray_contains,array_ne,memoryview_ne. All gate-pass Tier A; Tier B wins (notablybytearray_contains0.24x,memoryview_ne1KiB Tier A 0.02x vs slow Python). Tracker paste +OPS_INVENTORY→tierB.
[1.42.4] — 2026-07-22 — public ops inventory coverage foundation#
Docs / tooling#
Add
scripts/ops_inventory_coverage.py: publiccy*barrel vssession.comparelabels inbench/**; checklist indocs/OPS_INVENTORY.md(seed: covered →tierA/tierB, gaps →pending). Link fromdocs/README.md.
[1.42.3] — 2026-07-22 — full *_eq Tier B inventory#
Docs / benches#
Tier B depth for all 39 public
*_eqhelpers: cypycdefloop vs typed Cython==baseline (bench/tier_b/cyeq_inventory.py+cyeq_{containers,buffers,scalars,misc}_tb.pyx).Rollup:
docs/EQ_INVENTORY_TIERB.md; paste Tier B tables into module trackers (Tier A kept). Themes: identity/memcmp wins; abstractseq_eq/map_eq/buf_eq/num_eqlose in cdef loops.
[1.42.2] — 2026-07-22 — full *_eq Tier A inventory#
Docs / benches#
Add
bench/cyeq_inventory_bench.pycovering remaining public*_eqhelpers missing from module harnesses; paste measured tables into trackers.docs/EQ_INVENTORY.mdsummary. Note:buf_eqmv↔mv 1.14x lose (prefermemoryview_eq).
[1.42.1] — 2026-07-22 — eq Tier A depth pass#
Fixed / docs#
Replace smoke-placeholder
*_eqtracker rows with measured Tier A tables (deque_eq,range_eq,bytes_bytearray_eq,context_eq, identity misc). New harnesses:bench/cydeque_bench.py,bench/cyrange_bench.py,bench/cyeq_misc_bench.py; extendedcybytes/cycontextvarsbenches.
[1.42.0] — 2026-07-22 — context_eq + Runtime eq stretch#
Added#
context_eq(cycontextvars):Contextvalue equality — identity + richcompare (same asContext.__eq__). Softctxeq. Oncypy(nothot).ContextVar/Tokenstay identity → useobj_eq.**`docs/EQ_RUNTIME.md
**: Runtime/embedding*_eq`` checklist (#44) — skip/done; no mass identity wrappers.
[1.41.0] — 2026-07-22 — bytes_bytearray_eq#
Added#
bytes_bytearray_eq(cybytes): cross-typebytes↔bytearraycontent equality — identity / len +memcmponAS_STRING(either order; same-type also works). Softbba_eq. Oncypy/cypy.buffers(nothot; prefer typedbytes_eq/bytearray_eqthere). Cross-link:buf_eqis buffer-protocol / views, not this.
[1.40.0] — 2026-07-22 — range_eq#
Added#
range_eq(cyrange):rangeequality — identity + richcompare (same asrange.__eq__; empty / equivalent spans). Softrqeq. Oncypy/cypy.containers(nothot).
[1.39.0] — 2026-07-22 — deque_eq#
Added#
deque_eq(cydeque):collections.dequeequality — identity + richcompare (same asdeque.__eq__). Softdqeq. Oncypy/cypy.containers(nothot).
[1.38.0] — 2026-07-22 — func_eq / method_eq / mod_eq / gen_eq / iter_eq#
Added#
func_eq(cyfunction): function equality via identity (a is b) — CPythonobject.__eq__. Softfunceq. Oncypy(nothot).method_eq(cymethod): bound-method equality via identity short-circuitPyObject_RichCompareBool(Py_EQ) — CPythonmethod_richcompare(same function +__self__; not identity). Softmethodeq. Oncypy(nothot).
mod_eq(cymodule): module equality via identity (a is b) — CPythonobject.__eq__. Softmodeq. Oncypy(nothot).gen_eq(cygenobject): generator equality via identity (a is b) — CPythonobject.__eq__. Softgeneq. Oncypy(nothot).iter_eq(cyiterator): iterator equality via identity (a is b) — typical CPythonobject.__eq__. Softitereq. Oncypy(nothot).
Notes#
code_eqskipped: nocycodemodule (cycodecsis codecs); structural code equality would need a dedicated module — out of scope for this batch.
[1.37.0] — 2026-07-22 — weakref_eq#
Added#
weakref_eq(cyweakref): weakref/proxy equality via identity short-circuit +PyObject_RichCompareBool(Py_EQ) — CPythonweakref_richcompare(referent==when both alive; identity when either is dead). Softweakrefeq. Oncypy(nothot— Runtime; validate win before promoting).
[1.36.0] — 2026-07-22 — capsule_eq#
Added#
capsule_eq(cypycapsule): capsule equality via identity (a is b) — CPython usesobject.__eq__; same pointer/name does not make distinct capsules equal. Softcapsuleeq. Oncypy(nothot— Runtime; validate win before promoting).
[1.35.0] — 2026-07-22 — cell_eq#
Added#
cell_eq(cycellobject): cell equality via identity short-circuit +PyObject_RichCompareBool(Py_EQ) — content equality (CPythoncell_richcompare; empty↔empty True; not identity). Softcelleq. Oncypy(nothot— Runtime; validate win before promoting).
[1.34.0] — 2026-07-22 — type_eq#
Added#
type_eq(cytype): type-object equality via identity (a is b) — CPythontype_richcomparedefault; not Python==when a metaclass overrides__eq__. Softtypeeq(teqremainstuple_eq). Oncypy(nothot— Runtime; validate win before promoting).
[1.33.0] — 2026-07-22 — obj_eq#
Added#
obj_eq(cyobject): generic object equality viaPyObject_RichCompareBool(Py_EQ) — identity short-circuit (incl.nan is nan→ True; same as the C-API, not always Python==for floats). Prefer typed*_eqwhen known. Softoeq. Oncypy/cypy.protocols(nothot— validate win before promoting).
[1.32.0] — 2026-07-22 — dt_timedelta_eq#
Added#
dt_timedelta_eq(cydatetime): timedelta equality — identity short-circuit; exacttimedeltapairs compare days/seconds/microseconds; else richcompare (subtypes — Python==parity). Softdteq_delta. Oncypy(nothot— Runtime; validate win before promoting).
[1.31.0] — 2026-07-22 — dt_datetime_eq#
Added#
dt_datetime_eq(cydatetime): datetime equality — identity short-circuit; exact naivedatetimepairs compare year/month/day/hour/minute/second/ microsecond; else richcompare (subtypes / aware/naive / offset / date↔datetime Python==parity; fold ignored). Softdteq_dt. Oncypy(nothot— Runtime; validate win before promoting).
[1.30.0] — 2026-07-22 — dt_time_eq#
Added#
dt_time_eq(cydatetime): time equality — identity short-circuit; exact naivetimepairs compare hour/minute/second/microsecond; else richcompare (subtypes / aware/naive / offset Python==parity; fold ignored). Softdteq_time. Oncypy(nothot— Runtime; validate win before promoting).
[1.29.0] — 2026-07-22 — dt_date_eq#
Added#
dt_date_eq(cydatetime): date equality — identity short-circuit; exactdatepairs compare year/month/day; else richcompare (subtypes /datevsdatetimePython==parity). Softdteq_date. Oncypy(nothot— Runtime; validate win before promoting).
[1.28.0] — 2026-07-22 — slice_eq#
Added#
slice_eq(cyslice): slice equality — identity short-circuit + richcompare (same semantics asslice.__eq__; compares start/stop/step objects, soNonebounds are not normalized to0/1). Softsleq. Oncypy/cypy.buffers(nothot— completeness / buffer-adjacent).
[1.27.0] — 2026-07-22 — num_eq#
Added#
num_eq(cynumber): abstract number equality viaPyObject_RichCompare(Python==parity, including NaN != NaN even for the same object — notRichCompareBool, which identity-shortcuts). Prefer typedlong_eq/float_eq/complex_eq/bool_eqwhen known. Softneq_num. Oncypy/cypy.protocols(nothot).
[1.26.0] — 2026-07-22 — complex_eq#
Added#
complex_eq(cycomplex): complex/value equality with Python parity (NaN on either real or imag => unequal even for the same object;+0.0 == -0.0on each part). Complex/complex uses Cdouble ==on real/imag; mixed types usePyObject_RichCompare(notRichCompareBool, which identity-shortcuts same-object NaN parts). Softceq. Oncypy(nothot— clarity / scalar completeness).
[1.25.0] — 2026-07-22 — float_eq#
Added#
float_eq(cyfloat): float/value equality with Python parity (NaN != NaN even for the same object,+0.0 == -0.0). Float/float uses Cdouble ==; mixed types usePyObject_RichCompare(notRichCompareBool, which identity-shortcuts NaN). Softfeq. Oncypy(nothot— clarity / scalar completeness).
[1.24.0] — 2026-07-22 — bool_eq#
Added#
bool_eq(cybool): boolean/value equality — identity short-circuit + richcompare (same semantics as==; True/False singletons hit identity). Softbooleq. Oncypy(nothot— clarity / scalar completeness).
[1.23.0] — 2026-07-22 — long_eq / int_eq#
Added#
long_eq/int_eq(cylong): integer equality — identity short-circuit + richcompare (same semantics as==). Preferredlong_eq;int_eqis a discoverability alias. Softloeq/ieq. Oncypy(nothot— small-int==already specializes).
[1.22.0] — 2026-07-22 — map_eq#
Added#
map_eq(cymapping): abstract mapping equality — identity/size short-circuit + richcompare (same semantics as==). Softmapeq. Prefer typeddict_eqwhen known. Oncypy/cypy.protocols.
[1.21.0] — 2026-07-22 — seq_eq#
Added#
seq_eq(cysequence): abstract sequence equality — identity/size short-circuit + richcompare (same semantics as==). Softsqeq. Prefer typedlist_eq/tuple_eqwhen known. Oncypy/cypy.protocols.
[1.20.0] — 2026-07-22 — frozenset_eq#
Added#
frozenset_eq(cyset): typedfrozensetequality — identity/size short-circuit + richcompare (same semantics as==). Softfseteq. Oncypy/cypy.containers.
[1.19.0] — 2026-07-22 — set_eq#
Added#
set_eq(cyset): typedsetequality — identity/size short-circuit + richcompare (same semantics as==). Softseteq(notseq— avoidsseq_*/sq*confusion). Oncypy/cypy.containers.
[1.18.0] — 2026-07-22 — dict_eq#
Added#
dict_eq(cydict): typeddictequality — identity/size short-circuit + richcompare (same semantics as==). Softdeq. Oncypy/cypy.containers.
[1.17.0] — 2026-07-22 — tuple_eq#
Added#
tuple_eq(cytuple): typedtupleequality — identity/len + richcompare. Softteq. Oncypy/cypy.containers.
[1.16.0] — 2026-07-22 — list_eq#
Added#
list_eq(cylist): typedlistequality — identity/len short-circuit + richcompare (same semantics as==). Softleq. Oncypy/cypy.containers.
[1.15.0] — 2026-07-22 — uutf8_eq#
Added#
uutf8_eq(cyunicode, cimport-only): compare UTF-8 byte views of twostrviauutf8_and_size+memcmp(embedded NUL OK). Borrowed pointers must not outlive the arguments.
[1.14.0] — 2026-07-22 — str_lt / str_le / str_gt / str_ge#
Added#
str_lt/str_le/str_gt/str_ge(cystr): typed ordering predicates viastr_cmp. Softslt/sle/sgt/sge. Oncypy(nothot).
[1.13.0] — 2026-07-22 — str_cmp#
Added#
str_cmp(cystr): three-way typedstrcompare →-1/0/1viaPyUnicode_Compare(identity short-circuit). Soft aliasesstr_compare/scmp(COMPAT only). Oncypy(nothot).
[1.12.0] — 2026-07-22 — unicode_eq#
Added#
unicode_eq(cyunicode): discoverability alias ofstr_eq(same semantics; no divergent UCS path). Softueq. Oncypy.
[1.11.0] — 2026-07-22 — bytes_endswith#
Added#
bytes_endswith(cybytes): typed suffix test — empty suffix True, longer-than-sFalse, else tailmemcmp. Softbendswith. Oncypy/cypy.hot/cypy.buffers(mirrorsstr_endswith).
[1.10.0] — 2026-07-22 — bytes_startswith#
Added#
bytes_startswith(cybytes): typed prefix test — empty prefix True, longer-than-sFalse, elsememcmponPyBytes_AS_STRING. Softbstartswith. Oncypy/cypy.hot/cypy.buffers(mirrorsstr_startswith).
[1.9.0] — 2026-07-22 — bytearray_contains#
Added#
bytearray_contains(cybytearray): typedbytearraymembership for abytesneedle — same small-buffermemchr/memmem/ large-bufferinhybrid asbytes_contains. Softbacontains. Oncypy/cypy.hot/cypy.buffers.
[1.8.0] — 2026-07-22 — buf_eq#
Added#
buf_eq(cybuffer): abstract buffer-protocol equality — acquirePyBUF_FULL_ROviews, format/size/shape gates, C-contiguousmemcmpfast path, non-contiguous →memoryviewrichcompare. Soft aliasbuffer_eq(COMPAT only). Oncypy/cypy.buffers(nothot— heavier than typedbytes_eq).
[1.7.0] — 2026-07-22 — bytearray_ne / array_ne / memoryview_ne#
Added#
bytearray_ne,array_ne,memoryview_ne: typed inequality siblings of the corresponding*_eqhelpers (not *_eq/ softbane/ayne/mvne). Same contig/format rules as*_eq. Oncypy/cypy.hot/cypy.buffers(mirrorsbytes_ne/str_ne).
[1.6.0] — 2026-07-22 — bytes_ne#
Added#
bytes_ne(cybytes): typedbytesinequality (not bytes_eq/ softbne). Oncypy/cypy.hot/cypy.buffers(mirrorsstr_neAPI; pairs withbytes_eq).
[1.5.0] — 2026-07-22 — memoryview_eq#
Added#
memoryview_eq(cymemoryview): typedmemoryviewequality — C-contiguous same layout/memcmpfast path; non-contiguous falls back to richcompare. Softmveqcdef-only; oncypy/cypy.hot/cypy.buffers.
[1.4.0] — 2026-07-22 — array_eq#
Added#
array_eq(cyarray): typedarray.arrayequality — identity/typecode/len short-circuit +memcmpoveritemsize * len(mirrorsbytes_eq). Soft letterayeqstays cdef-only; preferred name oncypy/cypy.hot/cypy.buffers. Different typecodes compare false (same as Python==).
[1.3.0] — 2026-07-22 — bytearray_eq#
Added#
bytearray_eq(cybytearray): typedbytearrayequality — identity/len short-circuit +memcmponPyByteArray_AS_STRING(mirrorsbytes_eq). Soft letterbaeqstays cdef-only; preferred name oncypy/cypy.hot/cypy.buffers.
[1.2.0] — 2026-07-22 — unicode_from_string#
Added#
unicode_from_string(cyunicode): cimport thin wrapper forPyUnicode_FromString(no intern). Sibling ofuintern_from_string; mirrorsbytes_from_string.
[1.1.0] — 2026-07-22 — bytes_eq#
Added#
bytes_eq(cybytes): typedbytesequality — identity/len short-circuit +memcmponPyBytes_AS_STRING(mirrorsstr_eq). Soft letterbeqstays cdef-only; preferred name oncypy/cypy.hot/cypy.buffers.
[1.0.0] — 2026-07-21 — Core freeze#
Frozen#
Core public set:
cypy.__all__+cypy.hot— additive minors OK; removals / semantic changes need a major (seedocs/RELEASE.md).Cimport contracts for Core + documented
cdefhelpers: seeCOVERAGE.md§ “1.0 freeze” and per-module Surface / inventory indocs/modules/.
Post-1.0 policy (Protocols / Runtime)#
These tiers are not part of the Core freeze. They may still evolve under minors after 1.0 (additions preferred; removals need deprecation + major when they were public):
Tier |
Examples |
Guidance |
|---|---|---|
Protocols |
|
Prefer typed Core when the concrete type is known; |
Runtime |
|
Not micro-opt defaults; embedding / higher-level bridges |
cimport-only |
|
Cython SDK only — never pure-Python |
DEMOTE_ROOT at 1.0#
Soft-alias demotions completed in 0.3. Protocol/Runtime families remain
importable but outside Core __all__ / cypy.hot (no surprise barrel trim).
[0.3.0] — hard trim (Strategy B)#
Breaking#
Soft root aliases in cypy.compat.COMPAT_MAP are removed
from the cypy barrel and from public .pyi stubs. Soft letter/bare/*_string /
dt_delta_* / method_function / method_self / time_time names are Cython
cdef-only where they remain as implementation. Prefer word-prefix / str_* /
ansi_* / *_cstr / dt_timedelta_* / method_get_* / time_wall.
cypy.__getattr__ raises AttributeError with soft_alias_removal_hint for
removed soft names.
Kept#
Semantic twins (dict_len/dict_size, list_len/list_size, …) stay dual —
never identity-aliased.
[0.2.0] — soft-alias window (Strategy B)#
Soft aliases (removed in 0.3)#
Word-prefix / str_* / ansi_* / *_cstr / dt_timedelta_* / method_get_* /
time_wall preferred; letter/bare/*_string/… dual-exported for the soft window.
Conventions & discovery (Wave 5)#
N3/N4 rules:
docs/NAMING.mdOverlap playbooks:
examples/py_overlap_*.pyFacades:
cypy.containers,cypy.buffers,cypy.protocols(prefercypy.hot)Export CI:
scripts/check_exports.py
[0.1.1] — prior#
Phase 5/6 surface + skill + examples on git tags. See git history / GitHub releases.