Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
# Write Your Python Program - CHANGELOG

* 2.0.3 (2025-09-24)
* More fixes
* 2.0.2 (2025-09-24)
* More fixes
* 2.0.1 (2025-09-24)
* Minor fixes
* 2.0.1 - 2.0.5 (2025-09-24)
* Many minor fixes
* 2.0.0 (2025-09-24)
* Remove wrappers, only check types at function enter/exit points
* Restructure directory layout
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Write Your Python Program!",
"description": "A user friendly python environment for beginners",
"license": "See license in LICENSE",
"version": "2.0.3",
"version": "2.0.5",
"publisher": "StefanWehr",
"icon": "icon.png",
"engines": {
Expand Down
43 changes: 21 additions & 22 deletions python/code/wypp/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ def tr(key: str, **kws) -> str:
DE = {
'Expecting no return value when calling function `{fun}`.':
'Kein Rückgabewert erwartet bei Aufruf der Funktion `{fun}`.',
'Expecting no return value when calling method `{method}` of class `{cls}.':
'Kein Rückgabewert erwartet bei Aufruf der Methode `{method}` aus Klasse `{cls}`.',
'Expecting no return value when calling method `{method}` of class `{cls}`.':
'Kein Rückgabewert erwartet bei Aufruf der Methode `{method}` der Klasse `{cls}`.',
'Expecting no return value when calling constructor of record `{cls}`.':
'Kein Rückgabewert erwartet bei Aufruf des Konstruktors des Records `{cls}`.',

'Expecting return value of type `{ty}` when calling function `{fun}`.':
'Rückgabewert vom Typ `{ty}` erwartet bei Aufruf der Funktion `{fun}`.',
'Expecting return value of type `{ty}` when calling method `{method}` of class `{cls}`.':
'Rückgabewert vom Typ `{ty}` erwartet bei Aufruf von Methode `{method}` aus Klasse `{cls}`.',
'Rückgabewert vom Typ `{ty}` erwartet bei Aufruf der Methode `{method}` der Klasse `{cls}`.',
'Expecting return value of type `{ty}` when calling constructor of record `{cls}`.':
'Rückgabewert vom Typ `{ty}` erwartet bei Aufruf des Konstruktors des Records `{cls}`.',

Expand All @@ -71,14 +71,14 @@ def tr(key: str, **kws) -> str:
'Aufruf in Zeile {line} führt dazu, dass die Funktion keinen Wert zurückgibt:',

'The call of function `{fun}` expects value of type `{ty}` as {arg}.':
'Der Aufruf der Funktion `{fun}` erwartet Wert vom Typ `{ty}` als {arg}.',
'Der Aufruf der Funktion `{fun}` erwartet einen Wert vom Typ `{ty}` als {arg}.',
'The call of method `{method}` of class `{cls}` expects value of type `{ty}` as {arg}.':
'Der Aufruf der Methode `{method}` aus Klasse `{cls}` erwartet Wert vom Typ `{ty}` als {arg}.',
'Der Aufruf der Methode `{method}` der Klasse `{cls}` erwartet einen Wert vom Typ `{ty}` als {arg}.',
'The call of the constructor of record `{cls}` expects value of type `{ty}` as {arg}.':
'Der Aufruf des Konstruktors des Records `{cls}` erwartet Wert vom Typ `{ty}` als {arg}.',
'Der Aufruf des Konstruktors des Records `{cls}` erwartet einen Wert vom Typ `{ty}` als {arg}.',

'But the value given has type `{ty}`.': 'Aber der übergebene Wert hat Typ `{ty}`.',
'But the default value has type `{ty}`.': 'Aber der Default-Wert hat Typ `{ty}`.',
'But the value given has type `{ty}`.': 'Aber der übergebene Wert hat den Typ `{ty}`.',
'But the default value has type `{ty}`.': 'Aber der Default-Wert hat den Typ `{ty}`.',

'File': 'Datei',
'Line': 'Zeile',
Expand All @@ -93,22 +93,22 @@ def tr(key: str, **kws) -> str:
'Parameter `{param}` of function `{fun}` requires a type annotation.':
'Parameter `{param}` der Funktion `{fun}` benötigt eine Typannotation.',
'Parameter `{param}` of method `{method}` from class `{cls}` requires a type annotation.':
'Parameter `{param}` der Methode `{method}` aus Klasse `{cls}` benötigt eine Typannotation.',
'Parameter `{param}` der Methode `{method}` der Klasse `{cls}` benötigt eine Typannotation.',
'Parameter `{param}` of constructor of record `{cls}` requires a type annotation.':
'Parameter `{param}` des Konstruktors des Records `{cls}` benötigt eine Typannotation.',

'Attribute `{name}` of record `{record}` required a type annotation.':
'Attribute `{name}` of record `{record}` requires a type annotation.':
'Attribut `{name}` des Records `{record}` benötigt eine Typannotation.',

'invalid type `{ty}`':
'ungültiger Typ `{ty}`',
'Cannot set attribute to value of type `{ty}`.':
'Das Attribute kann nicht auf einen Wert vom Typ `{ty}` gesetzt werden.',
'Das Attribut kann nicht auf einen Wert vom Typ `{ty}` gesetzt werden.',
'Problematic assignment in line': 'Fehlerhafte Zuweisung in Zeile',
'Attribute `{attrName}` of record `{recordName}` declared with type `{ty}.`':
'Attribute `{attrName}` of record `{recordName}` declared with type `{ty}`.':
'Attribut `{attrName}` des Records `{recordName}` deklariert als Typ `{ty}`.',

'argument count mismatch': 'Anzahl der Argument passt nicht',
'argument count mismatch': 'Anzahl der Argumente stimmt nicht',
'Call in line': 'Aufruf in Zeile',
'Function `{fun}` takes ': 'Funktion `{fun}` benötigt ',
'Function `{fun}` takes at least ': 'Funktion `{fun}` benötigt mindestens ',
Expand All @@ -124,12 +124,12 @@ def tr(key: str, **kws) -> str:
'Default value for parameter `{paramName}` of function `{fun}` must have type `{ty}`.':
'Default-Wert des Parameters `{paramName}` der Funktion `{fun}` muss vom Typ `{ty}` sein.',
'Default value for parameter `{paramName}` of method `{method}` in class `{cls}` must have type `{ty}`.':
'Default-Wert des Parameters `{paramName}` der Methode `{method}` aus Klasse `{cls}` muss vom Typ `{ty}` sein.',
'Default-Wert des Parameters `{paramName}` der Methode `{method}` der Klasse `{cls}` muss vom Typ `{ty}` sein.',
'Default value for attribute `{paramName}` of record `{cls}` must have type `{ty}`.':
'Default-Wert des Attributs `{paramName}` des Records `{cls}` muss vom Typ `{ty}` sein.',

'Unknown attribute {attrName} for record {clsName}':
'Attribut {attrName} ist nicht bekannt für Record {clsName}',
'Attribut {attrName} ist nicht bekannt für den Record {clsName}',
'Did you mean `{ty}`?': 'Wolltest du `{ty}` schreiben?',

'unknown keyword argument': 'unbekanntes Schlüsselwort-Argument',
Expand All @@ -152,13 +152,12 @@ def tr(key: str, **kws) -> str:
'The impossible happened!': 'Das Unmögliche ist passiert!',
'Stop of execution': 'Abbruch der Ausführung',
'1 successful test': '1 erfolgreicher Test',
'all succesful': 'alle erfolgreich',
'and stop of execution': 'und Abbruch der Ausführung',
'all successful': 'alle erfolgreich',
'and stop of execution': 'und Abbruch der Ausführung',

'NOTE: running the code failed, some definitions might not be available in the interactive window!':
'ACHTUNG: der Code enthält Fehler, einige Definition sind möglicherweise in interaktiven Fenster nicht verfügbar!'

'ACHTUNG: Das Ausführen des Codes ist fehlgeschlagen; einige Definitionen sind möglicherweise im interaktiven Fenster nicht verfügbar!',
'=== WELCOME to ': '=== WILLKOMMEN bei '
}

def expectingNoReturn(cn: location.CallableName) -> str:
Expand All @@ -167,7 +166,7 @@ def expectingNoReturn(cn: location.CallableName) -> str:
return tr('Expecting no return value when calling function `{fun}`.',
fun=cn.name)
case location.ClassMember('method', cls):
return tr('Expecting no return value when calling method `{method}` of class `{cls}.',
return tr('Expecting no return value when calling method `{method}` of class `{cls}`.',
method=cn.name, cls=cls)
case location.ClassMember('recordConstructor', cls):
return tr('Expecting no return value when calling constructor of record `{cls}`.',
Expand Down Expand Up @@ -339,7 +338,7 @@ def expectingTypeAnnotation(cn: location.CallableName, param: str) -> str:
raise ValueError(f'Unexpected: {cn}')

def noTypeAnnotationForAttribute(attrName: str, recordName: str) -> str:
return tr('Attribute `{name}` of record `{record}` required a type annotation.',
return tr('Attribute `{name}` of record `{record}` requires a type annotation.',
name=attrName, record=recordName)

def invalidTy(ty: Any) -> str:
Expand All @@ -349,7 +348,7 @@ def didYouMean(ty: str) -> str:
return tr('Did you mean `{ty}`?', ty=ty)

def recordAttrDeclTy(recordName: str, attrName: str, ty: Any) -> str:
return tr('Attribute `{attrName}` of record `{recordName}` declared with type `{ty}.`',
return tr('Attribute `{attrName}` of record `{recordName}` declared with type `{ty}`.',
recordName=recordName, attrName=attrName, ty=ty)

def unknownKeywordArgument(cn: location.CallableName, name: str) -> str:
Expand Down
5 changes: 3 additions & 2 deletions python/code/wypp/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ def projectDir(d: str):
global _projectDir
old = _projectDir
_projectDir = _normPath(d)
if _projectDir and not _projectDir[-1] == '/':
_projectDir = _projectDir + '/'
sep = os.path.sep
if _projectDir and _projectDir[-1] != sep:
_projectDir = _projectDir + sep
try:
yield
finally:
Expand Down
40 changes: 20 additions & 20 deletions python/code/wypp/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@
import sys
import os

requiredVersion = (3, 12, 0)
def pythonVersionOk(v):
(reqMajor, reqMinor, reqMicro) = requiredVersion
if v.major < reqMajor or v.minor < reqMinor:
return False
if v.major == reqMajor and v.minor == reqMinor and v.micro < reqMicro:
return False
else:
return True

if not pythonVersionOk(sys.version_info):
vStr = sys.version.split()[0]
reqVStr = '.'.join([str(x) for x in requiredVersion])
print(f"""
Python in version {reqVStr} or newer is required. You are still using version {vStr}, please upgrade!
""")
sys.exit(1)

# local imports
from constants import *
import i18n
Expand All @@ -16,15 +34,6 @@
import exceptionHandler
import cmdlineArgs

requiredVersion = (3, 12, 0)
def pythonVersionOk(v):
(reqMajor, reqMinor, reqMicro) = requiredVersion
if v.major < reqMajor or v.minor < reqMinor:
return False
if v.major == reqMajor and v.minor == reqMinor and v.micro < reqMicro:
return False
else:
return True

def printWelcomeString(file, version, doTypecheck):
cwd = os.getcwd() + "/"
Expand All @@ -35,19 +44,10 @@ def printWelcomeString(file, version, doTypecheck):
tycheck = ''
if not doTypecheck:
tycheck = ', no typechecking'
printStderr('=== WELCOME to "Write Your Python Program" ' +
printStderr(i18n.tr('=== WELCOME to ') + '"Write Your Python Program" ' +
'(%sPython %s, %s%s) ===' % (versionStr, pythonVersion, file, tycheck))

def main(globals, argList=None):
v = sys.version_info
if not pythonVersionOk(v):
vStr = sys.version.split()[0]
reqVStr = '.'.join([str(x) for x in requiredVersion])
print(f"""
Python in version {reqVStr} or newer is required. You are still using version {vStr}, please upgrade!
""")
sys.exit(1)

(args, restArgs) = cmdlineArgs.parseCmdlineArgs(argList)
if args.verbose:
enableVerbose()
Expand Down Expand Up @@ -92,7 +92,7 @@ def main(globals, argList=None):
globals = runCode.runStudentCode(fileToRun, globals, args.checkRunnable,
doTypecheck=args.checkTypes, extraDirs=args.extraDirs)
except Exception as e:
verbose(f'Error while running code in {fileToRun}: {e}')
verbose(f'Error while running code in {fileToRun}')
exceptionHandler.handleCurrentException(exit=not isInteractive)
loadingFailed = True

Expand Down
6 changes: 3 additions & 3 deletions python/file-test-data/basics/async.err
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ Traceback (most recent call last):

WyppTypeError: "blub"

Der Aufruf der Funktion `foo` erwartet Wert vom Typ `int` als erstes Argument.
Aber der übergebene Wert hat Typ `str`.
Der Aufruf der Funktion `foo` erwartet einen Wert vom Typ `int` als erstes Argument.
Aber der übergebene Wert hat den Typ `str`.

## Datei file-test-data/basics/async.py
## Fehlerhafter Aufruf in Zeile 7:
Expand All @@ -22,4 +22,4 @@ Aber der übergebene Wert hat Typ `str`.

## Typ deklariert in Zeile 3:

async def foo(i: int):
async def foo(i: int):
4 changes: 2 additions & 2 deletions python/file-test-data/basics/constructor.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Traceback (most recent call last):

WyppTypeError: "1"

Der Aufruf der Methode `__init__` aus Klasse `C` erwartet Wert vom Typ `int` als erstes Argument.
Aber der übergebene Wert hat Typ `str`.
Der Aufruf der Methode `__init__` der Klasse `C` erwartet einen Wert vom Typ `int` als erstes Argument.
Aber der übergebene Wert hat den Typ `str`.

## Datei file-test-data/basics/constructor.py
## Fehlerhafter Aufruf in Zeile 5:
Expand Down
4 changes: 2 additions & 2 deletions python/file-test-data/basics/forwardRefs.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Traceback (most recent call last):

WyppTypeError: <__wypp__.A object at 0x00>

Der Aufruf der Methode `foo` aus Klasse `A` erwartet Wert vom Typ `B` als erstes Argument.
Aber der übergebene Wert hat Typ `A`.
Der Aufruf der Methode `foo` der Klasse `A` erwartet einen Wert vom Typ `B` als erstes Argument.
Aber der übergebene Wert hat den Typ `A`.

## Datei file-test-data/basics/forwardRefs.py
## Fehlerhafter Aufruf in Zeile 12:
Expand Down
4 changes: 2 additions & 2 deletions python/file-test-data/basics/functionArg.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Traceback (most recent call last):

WyppTypeError: "1"

Der Aufruf der Funktion `foo` erwartet Wert vom Typ `int` als zweites Argument.
Aber der übergebene Wert hat Typ `str`.
Der Aufruf der Funktion `foo` erwartet einen Wert vom Typ `int` als zweites Argument.
Aber der übergebene Wert hat den Typ `str`.

## Datei file-test-data/basics/functionArg.py
## Fehlerhafter Aufruf in Zeile 8:
Expand Down
4 changes: 2 additions & 2 deletions python/file-test-data/basics/kwargs.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Traceback (most recent call last):

WyppTypeError: 2

Der Aufruf der Funktion `foo` erwartet Wert vom Typ `str` als Argument `z`.
Aber der übergebene Wert hat Typ `int`.
Der Aufruf der Funktion `foo` erwartet einen Wert vom Typ `str` als Argument `z`.
Aber der übergebene Wert hat den Typ `int`.

## Datei file-test-data/basics/kwargs.py
## Fehlerhafter Aufruf in Zeile 4:
Expand Down
4 changes: 2 additions & 2 deletions python/file-test-data/basics/kwargs2.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Traceback (most recent call last):

WyppTypeError: 2

Der Aufruf der Funktion `foo` erwartet Wert vom Typ `str` als Argument `z`.
Aber der übergebene Wert hat Typ `int`.
Der Aufruf der Funktion `foo` erwartet einen Wert vom Typ `str` als Argument `z`.
Aber der übergebene Wert hat den Typ `int`.

## Datei file-test-data/basics/kwargs2.py
## Fehlerhafter Aufruf in Zeile 4:
Expand Down
2 changes: 1 addition & 1 deletion python/file-test-data/basics/listArg.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Traceback (most recent call last):

WyppTypeError: [1, 2, '3']

Der Aufruf der Funktion `foo` erwartet Wert vom Typ `list[int]` als erstes Argument.
Der Aufruf der Funktion `foo` erwartet einen Wert vom Typ `list[int]` als erstes Argument.

## Datei file-test-data/basics/listArg.py
## Fehlerhafter Aufruf in Zeile 4:
Expand Down
4 changes: 2 additions & 2 deletions python/file-test-data/basics/method.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Traceback (most recent call last):

WyppTypeError: "2"

Der Aufruf der Methode `method` aus Klasse `C` erwartet Wert vom Typ `int` als erstes Argument.
Aber der übergebene Wert hat Typ `str`.
Der Aufruf der Methode `method` der Klasse `C` erwartet einen Wert vom Typ `int` als erstes Argument.
Aber der übergebene Wert hat den Typ `str`.

## Datei file-test-data/basics/method.py
## Fehlerhafter Aufruf in Zeile 9:
Expand Down
2 changes: 1 addition & 1 deletion python/file-test-data/basics/mutable.err
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Traceback (most recent call last):
WyppTypeError: "foo"

Attribut `y` des Records `Point` deklariert als Typ `int`.
Das Attribute kann nicht auf einen Wert vom Typ `str` gesetzt werden.
Das Attribut kann nicht auf einen Wert vom Typ `str` gesetzt werden.

## Datei file-test-data/basics/mutable.py
## Fehlerhafte Zuweisung in Zeile 10:
Expand Down
2 changes: 1 addition & 1 deletion python/file-test-data/basics/mutable.err_en
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Traceback (most recent call last):

WyppTypeError: "foo"

Attribute `y` of record `Point` declared with type `int.`
Attribute `y` of record `Point` declared with type `int`.
Cannot set attribute to value of type `str`.

## File file-test-data/basics/mutable.py
Expand Down
4 changes: 2 additions & 2 deletions python/file-test-data/basics/mutable2.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Traceback (most recent call last):

WyppTypeError: '2'

Der Aufruf des Konstruktors des Records `Point` erwartet Wert vom Typ `int` als zweites Argument.
Aber der übergebene Wert hat Typ `str`.
Der Aufruf des Konstruktors des Records `Point` erwartet einen Wert vom Typ `int` als zweites Argument.
Aber der übergebene Wert hat den Typ `str`.

## Datei file-test-data/basics/mutable2.py
## Fehlerhafter Aufruf in Zeile 8:
Expand Down
4 changes: 2 additions & 2 deletions python/file-test-data/basics/nested.err
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Traceback (most recent call last):

WyppTypeError: 42

Der Aufruf der Funktion `foo` erwartet Wert vom Typ `list[list[int]]` als erstes Argument.
Aber der übergebene Wert hat Typ `int`.
Der Aufruf der Funktion `foo` erwartet einen Wert vom Typ `list[list[int]]` als erstes Argument.
Aber der übergebene Wert hat den Typ `int`.

## Datei file-test-data/basics/nested.py
## Fehlerhafter Aufruf in Zeile 4:
Expand Down
4 changes: 2 additions & 2 deletions python/file-test-data/basics/nestedFun.err
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Traceback (most recent call last):

WyppTypeError: "foo"

Der Aufruf der Funktion `bar` erwartet Wert vom Typ `int` als erstes Argument.
Aber der übergebene Wert hat Typ `str`.
Der Aufruf der Funktion `bar` erwartet einen Wert vom Typ `int` als erstes Argument.
Aber der übergebene Wert hat den Typ `str`.

## Datei file-test-data/basics/nestedFun.py
## Fehlerhafter Aufruf in Zeile 7:
Expand Down
2 changes: 1 addition & 1 deletion python/file-test-data/basics/optionalArgs.err
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Traceback (most recent call last):
WyppTypeError: 2

Default-Wert des Parameters `s` der Funktion `foo` muss vom Typ `str` sein.
Aber der Default-Wert hat Typ `int`.
Aber der Default-Wert hat den Typ `int`.

## Datei file-test-data/basics/optionalArgs.py
## Parameter deklariert in Zeile 1:
Expand Down
2 changes: 1 addition & 1 deletion python/file-test-data/basics/optionalArgs2.err
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Traceback (most recent call last):
File "file-test-data/basics/optionalArgs2.py", line 4, in <module>
foo(1)

WyppTypeError: Anzahl der Argument passt nicht
WyppTypeError: Anzahl der Argumente stimmt nicht

Funktion `foo` benötigt mindestens 2 Argumente.
Gegeben: 1 Argument
Expand Down
Loading