Skip to content

Commit 0230cc7

Browse files
committed
tooling: Fix stdlib stub override with self-contained time.pyi and include.
1 parent fa56bc7 commit 0230cc7

2 files changed

Lines changed: 23 additions & 307 deletions

File tree

pyrightconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
"pythonVersion": "3.7",
33
"pythonPlatform": "All",
44
"typeCheckingMode": "basic",
5+
"include": ["lib", "typings", "tests"],
56
"extraPaths": ["lib", "typings"],
67
"stubPath": "typings",
7-
"typeshedPath": "typings",
88
"exclude": [
99
".build",
1010
"node_modules",

typings/stdlib/time.pyi

Lines changed: 22 additions & 306 deletions
Original file line numberDiff line numberDiff line change
@@ -1,306 +1,22 @@
1-
"""
2-
Time related functions.
3-
4-
MicroPython module: https://docs.micropython.org/en/v1.27.0/library/time.html
5-
6-
CPython module: :mod:`python:time` https://docs.python.org/3/library/time.html .
7-
8-
The ``time`` module provides functions for getting the current time and date,
9-
measuring time intervals, and for delays.
10-
11-
**Time Epoch**: The unix, windows, webassembly, alif, mimxrt and rp2 ports
12-
use the standard for POSIX systems epoch of 1970-01-01 00:00:00 UTC.
13-
The other embedded ports use an epoch of 2000-01-01 00:00:00 UTC.
14-
Epoch year may be determined with ``gmtime(0)[0]``.
15-
16-
**Maintaining actual calendar date/time**: This requires a
17-
Real Time Clock (RTC). On systems with underlying OS (including some
18-
RTOS), an RTC may be implicit. Setting and maintaining actual calendar
19-
time is responsibility of OS/RTOS and is done outside of MicroPython,
20-
it just uses OS API to query date/time. On baremetal ports however
21-
system time depends on ``machine.RTC()`` object. The current calendar time
22-
may be set using ``machine.RTC().datetime(tuple)`` function, and maintained
23-
by following means:
24-
25-
* By a backup battery (which may be an additional, optional component for
26-
a particular board).
27-
* Using networked time protocol (requires setup by a port/user).
28-
* Set manually by a user on each power-up (many boards then maintain
29-
RTC time across hard resets, though some may require setting it again
30-
in such case).
31-
32-
If actual calendar time is not maintained with a system/MicroPython RTC,
33-
functions below which require reference to current absolute time may
34-
behave not as expected.
35-
36-
---
37-
Module: 'time' on micropython-v1.27.0-stm32-PYBV11-NETWORK
38-
"""
39-
40-
# MCU: {'variant': 'NETWORK', 'build': '', 'arch': 'armv7emsp', 'port': 'stm32', 'board': 'PYBV11', 'board_id': 'PYBV11-NETWORK', 'mpy': 'v6.3', 'ver': '1.27.0', 'family': 'micropython', 'cpu': 'STM32F405RG', 'version': '1.27.0'}
41-
# Stubber: v1.26.4
42-
from __future__ import annotations
43-
from _typeshed import Incomplete
44-
from _mpy_shed import _TimeTuple
45-
from typing import Tuple
46-
from typing_extensions import Awaitable, TypeAlias, TypeVar
47-
48-
_TicksMs: TypeAlias = int
49-
_TicksUs: TypeAlias = int
50-
_TicksCPU: TypeAlias = int
51-
_Ticks = TypeVar("_Ticks", _TicksMs, _TicksUs, _TicksCPU, int)
52-
53-
def ticks_diff(ticks1: _Ticks, ticks2: _Ticks, /) -> int:
54-
"""
55-
Measure ticks difference between values returned from `ticks_ms()`, `ticks_us()`,
56-
or `ticks_cpu()` functions, as a signed value which may wrap around.
57-
58-
The argument order is the same as for subtraction
59-
operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``.
60-
However, values returned by `ticks_ms()`, etc. functions may wrap around, so
61-
directly using subtraction on them will produce incorrect result. That is why
62-
`ticks_diff()` is needed, it implements modular (or more specifically, ring)
63-
arithmetic to produce correct result even for wrap-around values (as long as they not
64-
too distant in between, see below). The function returns **signed** value in the range
65-
[*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for
66-
two's-complement signed binary integers). If the result is negative, it means that
67-
*ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that
68-
*ticks1* occurred after *ticks2*. This holds **only** if *ticks1* and *ticks2*
69-
are apart from each other for no more than *TICKS_PERIOD/2-1* ticks. If that does
70-
not hold, incorrect result will be returned. Specifically, if two tick values are
71-
apart for *TICKS_PERIOD/2-1* ticks, that value will be returned by the function.
72-
However, if *TICKS_PERIOD/2* of real-time ticks has passed between them, the
73-
function will return *-TICKS_PERIOD/2* instead, i.e. result value will wrap around
74-
to the negative range of possible values.
75-
76-
Informal rationale of the constraints above: Suppose you are locked in a room with no
77-
means to monitor passing of time except a standard 12-notch clock. Then if you look at
78-
dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a
79-
long sleep), then once you finally look again, it may seem to you that only 1 hour
80-
has passed. To avoid this mistake, just look at the clock regularly. Your application
81-
should do the same. "Too long sleep" metaphor also maps directly to application
82-
behaviour: don't let your application run any single task for too long. Run tasks
83-
in steps, and do time-keeping in between.
84-
85-
`ticks_diff()` is designed to accommodate various usage patterns, among them:
86-
87-
* Polling with timeout. In this case, the order of events is known, and you will deal
88-
only with positive results of `ticks_diff()`::
89-
90-
# Wait for GPIO pin to be asserted, but at most 500us
91-
start = time.ticks_us()
92-
while pin.value() == 0:
93-
if time.ticks_diff(time.ticks_us(), start) > 500:
94-
raise TimeoutError
95-
96-
* Scheduling events. In this case, `ticks_diff()` result may be negative
97-
if an event is overdue::
98-
99-
# This code snippet is not optimized
100-
now = time.ticks_ms()
101-
scheduled_time = task.scheduled_time()
102-
if ticks_diff(scheduled_time, now) > 0:
103-
print("Too early, let's nap")
104-
sleep_ms(ticks_diff(scheduled_time, now))
105-
task.run()
106-
elif ticks_diff(scheduled_time, now) == 0:
107-
print("Right at time!")
108-
task.run()
109-
elif ticks_diff(scheduled_time, now) < 0:
110-
print("Oops, running late, tell task to run faster!")
111-
task.run(run_faster=true)
112-
113-
Note: Do not pass `time()` values to `ticks_diff()`, you should use
114-
normal mathematical operations on them. But note that `time()` may (and will)
115-
also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem .
116-
"""
117-
...
118-
119-
def ticks_add(ticks: _Ticks, delta: int, /) -> _Ticks:
120-
"""
121-
Offset ticks value by a given number, which can be either positive or negative.
122-
Given a *ticks* value, this function allows to calculate ticks value *delta*
123-
ticks before or after it, following modular-arithmetic definition of tick values
124-
(see `ticks_ms()` above). *ticks* parameter must be a direct result of call
125-
to `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions (or from previous
126-
call to `ticks_add()`). However, *delta* can be an arbitrary integer number
127-
or numeric expression. `ticks_add()` is useful for calculating deadlines for
128-
events/tasks. (Note: you must use `ticks_diff()` function to work with
129-
deadlines.)
130-
131-
Examples::
132-
133-
# Find out what ticks value there was 100ms ago
134-
print(ticks_add(time.ticks_ms(), -100))
135-
136-
# Calculate deadline for operation and test for it
137-
deadline = ticks_add(time.ticks_ms(), 200)
138-
while ticks_diff(deadline, time.ticks_ms()) > 0:
139-
do_a_little_of_something()
140-
141-
# Find out TICKS_MAX used by this port
142-
print(ticks_add(0, -1))
143-
"""
144-
...
145-
146-
def ticks_cpu() -> _TicksCPU:
147-
"""
148-
Similar to `ticks_ms()` and `ticks_us()`, but with the highest possible resolution
149-
in the system. This is usually CPU clocks, and that's why the function is named that
150-
way. But it doesn't have to be a CPU clock, some other timing source available in a
151-
system (e.g. high-resolution timer) can be used instead. The exact timing unit
152-
(resolution) of this function is not specified on ``time`` module level, but
153-
documentation for a specific port may provide more specific information. This
154-
function is intended for very fine benchmarking or very tight real-time loops.
155-
Avoid using it in portable code.
156-
157-
Availability: Not every port implements this function.
158-
"""
159-
...
160-
161-
def time() -> int:
162-
"""
163-
Returns the number of seconds, as an integer, since the Epoch, assuming that
164-
underlying RTC is set and maintained as described above. If an RTC is not set, this
165-
function returns number of seconds since a port-specific reference point in time (for
166-
embedded boards without a battery-backed RTC, usually since power up or reset). If you
167-
want to develop portable MicroPython application, you should not rely on this function
168-
to provide higher than second precision. If you need higher precision, absolute
169-
timestamps, use `time_ns()`. If relative times are acceptable then use the
170-
`ticks_ms()` and `ticks_us()` functions. If you need calendar time, `gmtime()` or
171-
`localtime()` without an argument is a better choice.
172-
173-
Admonition:Difference to CPython
174-
:class: attention
175-
176-
In CPython, this function returns number of
177-
seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point,
178-
usually having microsecond precision. With MicroPython, only Unix port
179-
uses the same Epoch, and if floating-point precision allows,
180-
returns sub-second precision. Embedded hardware usually doesn't have
181-
floating-point precision to represent both long time ranges and subsecond
182-
precision, so they use integer value with second precision. Some embedded
183-
hardware also lacks battery-powered RTC, so returns number of seconds
184-
since last power-up or from other relative, hardware-specific point
185-
(e.g. reset).
186-
"""
187-
...
188-
189-
def ticks_ms() -> int:
190-
"""
191-
Returns an increasing millisecond counter with an arbitrary reference point, that
192-
wraps around after some value.
193-
194-
The wrap-around value is not explicitly exposed, but we will
195-
refer to it as *TICKS_MAX* to simplify discussion. Period of the values is
196-
*TICKS_PERIOD = TICKS_MAX + 1*. *TICKS_PERIOD* is guaranteed to be a power of
197-
two, but otherwise may differ from port to port. The same period value is used
198-
for all of `ticks_ms()`, `ticks_us()`, `ticks_cpu()` functions (for
199-
simplicity). Thus, these functions will return a value in range [*0* ..
200-
*TICKS_MAX*], inclusive, total *TICKS_PERIOD* values. Note that only
201-
non-negative values are used. For the most part, you should treat values returned
202-
by these functions as opaque. The only operations available for them are
203-
`ticks_diff()` and `ticks_add()` functions described below.
204-
205-
Note: Performing standard mathematical operations (+, -) or relational
206-
operators (<, <=, >, >=) directly on these value will lead to invalid
207-
result. Performing mathematical operations and then passing their results
208-
as arguments to `ticks_diff()` or `ticks_add()` will also lead to
209-
invalid results from the latter functions.
210-
"""
211-
...
212-
213-
def ticks_us() -> _TicksUs:
214-
"""
215-
Just like `ticks_ms()` above, but in microseconds.
216-
"""
217-
...
218-
219-
def time_ns() -> int:
220-
"""
221-
Similar to `time()` but returns nanoseconds since the Epoch, as an integer (usually
222-
a big integer, so will allocate on the heap).
223-
"""
224-
...
225-
226-
def localtime(secs: int | None = None, /) -> Tuple:
227-
"""
228-
Convert the time *secs* expressed in seconds since the Epoch (see above) into an
229-
8-tuple which contains: ``(year, month, mday, hour, minute, second, weekday, yearday)``
230-
If *secs* is not provided or None, then the current time from the RTC is used.
231-
232-
The `gmtime()` function returns a date-time tuple in UTC, and `localtime()` returns a
233-
date-time tuple in local time.
234-
235-
The format of the entries in the 8-tuple are:
236-
237-
* year includes the century (for example 2014).
238-
* month is 1-12
239-
* mday is 1-31
240-
* hour is 0-23
241-
* minute is 0-59
242-
* second is 0-59
243-
* weekday is 0-6 for Mon-Sun
244-
* yearday is 1-366
245-
"""
246-
...
247-
248-
def sleep_us(us: int, /) -> None:
249-
"""
250-
Delay for given number of microseconds, should be positive or 0.
251-
252-
This function attempts to provide an accurate delay of at least *us*
253-
microseconds, but it may take longer if the system has other higher priority
254-
processing to perform.
255-
"""
256-
...
257-
258-
def gmtime(secs: int | None = None, /) -> Tuple:
259-
"""
260-
Convert the time *secs* expressed in seconds since the Epoch (see above) into an
261-
8-tuple which contains: ``(year, month, mday, hour, minute, second, weekday, yearday)``
262-
If *secs* is not provided or None, then the current time from the RTC is used.
263-
264-
The `gmtime()` function returns a date-time tuple in UTC, and `localtime()` returns a
265-
date-time tuple in local time.
266-
267-
The format of the entries in the 8-tuple are:
268-
269-
* year includes the century (for example 2014).
270-
* month is 1-12
271-
* mday is 1-31
272-
* hour is 0-23
273-
* minute is 0-59
274-
* second is 0-59
275-
* weekday is 0-6 for Mon-Sun
276-
* yearday is 1-366
277-
"""
278-
...
279-
280-
def sleep_ms(ms: int, /) -> None:
281-
"""
282-
Delay for given number of milliseconds, should be positive or 0.
283-
284-
This function will delay for at least the given number of milliseconds, but
285-
may take longer than that if other processing must take place, for example
286-
interrupt handlers or other threads. Passing in 0 for *ms* will still allow
287-
this other processing to occur. Use `sleep_us()` for more precise delays.
288-
"""
289-
...
290-
291-
def mktime(local_time: _TimeTuple, /) -> int:
292-
"""
293-
This is inverse function of localtime. It's argument is a full 8-tuple
294-
which expresses a time as per localtime. It returns an integer which is
295-
the number of seconds since the time epoch.
296-
"""
297-
...
298-
299-
def sleep(seconds: float, /) -> None:
300-
"""
301-
Sleep for the given number of seconds. Some boards may accept *seconds* as a
302-
floating-point number to sleep for a fractional number of seconds. Note that
303-
other boards may not accept a floating-point argument, for compatibility with
304-
them use `sleep_ms()` and `sleep_us()` functions.
305-
"""
306-
...
1+
"""
2+
MicroPython time module stub (self-contained, no external dependencies).
3+
4+
Overrides the CPython typeshed stub to add MicroPython-specific functions
5+
like sleep_ms(), sleep_us(), ticks_ms(), ticks_us(), ticks_cpu(), etc.
6+
"""
7+
8+
from typing import Tuple
9+
10+
def sleep(seconds: float, /) -> None: ...
11+
def sleep_ms(ms: int, /) -> None: ...
12+
def sleep_us(us: int, /) -> None: ...
13+
def ticks_ms() -> int: ...
14+
def ticks_us() -> int: ...
15+
def ticks_cpu() -> int: ...
16+
def ticks_diff(ticks1: int, ticks2: int, /) -> int: ...
17+
def ticks_add(ticks: int, delta: int, /) -> int: ...
18+
def time() -> int: ...
19+
def time_ns() -> int: ...
20+
def localtime(secs: int | None = None, /) -> Tuple: ...
21+
def gmtime(secs: int | None = None, /) -> Tuple: ...
22+
def mktime(local_time: Tuple, /) -> int: ...

0 commit comments

Comments
 (0)