.. This document was generated by tools/gen-cpydiff.py Builtin types ============= Generated Tue 19 Mar 2024 04:26:39 UTC Exception --------- .. _cpydiff_types_exception_attrs: All exceptions have readable ``value`` and ``errno`` attributes, not just ``StopIteration`` and ``OSError``. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** MicroPython is optimised to reduce code size. **Workaround:** Only use ``value`` on ``StopIteration`` exceptions, and ``errno`` on ``OSError`` exceptions. Do not use or rely on these attributes on other exceptions. Sample code:: e = Exception(1) print(e.value) print(e.errno) +-----------------------------------------------------------------+-------------+ | CPy output: | uPy output: | +-----------------------------------------------------------------+-------------+ | :: | :: | | | | | Traceback (most recent call last): | 1 | | File "", line 8, in | 1 | | AttributeError: 'Exception' object has no attribute 'value' | | +-----------------------------------------------------------------+-------------+ .. _cpydiff_types_exception_chaining: Exception chaining not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sample code:: try: raise TypeError except TypeError: raise ValueError +-------------------------------------------------------------------------+--------------------------------------------+ | CPy output: | uPy output: | +-------------------------------------------------------------------------+--------------------------------------------+ | :: | :: | | | | | Traceback (most recent call last): | Traceback (most recent call last): | | File "", line 8, in | File "", line 10, in | | TypeError | ValueError: | | | | | During handling of the above exception, another exception occurred: | | | | | | Traceback (most recent call last): | | | File "", line 10, in | | | ValueError | | +-------------------------------------------------------------------------+--------------------------------------------+ .. _cpydiff_types_exception_instancevar: User-defined attributes for builtin exceptions are not supported ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** MicroPython is highly optimized for memory usage. **Workaround:** Use user-defined exception subclasses. Sample code:: e = Exception() e.x = 0 print(e.x) +-------------+-------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+-------------------------------------------------------------+ | :: | :: | | | | | 0 | Traceback (most recent call last): | | | File "", line 8, in | | | AttributeError: 'Exception' object has no attribute 'x' | +-------------+-------------------------------------------------------------+ .. _cpydiff_types_exception_loops: Exception in while loop condition may have unexpected line number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** Condition checks are optimized to happen at the end of loop body, and that line number is reported. Sample code:: l = ["-foo", "-bar"] i = 0 while l[i][0] == "-": print("iter") i += 1 +--------------------------------------------+--------------------------------------------+ | CPy output: | uPy output: | +--------------------------------------------+--------------------------------------------+ | :: | :: | | | | | iter | iter | | iter | iter | | Traceback (most recent call last): | Traceback (most recent call last): | | File "", line 10, in | File "", line 12, in | | IndexError: list index out of range | IndexError: list index out of range | +--------------------------------------------+--------------------------------------------+ .. _cpydiff_types_exception_subclassinit: Exception.__init__ method does not exist. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** Subclassing native classes is not fully supported in MicroPython. **Workaround:** Call using ``super()`` instead:: class A(Exception): def __init__(self): super().__init__() Sample code:: class A(Exception): def __init__(self): Exception.__init__(self) a = A() +-------------+-------------------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+-------------------------------------------------------------------------+ | | :: | | | | | | Traceback (most recent call last): | | | File "", line 18, in | | | File "", line 15, in __init__ | | | AttributeError: type object 'Exception' has no attribute '__init__' | +-------------+-------------------------------------------------------------------------+ bytearray --------- .. _cpydiff_types_bytearray_sliceassign: Array slice assignment with unsupported RHS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sample code:: b = bytearray(4) b[0:1] = [1, 2] print(b) +----------------------------------------+-------------------------------------------------------------+ | CPy output: | uPy output: | +----------------------------------------+-------------------------------------------------------------+ | :: | :: | | | | | bytearray(b'\x01\x02\x00\x00\x00') | Traceback (most recent call last): | | | File "", line 8, in | | | NotImplementedError: array/bytes required on right side | +----------------------------------------+-------------------------------------------------------------+ bytes ----- .. _cpydiff_types_bytes_format: bytes objects support .format() method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** MicroPython strives to be a more regular implementation, so if both `str` and `bytes` support ``__mod__()`` (the % operator), it makes sense to support ``format()`` for both too. Support for ``__mod__`` can also be compiled out, which leaves only ``format()`` for bytes formatting. **Workaround:** If you are interested in CPython compatibility, don't use ``.format()`` on bytes objects. Sample code:: print(b"{}".format(1)) +--------------------------------------------------------------+-------------+ | CPy output: | uPy output: | +--------------------------------------------------------------+-------------+ | :: | :: | | | | | Traceback (most recent call last): | b'1' | | File "", line 7, in | | | AttributeError: 'bytes' object has no attribute 'format' | | +--------------------------------------------------------------+-------------+ .. _cpydiff_types_bytes_keywords: bytes() with keywords not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Workaround:** Pass the encoding as a positional parameter, e.g. ``print(bytes('abc', 'utf-8'))`` Sample code:: print(bytes("abc", encoding="utf8")) +-------------+----------------------------------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+----------------------------------------------------------------------------------------+ | :: | :: | | | | | b'abc' | Traceback (most recent call last): | | | File "", line 7, in | | | NotImplementedError: keyword argument(s) not implemented - use normal args instead | +-------------+----------------------------------------------------------------------------------------+ .. _cpydiff_types_bytes_subscrstep: Bytes subscription with step != 1 not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** MicroPython is highly optimized for memory usage. **Workaround:** Use explicit loop for this very rare operation. Sample code:: print(b"123"[0:3:2]) +-------------+---------------------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+---------------------------------------------------------------------------+ | :: | :: | | | | | b'13' | Traceback (most recent call last): | | | File "", line 7, in | | | NotImplementedError: only slices with step=1 (aka None) are supported | +-------------+---------------------------------------------------------------------------+ dict ---- .. _cpydiff_types_dict_keys_set: Dictionary keys view does not behave as a set. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** Not implemented. **Workaround:** Explicitly convert keys to a set before using set operations. Sample code:: print({1: 2, 3: 4}.keys() & {1}) +-------------+------------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+------------------------------------------------------------------+ | :: | :: | | | | | {1} | Traceback (most recent call last): | | | File "", line 7, in | | | TypeError: unsupported types for __and__: 'dict_view', 'set' | +-------------+------------------------------------------------------------------+ float ----- .. _cpydiff_types_float_implicit_conversion: uPy allows implicit conversion of objects in maths operations while CPython does not. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Workaround:** Objects should be wrapped in ``float(obj)`` for compatibility with CPython. Sample code:: class Test: def __float__(self): return 0.5 print(2.0 * Test()) +----------------------------------------------------------------------+-------------+ | CPy output: | uPy output: | +----------------------------------------------------------------------+-------------+ | :: | :: | | | | | Traceback (most recent call last): | 1.0 | | File "", line 14, in | | | TypeError: unsupported operand type(s) for *: 'float' and 'Test' | | +----------------------------------------------------------------------+-------------+ .. _cpydiff_types_float_rounding: uPy and CPython outputs formats may differ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sample code:: print("%.1g" % -9.9) +-------------+-------------+ | CPy output: | uPy output: | +-------------+-------------+ | :: | :: | | | | | -1e+01 | -10 | +-------------+-------------+ int --- .. _cpydiff_types_int_bit_length: ``bit_length`` method doesn't exist. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** bit_length method is not implemented. **Workaround:** Avoid using this method on MicroPython. Sample code:: x = 255 print("{} is {} bits long.".format(x, x.bit_length())) +-------------------------+----------------------------------------------------------------+ | CPy output: | uPy output: | +-------------------------+----------------------------------------------------------------+ | :: | :: | | | | | 255 is 8 bits long. | Traceback (most recent call last): | | | File "", line 9, in | | | AttributeError: 'int' object has no attribute 'bit_length' | +-------------------------+----------------------------------------------------------------+ .. _cpydiff_types_int_subclassconv: No int conversion for int-derived types available ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Workaround:** Avoid subclassing builtin types unless really needed. Prefer https://en.wikipedia.org/wiki/Composition_over_inheritance . Sample code:: class A(int): __add__ = lambda self, other: A(int(self) + other) a = A(42) print(a + a) +-------------+-------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+-------------------------------------------------------------+ | :: | :: | | | | | 84 | Traceback (most recent call last): | | | File "", line 14, in | | | File "", line 10, in | | | TypeError: unsupported types for __radd__: 'int', 'int' | +-------------+-------------------------------------------------------------+ list ---- .. _cpydiff_types_list_delete_subscrstep: List delete with step != 1 not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Workaround:** Use explicit loop for this rare operation. Sample code:: l = [1, 2, 3, 4] del l[0:4:2] print(l) +-------------+-------------------------------------------+ | CPy output: | uPy output: | +-------------+-------------------------------------------+ | :: | :: | | | | | [2, 4] | Traceback (most recent call last): | | | File "", line 8, in | | | NotImplementedError: | +-------------+-------------------------------------------+ .. _cpydiff_types_list_store_noniter: List slice-store with non-iterable on RHS is not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** RHS is restricted to be a tuple or list **Workaround:** Use ``list()`` on RHS to convert the iterable to a list Sample code:: l = [10, 20] l[0:1] = range(4) print(l) +----------------------+-----------------------------------------------------+ | CPy output: | uPy output: | +----------------------+-----------------------------------------------------+ | :: | :: | | | | | [0, 1, 2, 3, 20] | Traceback (most recent call last): | | | File "", line 8, in | | | TypeError: object 'range' isn't a tuple or list | +----------------------+-----------------------------------------------------+ .. _cpydiff_types_list_store_subscrstep: List store with step != 1 not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Workaround:** Use explicit loop for this rare operation. Sample code:: l = [1, 2, 3, 4] l[0:4:2] = [5, 6] print(l) +------------------+-------------------------------------------+ | CPy output: | uPy output: | +------------------+-------------------------------------------+ | :: | :: | | | | | [5, 2, 6, 4] | Traceback (most recent call last): | | | File "", line 8, in | | | NotImplementedError: | +------------------+-------------------------------------------+ str --- .. _cpydiff_types_str_endswith: Start/end indices such as str.endswith(s, start) not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sample code:: print("abc".endswith("c", 1)) +-------------+--------------------------------------------+ | CPy output: | uPy output: | +-------------+--------------------------------------------+ | :: | :: | | | | | True | Traceback (most recent call last): | | | File "", line 7, in | | | NotImplementedError: start/end indices | +-------------+--------------------------------------------+ .. _cpydiff_types_str_formatsubscr: Attributes/subscr not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sample code:: print("{a[0]}".format(a=[1, 2])) +-------------+---------------------------------------------------+ | CPy output: | uPy output: | +-------------+---------------------------------------------------+ | :: | :: | | | | | 1 | Traceback (most recent call last): | | | File "", line 7, in | | | NotImplementedError: attributes not supported | +-------------+---------------------------------------------------+ .. _cpydiff_types_str_keywords: str(...) with keywords not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Workaround:** Input the encoding format directly. eg ``print(bytes('abc', 'utf-8'))`` Sample code:: print(str(b"abc", encoding="utf8")) +-------------+----------------------------------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+----------------------------------------------------------------------------------------+ | :: | :: | | | | | abc | Traceback (most recent call last): | | | File "", line 7, in | | | NotImplementedError: keyword argument(s) not implemented - use normal args instead | +-------------+----------------------------------------------------------------------------------------+ .. _cpydiff_types_str_ljust_rjust: str.ljust() and str.rjust() not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **Cause:** MicroPython is highly optimized for memory usage. Easy workarounds available. **Workaround:** Instead of ``s.ljust(10)`` use ``"%-10s" % s``, instead of ``s.rjust(10)`` use ``"% 10s" % s``. Alternatively, ``"{:<10}".format(s)`` or ``"{:>10}".format(s)``. Sample code:: print("abc".ljust(10)) +-------------+-----------------------------------------------------------+ | CPy output: | uPy output: | +-------------+-----------------------------------------------------------+ | :: | :: | | | | | abc | Traceback (most recent call last): | | | File "", line 7, in | | | AttributeError: 'str' object has no attribute 'ljust' | +-------------+-----------------------------------------------------------+ .. _cpydiff_types_str_rsplitnone: None as first argument for rsplit such as str.rsplit(None, n) not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sample code:: print("a a a".rsplit(None, 1)) +------------------+-------------------------------------------+ | CPy output: | uPy output: | +------------------+-------------------------------------------+ | :: | :: | | | | | ['a a', 'a'] | Traceback (most recent call last): | | | File "", line 7, in | | | NotImplementedError: rsplit(None,n) | +------------------+-------------------------------------------+ .. _cpydiff_types_str_subscrstep: Subscript with step != 1 is not yet implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sample code:: print("abcdefghi"[0:9:2]) +-------------+---------------------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+---------------------------------------------------------------------------+ | :: | :: | | | | | acegi | Traceback (most recent call last): | | | File "", line 7, in | | | NotImplementedError: only slices with step=1 (aka None) are supported | +-------------+---------------------------------------------------------------------------+ tuple ----- .. _cpydiff_types_tuple_subscrstep: Tuple load with step != 1 not implemented ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sample code:: print((1, 2, 3, 4)[0:4:2]) +-------------+---------------------------------------------------------------------------+ | CPy output: | uPy output: | +-------------+---------------------------------------------------------------------------+ | :: | :: | | | | | (1, 3) | Traceback (most recent call last): | | | File "", line 7, in | | | NotImplementedError: only slices with step=1 (aka None) are supported | +-------------+---------------------------------------------------------------------------+