Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
67f3e67
Merge pull request #4 from CodeSteak/untypy
skogsbaer Sep 21, 2021
7434862
update untypy
skogsbaer Sep 21, 2021
2459169
update untypy
skogsbaer Sep 21, 2021
b6e440b
do not import a test module from some other test module
skogsbaer Sep 21, 2021
ee7b63c
update untypy
skogsbaer Sep 21, 2021
467b4f7
fix execution of integration tests
skogsbaer Sep 21, 2021
2a2b484
unskip to tests that now succeed
skogsbaer Sep 21, 2021
a23a8d0
update README
skogsbaer Sep 21, 2021
bdb0d96
remove leftover from implicit wypp import
skogsbaer Sep 21, 2021
55e0df9
improved repl tester and renamed some files
skogsbaer Sep 21, 2021
6349976
symlink for using wypp without installing
skogsbaer Sep 21, 2021
f4bb18e
test for replTester (fails!)
skogsbaer Sep 21, 2021
150c7a5
fix for failing replTester test
skogsbaer Sep 21, 2021
5da45e9
update TODO
skogsbaer Sep 21, 2021
e9504ab
update untypy
skogsbaer Sep 22, 2021
8f9ec73
fix tests
skogsbaer Sep 22, 2021
e8e2b9d
update untypy
skogsbaer Sep 22, 2021
febdc01
some new tests
skogsbaer Sep 22, 2021
4ad786e
export type vars from wypp
skogsbaer Sep 22, 2021
6a3854b
add github issues to failing tests
skogsbaer Sep 22, 2021
f84f048
update untypy
skogsbaer Sep 22, 2021
7ac53ac
tests for forward refs
skogsbaer Sep 23, 2021
ba89fb1
refer to github issue
skogsbaer Sep 23, 2021
96b5fa4
do not re-export internal ForwardRef type
skogsbaer Sep 23, 2021
1ba6f54
improve formatting of exceptions
skogsbaer Sep 23, 2021
6da4d25
test for return type
skogsbaer Sep 23, 2021
5b66956
update untypy
skogsbaer Sep 23, 2021
a47f8b4
script for invoking runYourProgram.py
skogsbaer Sep 23, 2021
9f311a1
add .ignore file for vscode
skogsbaer Sep 23, 2021
d72343b
update untypy
skogsbaer Sep 23, 2021
55570ef
make run script more powerful
skogsbaer Sep 23, 2021
fbdfd01
test for sequences
skogsbaer Sep 23, 2021
9762370
update untypy
skogsbaer Sep 23, 2021
5d63a48
test for variadic tuples
skogsbaer Sep 23, 2021
14f5570
failing test for sequence
skogsbaer Sep 23, 2021
3091c20
update untypy
skogsbaer Sep 23, 2021
50340ac
test for Sequence
skogsbaer Sep 23, 2021
4b3963e
update untypy
skogsbaer Sep 23, 2021
5a78f79
new failing test
skogsbaer Sep 23, 2021
f488566
another failing test
skogsbaer Sep 23, 2021
939f11e
update untypy
skogsbaer Sep 23, 2021
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
5 changes: 4 additions & 1 deletion TODO.org
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
* untypy
** add tests with type annotations
*** for records
**** construction
**** write access
**** test for correct location
** understand why commit 150c7a5b209ddb264fd104feae42eba4905c2be7 is necessary to fix the replTester test
* other
** mode where all functions or methods without type signatures are reported as errors
** upload dist to pypi
** update README
*** python version
*** pip
*** records
*** import
2 changes: 2 additions & 0 deletions python/.ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
site-lib/wypp
site-lib/untypy
1 change: 0 additions & 1 deletion python/file-tests/testArgs.out

This file was deleted.

7 changes: 0 additions & 7 deletions python/file-tests/testTraceback.err

This file was deleted.

5 changes: 0 additions & 5 deletions python/file-tests/testTraceback2.err

This file was deleted.

17 changes: 0 additions & 17 deletions python/file-tests/testTypes1.err

This file was deleted.

17 changes: 0 additions & 17 deletions python/file-tests/testTypes2.err

This file was deleted.

8 changes: 5 additions & 3 deletions python/integration-tests/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,12 @@ def hook(self):

def exit(self, code=0):
if code is None:
code = 0
myCode = 0
elif type(code) != int:
code = 1
self.exitCode = code
myCode = 1
else:
myCode = code
self.exitCode = myCode
self._origExit(code)

def exc_handler(self, exc_type, exc, *args):
Expand Down
113 changes: 61 additions & 52 deletions python/integration-tests/testIntegration.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,140 +32,149 @@ def stripTrailingWs(s):

LOG_FILE = shell.mkTempFile(prefix="wypp-tests", suffix=".log", deleteAtExit='ifSuccess')
print(f'Output of integration tests goes to {LOG_FILE}')
LOG_REDIR = f'> {LOG_FILE} 2>&1'
LOG_REDIR = f'>> {LOG_FILE} 2>&1'

class TypeTests(unittest.TestCase):
def test_enumOk(self):
out = runInteractive('file-tests/typeEnums.py', 'colorToNumber("red")')
out = runInteractive('test-data/typeEnums.py', 'colorToNumber("red")')
self.assertEqual(['0'], out)

def test_enumTypeError(self):
out = runInteractive('file-tests/typeEnums.py', 'colorToNumber(1)')[0]
self.assertIn("expected: Literal['red', 'yellow', 'green']", out)
out = runInteractive('test-data/typeEnums.py', 'colorToNumber(1)')[0]
self.assertIn("expected: value of type Literal['red', 'yellow', 'green']", out)

def test_recordOk(self):
rec = 'file-tests/typeRecords.py'
rec = 'test-data/typeRecords.py'
out1 = runInteractive(rec, 'Person("stefan", 42)')
self.assertEqual(["Person(name='stefan', age=42)"], out1)
out2 = runInteractive(rec, 'incAge(Person("stefan", 42))')
self.assertEqual(["Person(name='stefan', age=43)"], out2)

@unittest.skip
def test_recordFail1(self):
rec = 'file-tests/typeRecords.py'
rec = 'test-data/typeRecords.py'
out = runInteractive(rec, 'Person("stefan", 42.3)')[0]
self.assertIn('expected: int', out)
self.assertIn('expected: value of type int', out)

def test_recordFail2(self):
rec = 'file-tests/typeRecords.py'
rec = 'test-data/typeRecords.py'
out = runInteractive(rec, 'mutableIncAge(Person("stefan", 42))')[0]
self.assertIn('expected: MutablePerson', out)
self.assertIn('expected: value of type MutablePerson', out)

def test_recordMutableOk(self):
rec = 'file-tests/typeRecords.py'
rec = 'test-data/typeRecords.py'
out1 = runInteractive(rec, 'MutablePerson("stefan", 42)')
self.assertEqual(["MutablePerson(name='stefan', age=42)"], out1)
out2 = runInteractive(rec, 'p = MutablePerson("stefan", 42)\nmutableIncAge(p)\np')
self.assertEqual(['', '', "MutablePerson(name='stefan', age=43)"], out2)

@unittest.skip
def test_mutableRecordFail1(self):
rec = 'file-tests/typeRecords.py'
rec = 'test-data/typeRecords.py'
out = runInteractive(rec, 'MutablePerson("stefan", 42.3)')[0]
self.assertIn('expected: int', out)
self.assertIn('expected: value of type int', out)

def test_mutableRecordFail2(self):
rec = 'file-tests/typeRecords.py'
rec = 'test-data/typeRecords.py'
out = runInteractive(rec, 'incAge(MutablePerson("stefan", 42))')[0]
self.assertIn('expected: Person', out)
self.assertIn('expected: value of type Person', out)

@unittest.skip
def test_mutableRecordFail3(self):
rec = 'file-tests/typeRecords.py'
rec = 'test-data/typeRecords.py'
out = runInteractive(rec, 'p = MutablePerson("stefan", 42)\np.age = 42.4')
self.assertIn('expected: int', out)
self.assertIn('expected: value of type int', out)

def test_union(self):
out = runInteractive('file-tests/typeUnion.py', """formatAnimal(myCat)
out = runInteractive('test-data/typeUnion.py', """formatAnimal(myCat)
formatAnimal(myParrot)
formatAnimal(None)
""")
self.assertEqual("'Cat Pumpernickel'", out[0])
self.assertEqual("\"Parrot Mike says: Let's go to the punkrock show\"", out[1])
self.assertIn('given: None\nexpected: Union[Cat, Parrot]', out[2])
self.assertIn('given: None\nexpected: value of type Union[Cat, Parrot]', out[2])

class StudentSubmissionTests(unittest.TestCase):
def check(self, file, testFile, ecode, tycheck=True):
flags = ['--check']
if not tycheck:
flags.append('--no-typechecking')
cmd = f"python3 src/runYourProgram.py {' '.join(flags)} --test-file {testFile} {file} {LOG_REDIR}"
print(cmd)
res = shell.run(cmd, onError='ignore')
self.assertEqual(ecode, res.exitcode)

def test_goodSubmission(self):
self.check("file-tests/student-submission.py", "file-tests/student-submission-tests.py", 0)
self.check("file-tests/student-submission.py", "file-tests/student-submission-tests.py", 0,
self.check("test-data/student-submission.py", "test-data/student-submission-tests.py", 0)
self.check("test-data/student-submission.py", "test-data/student-submission-tests.py", 0,
tycheck=False)

def test_badSubmission(self):
self.check("file-tests/student-submission-bad.py",
"file-tests/student-submission-tests.py", 1)
self.check("file-tests/student-submission-bad.py",
"file-tests/student-submission-tests.py", 1, tycheck=False)
self.check("test-data/student-submission-bad.py",
"test-data/student-submission-tests.py", 1)
self.check("test-data/student-submission-bad.py",
"test-data/student-submission-tests.py", 1, tycheck=False)

def test_submissionWithTypeErrors(self):
self.check("file-tests/student-submission-tyerror.py",
"file-tests/student-submission-tests.py", 1)
self.check("file-tests/student-submission-tyerror.py",
"file-tests/student-submission-tests.py", 0, tycheck=False)
self.check("file-tests/student-submission.py",
"file-tests/student-submission-tests-tyerror.py", 1)
self.check("file-tests/student-submission.py",
"file-tests/student-submission-tests-tyerror.py", 0, tycheck=False)
self.check("test-data/student-submission-tyerror.py",
"test-data/student-submission-tests.py", 1)
self.check("test-data/student-submission-tyerror.py",
"test-data/student-submission-tests.py", 0, tycheck=False)
self.check("test-data/student-submission.py",
"test-data/student-submission-tests-tyerror.py", 1)
self.check("test-data/student-submission.py",
"test-data/student-submission-tests-tyerror.py", 0, tycheck=False)

class InteractiveTests(unittest.TestCase):

def test_scopeBugPeter(self):
out = runInteractive('file-tests/scope-bug-peter.py', 'local_test()\nprint(spam)')
out = runInteractive('test-data/scope-bug-peter.py', 'local_test()\nprint(spam)')
self.assertIn('IT WORKS', out)

def test_types1(self):
out = runInteractive('file-tests/testTypesInteractive.py', 'inc(3)')
out = runInteractive('test-data/testTypesInteractive.py', 'inc(3)')
self.assertEqual(['4'], out)

def test_types2(self):
out = runInteractive('file-tests/testTypesInteractive.py', 'inc("3")')[0]
expected = """given: '3'
expected: int
^^^
out = runInteractive('test-data/testTypesInteractive.py', 'inc("3")')[0]
expected = """untypy.error.UntypyTypeError
given: '3'
expected: value of type int

context: inc(x: int) -> int
^^^
declared at: /Users/swehr/devel/write-your-python-program/python/test-data/testTypesInteractive.py:1
1 | def inc(x: int) -> int:
2 | return x + 1

inside of inc(x: int) -> int
^^^
declared at:"""
self.assertIn(expected, stripTrailingWs(out))
caused by: <console>:1"""
self.assertEqual(expected, out)

def test_types3(self):
out = runInteractive('file-tests/testTypesInteractive.py',
out = runInteractive('test-data/testTypesInteractive.py',
'def f(x: int) -> int: return x\n\nf("x")')[1]
self.assertIn('expected: int', out)
self.assertIn('expected: value of type int', out)

def test_types4(self):
out = runInteractive('file-tests/testTypesInteractive.py',
out = runInteractive('test-data/testTypesInteractive.py',
'def f(x: int) -> int: return x\n\nf(3)')
self.assertEqual(['...', '3'], out)

def test_types5(self):
out = runInteractive('file-tests/testTypesInteractive.py',
out = runInteractive('test-data/testTypesInteractive.py',
'def f(x: int) -> int: return x\n\nf("x")',
tycheck=False)
self.assertEqual(['...', "'x'"], out)

def test_typesInImportedModule1(self):
out = run('file-tests/testTypes3.py', ecode=1)
self.assertIn('expected: int', out)
out = run('test-data/testTypes3.py', ecode=1)
self.assertIn('expected: value of type int', out)

def test_typesInImportedModule2(self):
out = run('file-tests/testTypes3.py', tycheck=False)
out = run('test-data/testTypes3.py', tycheck=False)
self.assertEqual('END', out)

class ReplTesterTests(unittest.TestCase):

def test_replTester(self):
d = shell.pwd()
cmd = f'python3 {d}/src/replTester.py {d}/test-data/repl-test-lib.py --repl {d}/test-data/repl-test-checks.py'
res = shell.run(cmd, captureStdout=True, onError='die', cwd='/tmp')
self.assertIn('All 1 tests succeded. Great!', res.stdout)
5 changes: 5 additions & 0 deletions python/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

PYTHONPATH="$SCRIPT_DIR"/site-lib/ python3 "$SCRIPT_DIR"/src/runYourProgram.py "$@"
49 changes: 36 additions & 13 deletions python/runFileTests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ d=$(pwd)
siteDir=$(python3 -c 'import site; print(site.USER_SITE)')
t=$(mktemp)

echo
echo "Running file tests, siteDir=$siteDir ..."
echo "Writing logs to $t"
function check()
Expand All @@ -23,10 +22,10 @@ function check()
python3 $d/src/runYourProgram.py --check --install-mode assertInstall $d/"$1" >> "$t"
popd > /dev/null
}
check file-tests/fileWithImport.py
check file-tests/fileWithoutImport.py
check file-tests/fileWithBothImports.py
check file-tests/fileWithRecursiveTypes.py
check test-data/fileWithImport.py
check test-data/fileWithoutImport.py
check test-data/fileWithBothImports.py
check test-data/fileWithRecursiveTypes.py

# First argument: whether to do type checking or not
# Second argument: expected exit code. If given as X:Y, then X is the exit code with active
Expand All @@ -37,6 +36,7 @@ function checkWithOutputAux()
local tycheck="$1"
local expectedEcode=$2
local file="$3"
echo "Checking $file"
shift 3
tycheckOpt=""
suffixes="${PYENV_VERSION}"
Expand Down Expand Up @@ -101,11 +101,34 @@ function checkWithOutput()
checkWithOutputAux no "$@"
}

checkWithOutput 1 file-tests/testTraceback.py
checkWithOutput 1 file-tests/testTraceback2.py
checkWithOutput 1 file-tests/testTraceback3.py
checkWithOutput 0 file-tests/testArgs.py ARG_1 ARG_2
checkWithOutput 0 file-tests/printModuleName.py
checkWithOutput 0 file-tests/printModuleNameImport.py
checkWithOutput 1 file-tests/testTypes1.py
checkWithOutput 1:0 file-tests/testTypes2.py
checkWithOutput 1 test-data/testTraceback.py
checkWithOutput 1 test-data/testTraceback2.py
checkWithOutput 1 test-data/testTraceback3.py
checkWithOutput 0 test-data/testArgs.py ARG_1 ARG_2
checkWithOutput 0 test-data/printModuleName.py
checkWithOutput 0 test-data/printModuleNameImport.py
checkWithOutput 1 test-data/testTypes1.py
checkWithOutput 1:0 test-data/testTypes2.py
checkWithOutputAux yes 1 test-data/testTypesCollections1.py
checkWithOutputAux yes 1 test-data/testTypesCollections2.py
# checkWithOutputAux yes 1 test-data/testTypesCollections3.py See #5
# checkWithOutputAux yes 1 test-data/testTypesCollections4.py See #6
checkWithOutputAux yes 1 test-data/testTypesProtos1.py
# checkWithOutputAux yes 1 test-data/testTypesProtos2.py See #8
checkWithOutputAux yes 1 test-data/testTypesProtos3.py
# checkWithOutputAux yes 1 test-data/testTypesProtos4.py See #9
# checkWithOutputAux yes 1 test-data/testTypesSubclassing1.py See #10
# checkWithOutputAux yes 1 test-data/testTypesHigherOrderFuns.py See #7
# checkWithOutputAux yes 1 test-data/testTypesRecordInheritance.py See #11
checkWithOutputAux yes 0 test-data/testForwardRef1.py
# checkWithOutputAux yes 1 test-data/testForwardRef2.py See #14
checkWithOutputAux yes 0 test-data/testForwardRef3.py
# checkWithOutputAux yes 1 test-data/testForwardRef4.py See #14
# checkWithOutputAux yes 1 test-data/testTypesReturn.py See #15
checkWithOutputAux yes 1 test-data/testTypesSequence1.py
checkWithOutputAux yes 1 test-data/testTypesSequence2.py
checkWithOutputAux yes 1 test-data/testTypesTuple1.py
# checkWithOutputAux yes 1 test-data/wrong-caused-by.py See #17
# checkWithOutputAux yes 1 test-data/declared-aty.py See #18


Loading