Repository navigation
Discussion of Python 3.5 support #1329
Description
MicroPython aims to implement the Python 3.x "standard". At the moment x is currently 4, ie we try to be compatible with CPython 3.4. It's new territory as to what to do when CPython evolves to larger version numbers. I would say we should try to follow the changes and implement them when possible/sensible.
Python 3.5 had a feature freeze on 24 May 2015 and is scheduled for final release on 13 September 2015. This ticket here is about discussing if, what and how we should upgrade uPy to version 3.5 of the language. It may be that some issues need to break off into separate tickets and that's fine but we should link to them from this one.
The PEP discussing the new features in 3.5: https://www.python.org/dev/peps/pep-0478/
A more friendly overview in the docs: https://docs.python.org/3.5/whatsnew/3.5.html
Below is a list of finalised/accepted PEPs for 3.5 grouped into their impact to MicroPython.
Extensions to the syntax:
- PEP 448 - additional unpacking generalizations; see Additional function arg unpacking (PEP 448) #5807
- PEP 465 - a new matrix multiplication operator; done in 2069c56
- PEP 492 - coroutines with async and await syntax
Extensions and changes to the runtime:
- PEP 461 - %-formatting for binary strings - tentatively done
- PEP 475 - retrying system calls that fail with EINTR - done in 9418611
- PEP 479 - change StopIteration handling inside generators - done in 3f6ffe0
Standard library changes:
- PEP 471 - os.scandir()
- PEP 485 - math.isclose(), a function for testing approximate equality - done in af5c998
Miscellaneous changes that are not relevant to MicroPython:
- PEP 441 - improved Python zip application support
- PEP 486 - make the Python Launcher aware of virtual environments
- PEP 484 - type hints (advisory only)
- PEP 488 - elimination of PYO files
- PEP 489 - redesigning extension module loading
- Added the
"namereplace"error handlers. The"backslashreplace"error handlers now work with decoding and translating. - Property docstrings are now writable. This is especially useful for collections.namedtuple() docstrings.
- Circular imports involving relative imports are now supported.
Changes to MicroPython built-in modules
- asyncio (many, may need another ticket)
- cmath - A new function
isclose()provides a way to test for approximate equality.
- collections
- The
OrderedDictclass is now implemented in C, which makes it 4 to 100 times faster. -
OrderedDict.items(),OrderedDict.keys(),OrderedDict.values()views now supportreversed()iteration. - The deque class now defines
index(),insert(), andcopy(), and supports the + and * operators. - Docstrings produced by
namedtuple()can now be updated. - The
UserStringclass now implements the__getnewargs__(),__rmod__(),casefold(),format_map(),isprintable(), andmaketrans()methods to match the corresponding methods ofstr.
- The
- heapq - Element comparison in
merge()can now be customized by passing a key function in a new optional key keyword argument, and a new optionalreversekeyword argument can be used to reverse element comparison - io - A new
BufferedIOBase.readinto1()method, that uses at most one call to the underlying raw stream'sRawIOBase.read()orRawIOBase.readinto()methods. - json - JSON decoder now raises
JSONDecodeErrorinstead ofValueErrorto provide better context information about the error.
- math
- Two new constants have been added to the math module:
infandnan. - A new function
isclose()provides a way to test for approximate equality. - A new
gcd()function has been added. Thefractions.gcd()function is now deprecated.
- Two new constants have been added to the math module:
- os
- The new
scandir()function returning an iterator ofDirEntryobjects has been added. - The
urandom()function now uses thegetrandom()syscall on Linux 3.17 or newer, and getentropy() on OpenBSD 5.6 and newer, removing the need to use /dev/urandom and avoiding failures due to potential file descriptor exhaustion. - New
get_blocking()andset_blocking()functions allow getting and setting a file descriptor's blocking mode (O_NONBLOCK.) - There is a new
os.path.commonpath()function returning the longest common sub-path of each passed pathname.
- The new
- re
- References and conditional references to groups with fixed length are now allowed in lookbehind assertions.
- The number of capturing groups in regular expressions is no longer limited to 100.
- The
sub()andsubn()functions now replace unmatched groups with empty strings instead of raising an exception. - The
re.errorexceptions have new attributes,msg,pattern,pos,lineno, andcolno, that provide better context information about the error
- socket
- Functions with timeouts now use a monotonic clock, instead of a system clock.
- A new
socket.sendfile()method allows sending a file over a socket by using the high-performanceos.sendfile()function on UNIX, resulting in uploads being from 2 to 3 times faster than when using plainsocket.send(). - The
socket.sendall()method no longer resets the socket timeout every time bytes are received or sent. The socket timeout is now the maximum total duration to send all data. - The backlog argument of the
socket.listen()method is now optional. By default it is set to SOMAXCONN or to 128, whichever is less.
- ssl
- Memory BIO Support
- Application-Layer Protocol Negotiation Support
- There is a new
SSLSocket.version()method to query the actual protocol version in use. - The
SSLSocketclass now implements aSSLSocket.sendfile()method. - The
SSLSocket.send()method now raises either thessl.SSLWantReadErrororssl.SSLWantWriteErrorexception on a non-blocking socket if the operation would block. Previously, it would return 0. - The
cert_time_to_seconds()function now interprets the input time as UTC and not as local time, per RFC 5280. Additionally, the return value is always an int. - New
SSLObject.shared_ciphers()andSSLSocket.shared_ciphers()methods return the list of ciphers sent by the client during the handshake. - The
SSLSocket.do_handshake(),SSLSocket.read(),SSLSocket.shutdown(), andSSLSocket.write()methods of theSSLSocketclass no longer reset the socket timeout every time bytes are received or sent. - The
match_hostname()function now supports matching of IP addresses.
- sys
- A new
set_coroutine_wrapper()function allows setting a global hook that will be called whenever a coroutine object is created by an async def function. A correspondingget_coroutine_wrapper()can be used to obtain a currently set wrapper. - A new
is_finalizing()function can be used to check if the Python interpreter is shutting down.
- A new
- time The
monotonic()function is now always available.
(Changes to non-built-in modules will need to be documented elsewhere.)
The above list should be edited if/when progress is made on a given feature.
Activity
pfalcon commentedon Jun 15, 2015
We "by definition" have "%-formatting for binary strings", I'm not sure however what details PEP 461 may have.
pfalcon commentedon Jun 15, 2015
is potentially interesting, because it's boring to handle it in each app, and actually nobody handles it in each app, unless faces issues, and then it's likely users, and not an author. So, doing that PEP kinda saves from such situations. But then again it may be just adding more bloat than necessary. Need to read PEP, and actually, all PEPs (in detail, again, or at all).
dpgeorge commentedon Jun 15, 2015
We are missing: "%b" for interpolating bytes objects, "%a" for repr of bytes, "%c" in uPy truncates to 7-bit char but should be full 8-bit char, and we don't support % operator on bytearray object.
roger- commentedon Jun 19, 2015
Type hints sound like they could be useful.
Personally I'd like to see unpacking generalizations and async/await support.
dpgeorge commentedon Jun 20, 2015
I just had a read of that PEP and it looks like it might be some effort, and a decent increase in code size, to implement that. It allows things like
lst = [*a, b, *c]andfoo(*a, b, *c).pfalcon commentedon Jul 19, 2015
Running uPy testsuite against CPython3.5b3 produces few warnings/errors.
dpgeorge commentedon Jul 20, 2015
A few too many, or few enough to easily fix them? Do you have any examples of failures?
pfalcon commentedon Jul 20, 2015
I built 3.5b3, and that managed to install itself as system-wide python3, so I scratched ny head for a bit while testsuite fails. As soon as I figured that out, I switched it back and didn't look back, and don't think it's a priority before 3.5 release. So, just FYI ;-).
pfalcon commentedon Sep 13, 2015
3.5.0 was released today.
dpgeorge commentedon Oct 2, 2015
CPy 3.5 is now distributed with Arch Linux so that's what I'll be using. There are only a few errors (mostly related to new , * syntax).
dpgeorge commentedon Oct 2, 2015
@pfalcon you'll be pleased to know that regex splitting with an empty regex is on track for deprecation. Running tests/extmod/ure_split.py with CPy 3.5 gives a FutureWarning for these cases. So this means the dirty magic is hopefully gone!
dpgeorge commentedon Oct 2, 2015
Tests now pass with CPy 3.5; see 34f26ea.
dpgeorge commentedon Oct 8, 2015
Evaluation order of dictionary key/value pairs in CPy 3.5 has changed. Key is now evaluated first in a dict literal.
njouanin commentedon Oct 27, 2015
Hi,
Is Python 3.5 coroutine syntax (await / async) supported be uPy ?
dpgeorge commentedon Nov 2, 2015
@njouanin await/async syntax is not (yet) supported. But the underlying "yield from" functionality is.
19 remaining items
peterhinch commentedon Jul 3, 2019
If it's not too problematic PEP448 would be useful. There is evident demand: I've already had to explain to users that it's not yet supported.
I appreciate that PEP572 is Python 3.8. My interest is on the theory that it might improve performance and/or code size e.g. in comprehensions and lambdas.
spacemanspiff2007 commentedon Jul 3, 2019
Same here! It'll come anyway so it might be as well available in time with the release of 3.8
nickovs commentedon Jul 6, 2019
Notwithstanding the fact that
numpyis very unlikely to get ported to MicroPython, it might we worth implementing PEP 465 anyway since (a) it would probably be easy and small, (b) it would provide compatibility and (c) having a spare infix operator lying around is often handy.FWIW, I've have ended up implementing a tiny linear algebra system on uPy (they are handy for optimising some dynamic systems and the ESP32 with SPIRAM has the space and horsepower to cope) and having the
@and@=operators would have been quite helpful for improving readability and compactness.(I also note that MicroPython already supports
Ellipsisand it never gets used in any of the standard libraries, so there is a precedent for implementing language features that have no built-in use cases.)jimmo commentedon Jul 6, 2019
@nickovs I have already implemented this in #4740
(I am working on porting a useful subset of numpy, based on ublas/lapack like regular numpy).
dlech commentedon Jan 23, 2020
PEP 465 can be crossed off of the list now
dlech commentedon Mar 5, 2020
proposed PEP 475 implementation in #5723
dlech commentedon Mar 26, 2020
Should PEP 485 be crossed off of the list? #4894
dpgeorge commentedon Mar 27, 2020
Yes, list is now updated for PEP 475 and 485.
dlech commentedon Mar 31, 2022
Now that #5807 has been merged, we have partial support for PEP 448, namely:
The remaining bit that is not implemented is:
I think we could leverage the partial implementation to easily implement the rest. It could work like this:
We need two intrinsic functions that basically look like this:
If the compiler encounters
*in a tuple, list or set display or**in a dictionary display, then it "rewrites" the code like this:dpgeorge commentedon Apr 1, 2022
That's interesting, and definitely simple... but I'm not sure how to implement intrinsic functions (efficiently).
I wonder how CPython does it, do they create a comprehension function to build the tuple/list/set/dict? If so that would alter the semantics.
dlech commentedon Apr 1, 2022
I looked at the patch that implements it and they just added new opcodes for each case:
dpgeorge commentedon Apr 2, 2022
I guess we could do that as well.
I think this feature is rarely used (??) so if MicroPython implements it I would say it should be done as "cheaply" as possible, ie with a minimum of firmware size. Maybe adding new opcodes is the smallest way to implement it, or maybe it's some other way.
It looks like the hardest thing (biggest increase in code size) would be to change the compiler to detect these cases. So investigations would be best to start there.