[Microbit-Python] A request for help... fancy designing a Pythonic API that up to 1 million kids would use..?

Mark Shannon mark at hotpy.org
Sat Aug 29 19:25:34 CEST 2015


Hi,

Here is my initial suggestion for an API covering all the TD contents as 
provided by David.

As a general comment, I like to suggest that we shouldn't be too afraid 
to add things to the builtin namespace.
If every program is going to start with:
import microbit
from microbit import pins
from microbit import leds
from microbit import buttons
from microbit import game
from microbit import inputs

then we may as well adds those to the builtins namespace.

So I would suggest that the following objects (which could be modules) 
are added to the builtins at startup:
pins, leds, buttons, game, inputs

I have made fairly extensive use of properties:
img = leds.image ; leds.image = img
rather than img = leds.get_image() ; leds.set_image(img)

Not only do I think this is a more readable, pythonic interface,
it also prevents the following error, when parentheses are forgotten.

 >>> image = led.get_image
 >>> image
<builtin function or method 'leds.get_image'>




So, here is a first draft of the API:

On 29/08/15 13:35, David Whale wrote:
[snip]
>
> MICROBIT.BASIC NAMESPACE
> ------------------------
>
> plot image(leds)
What does this do? There is no image argument.
To display an image on the leds:
leds.image = img

> show number(value, interval)
I'm guessing that this displays a number using the leds. If so, then:
leds.show(number, duration=REASONABLE_DEFAULT)

> show string(text, interval)
Same for text?
leds.show(text, duration=REASONABLE_DEFAULT)

> show animation(leds, interval)
And again?
leds.show(animation, duration=REASONABLE_DEFAULT)

> clear screen()
leds.clear()

> forever(body)
I think "while True:" works quite well for this :)

> pause(ms)
Seems fine as a function in the builtins namespace.

>
>
> MICROBIT.LED NAMESPACE
> ----------------------
>
> plot(x, y)
I like: leds[x,y] = True (or leds[x][y] = True)*
but that may be being too clever, perhaps
leds.set(x, y, val=True) would be better
and/or
leds.turn_on(x,y)

* Note that this would involve creation of an intermediate column object:
col = leds[x] ; col[y] = val

> unplot(x, y)
As above
leds[x,y] = False (or leds[x][y] = False)
or
leds.set(x, y, False)
and/or
leds.turn_off(x, y)

> point(x, y)->bool
val = leds[x,y]
or
val = leds.get(x,y)

> set brightness(value)
leds.brightness = value

> fade in(ms)
leds.fade_in(ms)

> fade out(ms)
leds.fade_out(ms)

> *plot all()
> *screenshot->img
leds.image

> *toggle(x, y)
leds.toggle(x,y)
("leds[x,y] ^= True" is being too clever :) )

> *toggle all()
leds.toggle_all()

> *brightness()->int
val = leds.brightness

>
>
> MICROBIT.CONTROL NAMESPACE
> --------------------------
>
> in background(body)
>
>
> *MICROBIT.EVENTS NAMESPACE
> -------------------------
> {possibly limited to bluetooth only, but they do go on the event bus,
> so there might still be a way to get these to action even without BT}

