Update 2026-09-15: tried the split, found the real blocker
Split Timer.init into the three real keyword-only overloads
(mode=/period=/callback=/hard=, mode=/freq=/callback=/hard=,
mode=/tick_hz=/callback=/hard=) plus a fourth for the existing prescaler=
extension. Each one compiled on its own. Every real call through it did not:
t.init(period=500, callback=on_tick)
error: CompileError: 'init' has more than one @inline overload, and an overload is chosen by
the types of the POSITIONAL arguments, so a keyword argument cannot select one.
This is not particular to Timer.init: any name with more than one @inline overload
refuses every call that uses a keyword argument at all, filed precisely at
PyMCU/PyMCU#447. Timer.init's three MicroPython overloads are keyword-only by
definition (*, mode=..., period=None, ...) -- there is no positional call shape for them to
fall back to -- so splitting it is not just imperfect, it makes the method
uncallable the way MicroPython itself always calls it. Reverted to the single
merged signature this repo already had (init(period=0, mode=1, callback=0, prescaler=0, freq=0)), which is the only shape here that both compiles and stays callable by keyword.
This stays a permanent, structural deviation, not a "someone should decide" one: the split
this issue originally asked for is real work whenever PyMCU/PyMCU#447 lands, not before.
Original report
MicroPython's machine.Timer.init is declared in micropython-rp2-stubs as three
keyword-only overloads that share mode and callback but each accept exactly one of
period=, freq= or tick_hz=:
init(self, *, mode=PERIODIC, period=None, callback=None, hard=None)
init(self, *, mode=PERIODIC, freq=None, callback=None, hard=None)
init(self, *, mode=PERIODIC, tick_hz=None, callback=None, hard=None)
This layer's Timer.init(period=0, mode=1, callback=0, prescaler=0, freq=0) merges period
and freq into one call (deliberately: a caller can reach either unit), adds a
prescaler= low-level override the stub has no equivalent for, and takes all five as
positional-or-keyword rather than keyword-only.
Repo choice
Blocked on PyMCU/PyMCU#447 (keyword arguments refused whenever a name has more than one
@inline overload). Once that lands, splitting init into matching keyword-only
period=/freq=/tick_hz= overloads (losing the "set both" convenience, gaining
tick_hz= -- buildable on this chip as "pick whichever of the four AVR prescalers puts the
counting rate closest to what was asked, fire the callback on overflow") is
src/pymcu_micropython/machine.py-only work; the design above is written out and ready to
paste back in once #447 is fixed.
Update 2026-09-15: tried the split, found the real blocker
Split
Timer.initinto the three real keyword-only overloads(
mode=/period=/callback=/hard=,mode=/freq=/callback=/hard=,mode=/tick_hz=/callback=/hard=) plus a fourth for the existingprescaler=extension. Each one compiled on its own. Every real call through it did not:
This is not particular to
Timer.init: any name with more than one@inlineoverloadrefuses every call that uses a keyword argument at all, filed precisely at
PyMCU/PyMCU#447.
Timer.init's three MicroPython overloads are keyword-only bydefinition (
*, mode=..., period=None, ...) -- there is no positional call shape for them tofall back to -- so splitting it is not just imperfect, it makes the method
uncallable the way MicroPython itself always calls it. Reverted to the single
merged signature this repo already had (
init(period=0, mode=1, callback=0, prescaler=0, freq=0)), which is the only shape here that both compiles and stays callable by keyword.This stays a permanent, structural deviation, not a "someone should decide" one: the split
this issue originally asked for is real work whenever PyMCU/PyMCU#447 lands, not before.
Original report
MicroPython's
machine.Timer.initis declared inmicropython-rp2-stubsas threekeyword-only overloads that share
modeandcallbackbut each accept exactly one ofperiod=,freq=ortick_hz=:This layer's
Timer.init(period=0, mode=1, callback=0, prescaler=0, freq=0)mergesperiodand
freqinto one call (deliberately: a caller can reach either unit), adds aprescaler=low-level override the stub has no equivalent for, and takes all five aspositional-or-keyword rather than keyword-only.
Repo choice
Blocked on PyMCU/PyMCU#447 (keyword arguments refused whenever a name has more than one
@inlineoverload). Once that lands, splittinginitinto matching keyword-onlyperiod=/freq=/tick_hz=overloads (losing the "set both" convenience, gainingtick_hz=-- buildable on this chip as "pick whichever of the four AVR prescalers puts thecounting rate closest to what was asked, fire the callback on overflow") is
src/pymcu_micropython/machine.py-only work; the design above is written out and ready topaste back in once #447 is fixed.