skogsbaer / write-your-python-program

BSD 3-Clause "New" or "Revised" License
1 stars 4 forks source link

Python CI Node.js CI

Write Your Python Program

A user-friendly python programming environment for beginners.

The ideas of this environment are based on the great ideas from Schreib dein Programm!.

Quick start

Troubleshooting

Usage without Visual Studio Code

Write Your Python Program can be installed outside of Visual Studio Code via pip:

pip3 install wypp

After installation, you can use the wypp command for running your python files, making all features explained below available. Run wypp --help for usage information.

What's new?

Here is the Changelog.

Features

Here is a screen shot:

Screenshot

When hitting the RUN button, the vscode extension saves the current file, opens a terminal and executes the file with Python, staying in interactive mode after all definitions have been executed.

The file being executed should contain the following import statement in the first line:

from wypp import*

Running the file with the RUN button makes the following features available:

Type Definitions

You can define enums, records and union data types and the use them with the type hints of Python 3. Type hints are checked for correctness dynamically, i.e. violations are detected only at the moment when a function is applied to an argument not matching its type hint or when a function returns a value not matching the return type hint. (This approach is similar to contract checking in racket)

Enums

type Color = Literal['red', 'green', 'blue']

Records

@record
class Point:
    x: float
    y: float

@record
class Square:
    center: Point
    width: float

@record
class Circle:
    center: Point
    radius: float

You work with a record like this:

p = Point(2, 3) # point at x=2, y=3
print(p.x)      # Prints 2

Fields of records are immutable by default. You get mutable fields with @record(mutable=True).

Mixed Data Types

type PrimitiveShape = Union[Circle, Square]

To use recursive types, you need to write a forward reference to the yet undefined type as a string:

type Shape = Union[Circle, Square, 'Overlay']

@record
class Overlay:
    top: Shape
    bottom: Shape

Case distinction works like this:

def workOnShape(s: Shape) -> None:
    if isinstance(s, Square):
        # s is a Square, do something with it
        pass
    elif isinstance(s, Circle):
        # s is a Circle, do something with it
        pass
    elif isinstance(s, Overlay):
        # s is an Overlay, do something with it
        pass

The body of workOnShape can safely assume that s is indeed one Square, Circle, or Overlay because the type hint Shape for argument s is checked dynamically. Here is what happens if you apply workOnShape to, say, a string, that is workOnShape('foo').

Traceback (most recent call last):
  File "test.py", line 42, in <module>
    workOnShape("foo")
WyppTypeError: got value of wrong type
given:    'foo'
expected: value of type Union[Circle, Square, Overlay]

context: workOnShape(s: Union[Circle, Square, Overlay]) -> None
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
declared at: test.py:31
caused by: test.py:42
  | workOnShape("foo")

Tests

Tests are defined via check. The first argument of check is the actual result, then second argument the expected result.

check(factorial(4), 24)

Annotations

All python types (builtin or from the typing module) can be used as annotations. Also, you can use every class as a type. In addition, WYPP comes with the following predefined types:

The code is run with from __future__ import annotations (see PEP 563). This means that you can use a type as an annotation before the type being defined, for example to define recursive types or as the type of self inside of classes. In fact, there is no check at all to make sure that anotations refer to existing types.

For builtin list[T] the following operations are typechecked:

For builtin set[T] these operations are typechecked:

For builtin dict[K,V] the supported typechecked operations are:

Module name and current working directory

When executing a python file with the RUN button, the current working directory is set to the directory of the file being executed. The __name__ attribute is set to the value '__wypp__'.

Bugs & Problems

Please report them in the issue tracker.

Hacking

You can debug the extension from Visual Studio Code: