Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
8d3fde2
no more badges
skogsbaer May 10, 2025
c13d0e4
Merge branch 'master' of github.com:skogsbaer/write-your-python-program
skogsbaer May 11, 2025
bf262a6
version bump and changelog for 1.3.1 and 1.3.2
skogsbaer May 11, 2025
7c42534
more tests
skogsbaer May 26, 2025
8cb1064
port fileTests to python
skogsbaer May 26, 2025
0e4e046
remove untypy
skogsbaer May 27, 2025
88427bf
split file tests
skogsbaer May 27, 2025
43822fd
improve python tycheck IDE config
skogsbaer May 27, 2025
350b296
basics tests
skogsbaer Jun 4, 2025
db1776a
TEMP
skogsbaer Jun 4, 2025
808ffc1
add typeguard
skogsbaer Jun 5, 2025
41dfa13
move typeguard
skogsbaer Jun 6, 2025
eb2e7ba
add typing_extensions
skogsbaer Jun 6, 2025
81632bc
progress
skogsbaer Jul 1, 2025
11932fa
remove most occurrences of untypy
skogsbaer Jul 7, 2025
bbbf848
many improvements
skogsbaer Sep 12, 2025
c6a3069
typeguard: properly format forward references
skogsbaer Sep 12, 2025
fcba062
typeguard: hide certain prefixes
skogsbaer Sep 12, 2025
1fea0ff
more fixes
skogsbaer Sep 12, 2025
456d6a1
some I18N
skogsbaer Sep 13, 2025
37e1397
finally remove untypy
skogsbaer Sep 14, 2025
fbccc51
fix unit tests
skogsbaer Sep 14, 2025
fec1bd6
test for I18N
skogsbaer Sep 14, 2025
312cfff
get language from environment
skogsbaer Sep 15, 2025
4523802
more unit tests
skogsbaer Sep 18, 2025
990ce41
functionality for recording expected test results
skogsbaer Sep 18, 2025
ffb6fe5
cmdline option for language
skogsbaer Sep 18, 2025
d82f3b2
bugfix
skogsbaer Sep 18, 2025
ae8a25b
add missing files
skogsbaer Sep 18, 2025
c6a19fc
support for lang in tests
skogsbaer Sep 18, 2025
5a4764b
all tests in test-data-2.0 working
skogsbaer Sep 19, 2025
51092b9
add missing files
skogsbaer Sep 19, 2025
37dfe4f
support for functions/methods without annotations
skogsbaer Sep 22, 2025
2c9ff59
refactored formatting of types
skogsbaer Sep 22, 2025
c27cc14
support for detecting illegal types such as list(int) and mutable record
skogsbaer Sep 22, 2025
053c6bb
fixed tests
skogsbaer Sep 22, 2025
0c8f0b5
add missing files
skogsbaer Sep 22, 2025
eff4f74
fixes
skogsbaer Sep 22, 2025
01392ae
fixed many tests
skogsbaer Sep 22, 2025
de7bcfa
typeguard: delete frame after use
skogsbaer Sep 23, 2025
4bb2d74
most tests are working now
skogsbaer Sep 23, 2025
d56790d
typeguard: support for type aliases
skogsbaer Sep 23, 2025
63e6866
all file tests working except one
skogsbaer Sep 23, 2025
ea12943
all file tests running
skogsbaer Sep 23, 2025
4c525d7
do not fix file paths in tests
skogsbaer Sep 23, 2025
10de15c
moved tests from failing to extras
skogsbaer Sep 23, 2025
3a5b793
split runner
skogsbaer Sep 23, 2025
677bd49
fixed integration tests
skogsbaer Sep 23, 2025
6864969
fixed import tests
skogsbaer Sep 23, 2025
eaa2276
all tests working for python 3.12
skogsbaer Sep 23, 2025
97a2be2
all tests expect install tests running for 3.12 and 3.13
skogsbaer Sep 24, 2025
7e4cc05
finished big refactoring
skogsbaer Sep 24, 2025
c6f0183
update README and version
skogsbaer Sep 24, 2025
375f0ea
changelog and setup for 2.0.0
skogsbaer Sep 24, 2025
b9a55e9
update python version for CI checks
skogsbaer Sep 24, 2025
e9fbf9c
remove more absolute paths from test output
skogsbaer Sep 24, 2025
a561b1a
fix trace generator tests
skogsbaer Sep 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 1 addition & 2 deletions .github/workflows/github-action-test-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
# You need to change to branch protection rules if you change the versions here
python-version: [3.12.1, 3.13.0]
python-version: [3.12.11, 3.13.7]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -24,5 +24,4 @@ jobs:
cd python && ./allTestsForPyVersion
- name: Test pytrace-generator
run: |
python3 python/src/runYourProgram.py --install-mode installOnly
python3 pytrace-generator/test/runTests.py
8 changes: 8 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Write Your Python Program - CHANGELOG

* 2.0.0 (2025-09-24)
* Remove wrappers, only check types at function enter/exit points
* Restructure directory layout
* RUN button now longer copies files to the site-lib directory
* 1.3.2 (2025-05-11)
* Fix release (version 1.3.1. did no include the latest changes)
* 1.3.1 (2025-05-10)
* Fix bug with python 3.13 and wrappers
* 1.3.0 (2024-12-01)
* Fix bug with union of unions
* Improve scrolling #148
Expand Down
48 changes: 10 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[![Python CI](https://github.com/skogsbaer/write-your-python-program/actions/workflows/github-action-test-python.yml/badge.svg)](https://github.com/skogsbaer/write-your-python-program/actions/workflows/github-action-test-python.yml)
[![Node.js CI](https://github.com/skogsbaer/write-your-python-program/actions/workflows/github-action-test-js.yml/badge.svg)](https://github.com/skogsbaer/write-your-python-program/actions/workflows/github-action-test-js.yml)

# Write Your Python Program

A user-friendly python programming environment for beginners.
Expand Down Expand Up @@ -40,6 +37,11 @@ Run `wypp --help` for usage information.

Here is the [Changelog](ChangeLog.md).

* **Breaking change** in version 2.0.0 (2025-0-24): type annotations are now only
checked when entering/exiting a function. Before, certain things such as lists
or callable were put behind wrapper objects. For example, these wrappers ensured
that only ints could be appended to a list of type `list[int]`. However, these
wrappers came with several drawbacks, so they were removed in release 2.0.0
* **Breaking change** in version 0.12.0 (2021-09-28): type annotations are now checked
dynamically when the code is executed.
This behavior can be deactivated in the settings of the extension.
Expand All @@ -50,7 +52,10 @@ You need an explicit import statement such as `from wypp import *`.

Here is a screen shot:

![Screenshot](screenshot.jpg)
![Screenshot](screenshot.png)

There is also a visualization mode, similar to [Python Tutor](https://pythontutor.com/):
![Screenshot](screenshot2.png)

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
Expand All @@ -59,7 +64,7 @@ all definitions have been executed.
The file being executed should contain the following import statement in the first line:

~~~python
from wypp import*
from wypp import *
~~~

Running the file with the RUN button makes the following features available:
Expand Down Expand Up @@ -193,39 +198,6 @@ 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:
- `list[idx]`
- `list[idx] = value`
- `list += [...]`
- `list.append(value)`
- `list.insert(idx, value)`
- `list.extend(iterator)`
- `for i in list:` (Iterator)

For builtin `set[T]` these operations are typechecked:
- `set.add(value)`
- `set.pop()`
- `set.remove(value)` Value must be of `T`
- `set.update(other, ...)`
- `value in set` Value must be of `T`
- `for i in set:` (Iterator)

For builtin `dict[K,V]` the supported typechecked operations are:
- `dict.get(key)`
- `dict.items()`
- `dict.keys()`
- `dict.pop()`
- `dict.popitem()`
- `dict.setdefault(key, default)` <br/>_Note:_ In contrast to the standard library `default` is required, to avoid inserting `None` as value into otherwise typed dicts.
- `dict.update(other)`
- `dict.update(key=value, ...)`
- `dict.values()`
- `key in dict` Key must be of `K`
- `del dict[key]`
- `for k in dict` (Iterator)
- `reversed(dict)`
- `dict[key]`
- `dict[key] = value`

## Module name and current working directory

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"displayName": "Write Your Python Program!",
"description": "A user friendly python environment for beginners",
"license": "See license in LICENSE",
"version": "1.3.0",
"version": "2.0.0",
"publisher": "StefanWehr",
"icon": "icon.png",
"engines": {
"vscode": "^1.85.0"
"vscode": "^1.94.2"
},
"keywords": [
"Python",
Expand Down
2 changes: 0 additions & 2 deletions python/.ignore

This file was deleted.

6 changes: 6 additions & 0 deletions python/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"python.analysis.diagnosticMode": "workspace",
"python.autoComplete.extraPaths": [
"/Users/swehr/.vscode/extensions/stefanwehr.write-your-python-program-1.3.2/python/src/"
]
}
2 changes: 2 additions & 0 deletions python/TODO.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Code duplication
- wrappedclass.py, protocol.py and typedfunction.py
4 changes: 4 additions & 0 deletions python/TODO_nowrappers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* Test windows
* location matcher for vscode
* show "@record\nclass C" for record attributes

4 changes: 2 additions & 2 deletions python/allTests
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ function run()
echo
}

PYENV_VERSION=3.12.1 run
PYENV_VERSION=3.13.0 run
PYENV_VERSION=3.12 run
PYENV_VERSION=3.13 run
85 changes: 41 additions & 44 deletions python/allTestsForPyVersion
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,61 @@ set -u

cd $(dirname $0)

unit_test_path=src:tests:deps/untypy

function prepare_integration_tests()
{
echo "Preparing integration tests by install the WYPP library"
local d=$(mktemp -d)
trap "rm -rf $d" EXIT
WYPP_INSTALL_DIR=$d python3 src/runYourProgram.py --install-mode installOnly
integ_test_path=integration-tests:$d
}
unit_test_path=code/wypp:tests:code
integration_test_path=code/wypp:integration-tests:code

function usage()
{
echo "USAGE: $0 [--unit | --integration] [ FILE ]"
exit 1
}

if [ -z "${1:-}" ]; then
echo "Python version:"
python3 --version
echo "Running untypy tests"
pushd deps/untypy > /dev/null
./runtests.sh || exit 1
popd > /dev/null
echo "Done with untypy tests"
echo "Running all unit tests, PYTHONPATH=$unit_test_path"
PYTHONPATH=$unit_test_path python3 -m unittest tests/test*.py
echo "Done with unit tests"
echo
prepare_integration_tests
echo "Running all integration tests, PYTHONPATH=$integ_test_path"
PYTHONPATH=$integ_test_path python3 -m unittest integration-tests/test*.py
echo "Done with integration tests"
else
if [ "$1" == "--unit" ]; then
what="unit"
dir=tests
p=$unit_test_path
elif [ "$1" == "--integration" ]; then
what="integration"
dir=integration-tests
prepare_integration_tests
p=$integ_test_path
function run_unit_tests()
{
echo "Running unit tests, PYTHONPATH=$unit_test_path"
if [ -z "${1:-}" ]; then
PYTHONPATH=$unit_test_path python3 -m unittest tests/test*.py
ecode=$?
else
usage
PYTHONPATH=$unit_test_path python3 -m unittest "$@"
ecode=$?
fi
shift
echo "Running $what tests $@ with PYTHONPATH=$p"
echo "Done with unit tests"
}

function run_integration_tests()
{
echo "Running all integration tests, PYTHONPATH=$integration_test_path"
if [ -z "${1:-}" ]; then
PYTHONPATH=$p python3 -m unittest $dir/test*.py
PYTHONPATH=$integration_test_path python3 -m unittest integration-tests/test*.py
ecode=$?
else
PYTHONPATH=$p python3 -m unittest "$@"
PYTHONPATH=$integration_test_path python3 -m unittest "$@"
ecode=$?
fi
echo "$what tests finished with exit code $ecode"
echo "Done with integration tests"
}


echo "Python version:"
python3 --version

if [ -z "${1:-}" ]; then
run_unit_tests
echo
run_integration_tests
echo
echo "Running file tests ..."
python3 ./fileTests.py
elif [ "$1" == "--unit" ]; then
shift
run_unit_tests "$@"
exit $ecode
elif [ "$1" == "--integration" ]; then
shift
run_integration_tests "$@"
exit $ecode
else
usage
fi

echo "Running file tests ..."
./fileTests
48 changes: 48 additions & 0 deletions python/code/typeguard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
from typing import Any

from ._checkers import TypeCheckerCallable as TypeCheckerCallable
from ._checkers import TypeCheckLookupCallback as TypeCheckLookupCallback
from ._checkers import check_type_internal as check_type_internal
from ._checkers import checker_lookup_functions as checker_lookup_functions
from ._checkers import load_plugins as load_plugins
from ._config import CollectionCheckStrategy as CollectionCheckStrategy
from ._config import ForwardRefPolicy as ForwardRefPolicy
from ._config import TypeCheckConfiguration as TypeCheckConfiguration
from ._decorators import typechecked as typechecked
from ._decorators import typeguard_ignore as typeguard_ignore
from ._exceptions import InstrumentationWarning as InstrumentationWarning
from ._exceptions import TypeCheckError as TypeCheckError
from ._exceptions import TypeCheckWarning as TypeCheckWarning
from ._exceptions import TypeHintWarning as TypeHintWarning
from ._functions import TypeCheckFailCallback as TypeCheckFailCallback
from ._functions import check_type as check_type
from ._functions import warn_on_error as warn_on_error
from ._importhook import ImportHookManager as ImportHookManager
from ._importhook import TypeguardFinder as TypeguardFinder
from ._importhook import install_import_hook as install_import_hook
from ._memo import TypeCheckMemo as TypeCheckMemo
from ._suppression import suppress_type_checks as suppress_type_checks
from ._utils import Unset as Unset

# Re-export imports so they look like they live directly in this package
for value in list(locals().values()):
if getattr(value, "__module__", "").startswith(f"{__name__}."):
value.__module__ = __name__


config: TypeCheckConfiguration


def __getattr__(name: str) -> Any:
if name == "config":
from ._config import global_config

return global_config

raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


# Automatically load checker lookup functions unless explicitly disabled
if "TYPEGUARD_DISABLE_PLUGIN_AUTOLOAD" not in os.environ:
load_plugins()
Loading