post by "adafruit" account

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
User avatar
Posts: 9
Joined: Sun Oct 30, 2016 11:56 pm
Location: NYC

post by "adafruit" account

Post by adafruit » Sat Dec 01, 2018 9:11 pm

pfalcon wrote:
Sat Dec 01, 2018 8:28 pm have rather strange definition of "CPython compatibility". CPython compatibility means being able to run CPython applications on SomethingPython, not the other way around. So, you pretend and misguide that you have "CPython compatibility", whereas actually you complicate it by grabbing namespace which doesn't belong to you. Or put it another way, what you do is as good as teaching kids that the value of Pi is 3.
CPython compatibilities goes both ways. MicroPython already does a great job of "CPython code runs well on Microcontrollers". Other than a few exceptions, like list slices and integer sizes, the huge amount of the core Python functionality runs the same, which is what makes it so great.

Bi-directional compatibility means that that code from 'small' microcontrollers like ATSAMD or nRF52 or ESP32 also runs on 'larger microcontrollers', like Raspberry Pi or Orange Board or Mac/Windows, with Python 3.

You make a really good point about the value of Pi. In CPython, math.pi is 3.141592653589793

On the small CircuitPython board in front of me, it's 3.14159 because we don't have double floats.

Both are wrong, Pi is neither number. But CircuitPython's version of math.pi is a subset of CPython.

There are also some older ports of MicroPython that had no float's at all - and for these, I suppose Pi was 3, but CircuitPython doesn't rename math to math_singleprecision :)

User avatar
Posts: 3367
Joined: Fri Jul 18, 2014 8:01 am
Location: UK

Re: post by "adafruit" account

Post by pythoncoder » Sun Dec 02, 2018 7:29 am

I'm afraid I think Paul is right on this one. If a library is a subset of a CPython library it should have a separate namespace. If you want to write code portable to CPython, use the 'u' subset and write:

Code: Select all

    import uasyncio as asyncio
except ImportError:
    import asyncio
The 'u' libraries are "micro" subsets and hiding the fact serves only to create confusion.
Peter Hinch

Posts: 7
Joined: Mon Jan 16, 2017 3:58 am

Re: post by "adafruit" account

Post by danhalbert » Sun Dec 02, 2018 3:31 pm

(I'm speaking as one of the CircuitPython core devs)

I think both naming schemes have advantages and disadvantages. This describes our naming philosophy:
  • No module aliasing. (uos and utime are not available as os and time respectively.) Instead os, time, and random are CPython compatible.
  • New storage module which manages file system mounts. (Functionality from uos in MicroPython.)
  • Modules with a CPython counterpart, such as time, os and random, are strict subsets of their CPython version. Therefore, code from CircuitPython is runnable on CPython but not necessarily the reverse.
  • tick count is available as time.monotonic()
In MicroPython, the `u` modules are not necessarily strict subsets. They may include additional non-CPython functionality. `utime` is a good example: it has a number of extra functions that are not in `time`, such as, say, `sleep_ms()`. So if you `import utime as time`, functions will show up that are not in CPython `time`. Our philosophy has been to move the extra functionality into another non-CPython module name. As mentioned above, "code from CircuitPython is runnable on CPython but not necessarily the reverse.".

This paragraph from the MicroPython doc is of note: ... -libraries:
On some embedded platforms, where it may be cumbersome to add Python-level wrapper modules to achieve naming compatibility with CPython, micro-modules are available both by their u-name, and also by their non-u-name. The non-u-name can be overridden by a file of that name in your library path (sys.path). For example, import json will first search for a file (or package directory json) and load that module if it is found. If nothing is found, it will fallback to loading the built-in ujson module.
I think our strict subsetting is in some ways like upward compatibility from Python 3.x to 3.y (x < y). There are dilemmas either way. For example, `time.monotonic _ns()` was added to CPython recently. We added it to our `time` module , except for ports that don't have longints for space reasons. So code for those ports can't use that function, unfortunately. But we have decided that all ports have floats, so we can always do `time.sleep()`.

Another reason for our choice is that we've written wrapper libraries for Raspberry Pi and similar platforms with pin I/O support. The wrappers re-implement (in CPython) the native pin I/O functionality (like I2C) provided in CircuitPython. This allows the existing CircuitPython libraries for our breakout boards, etc., to run without change on RPi and the like. And the user code that calls those libraries can also be run without change, without having to do module name aliasing like `import uxyz as xyz`.

MicroPython and CircuitPython have different but overlapping goals and audiences. MPy has provided a fantastic base for expanding physical computing to a larger, non-professional audience. We are extremely grateful to Damien and the rest of the MPy contributors. I usually explain that CPy is a "friendly fork". We merge from upstream regularly, and try to contribute back as appropriate.

User avatar
Posts: 3153
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada

Re: post by "adafruit" account

Post by dhylands » Sun Dec 02, 2018 5:14 pm

I guess my take on the u versus non-u is that if you call the builtin time module 'time', then there is no way to extend it and still have it called time.

The u modules were created with softlinks so that the only code that should ever have to import utime is the module thats extending the utime functionality. All other places you should be able to just 'import time'

Post Reply