I don't get what these do, so I'll punt on these for now.
>
> *remote control(event)
> *  event=[play,pause,stop,next track, previous track, rewind, volume up,
> volume down]
> *camera(event)
> *  event=[take photo, start video capture, stop video capture, toggle
> front-rear,
> *  launch photo mode, launch video mode, stop photo mode, stop video mode]
> *alert(event)
> *  event=[display toast, vibrate, play sound, play ringtone, find my phone,
> *  alarm 1, alarm 2, alarm 3, alarm 4, alarm 5, alarm 6,
> *audio recorder(event)
> *  event=[launch, start capture, stop capture, stop]
>
>
> *MICROBIT.GAME NAMESPACE
> -----------------------
> (a standard library already included in the root namespace)
> *add life(lives)
game.lives += lives
> *add score(points)
game.score += points
> *current time()->number
game.current_time() or game.now() which is concise, but a bit less clear.
> *level->number
game.level
> *level up()
game.level += 1
> *life()->number
game.lives
> *remove life(live)
game.lives -= number
> *score()->number
game.score
> *set life(value)
game.lives = value
> *set score(value)
game.score = value
> *start countdown(ms)
game.start_countdown(ms)
>
>
> MICROBIT.INPUT NAMESPACE
> ------------------------
> {note, 'body' is block of code}
>
> button is pressed(name)->bool
buttons.name.is_pressed
> on button pressed(body)
buttons.name.when_pressed(func)
# func can be any callable taking 0 arguments

> acceleration(dimension)->number
inputs.acceleration (as a vector?)
inputs.x_acceleration, etc for components.
(read-only property)

> compass heading()->number
inputs.compass_heading
(read-only property)

> calibrate()
What does this do? Give it a meaningful name.

> running time()->number
inputs.running_time or just inputs.time
(read-only property)

The following should all take a callable.
> on shake(body)
> on fall(body)
> on screen up(body)
> on screen down(body)
> on logo up(body)
> on logo down(body)

> *pin is pressed(name)->bool
pins.name.pressed

> *on pin pressed(body)
pins.name.when_pressed(func)
>

Because the event functions take a callable, they can all be used as 
decorators (probably not for beginners).

>
> MICROBIT.IMAGE NAMESPACE
> ------------------------
>
Is there really only one image?
Surely we want image objects (which only need one bit per LED so can 
tiny) and pass those around.

> create image
img = Image()

> img->clear()
I would like to make images immutable, like numbers and strings. It 
seems much more natural that images are immutable, and it is the leds 
that change.
However, it might be frustrating being unable to modify an image without 
creating a new one.

I think it would be good to provide a way to create a new image pictorially:
img = Image('''.x.x.
                .....
                ..x..
                x...x
                .xxx.''')
Although this isn't very efficient in terms of code size.

We could also provide a "library" of images as each individual image is 
very small:
images.letters['c'], images.digits[4], images.happy_face, 
images.sad_face, images.star, etc.

If images are mutable, then the above would need to create a copy of the 
stored image.

> img->set pixel(x,y,value)
If images are to be mutable, then is making them indexable too obscure?
img[x,y] = value
or
img.set_pixel(x,y, value=True)

> img->pixel(x,y)->bool
img[x,y]
or
img.get_pixel(x,y)

> img->show image(x offset)
leds.image = img

> img->scroll image(x offset per step, interval)
leds.scroll(image, step=1, interval=SENSIBLE_DEFAULT)

> img->width()->int
img.width


It might be worth adding some utility methods on Image class, such as
rotate_left/right/up/down() and invert()

>
>
> MICROBIT.PINS NAMESPACE
> -----------------------
>
> analog read pin(name)->number
pins.name.analog_value

> analog write pin(name, value)
pins.name.analog_value = value

> digital read pin(name)->number
pins.name.digital_value

> digital write pin(name, value)
pins.name.digital_value = value

> -pin is pressed [moved to input namespace]
pins.name.is_pressed

> -on pin pressed [moved to input namespace]
pins.name.when_pressed(func)

>
>
> MICROBIT.MATH NAMESPACE
> -----------------------
>
We already have the math module for most of these

> abs(x)->number
The builtin function abs already exists.

> clamp(min, max, value)->number
Just add this to the math module

Use the standard Python implementation of these.
> max(x, y)->number
> min(x, y)->number
> mod(x, y)->number
> pow(x, y)->number
> random(limit)->number
> *sqrt(x)->number
> *sign(x)->number
>
>
>
> MICROBIT.BITS NAMESPACE
> -----------------------
Rather than this namespace, it would be better to
add an int32 type to the builtin namespace.
In fact, is this necessary at all?
Wouldn't int do the job?

> add int32
> multiply int32
> subtract int32
> and uint32(x, y)->number
> xor uint32(x, y)->number
> -not uint32 [removed]
>
> -create buffer [removed]
> -string to buffer [removed]

> rotate left uint32(x, bits)->number
res = math.rotate_left32(x, bits)

> rotate right uint32(x, bits)->number
res = math.rotate_right32(x, bits)

> shift left uint32(x, bits)->number
> shift right uint32(x, bits)->number
>
> END.
>
[snip]

Cheers,
Mark.


More information about the Microbit mailing list