mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-03 05:53:15 +08:00
added some entity tests
This commit is contained in:
parent
fbd7ea71d3
commit
1420c54947
9
.idea/dictionaries/ericf.xml
generated
9
.idea/dictionaries/ericf.xml
generated
@ -187,6 +187,7 @@
|
||||
<w>bumpmap</w>
|
||||
<w>buttondown</w>
|
||||
<w>buttonwidget</w>
|
||||
<w>bval</w>
|
||||
<w>byteswap</w>
|
||||
<w>cachable</w>
|
||||
<w>cachebasename</w>
|
||||
@ -281,6 +282,7 @@
|
||||
<w>compat</w>
|
||||
<w>compileall</w>
|
||||
<w>compilelocations</w>
|
||||
<w>compoundlist</w>
|
||||
<w>configerror</w>
|
||||
<w>confighash</w>
|
||||
<w>configkey</w>
|
||||
@ -470,6 +472,7 @@
|
||||
<w>entrytype</w>
|
||||
<w>entrytypeselect</w>
|
||||
<w>enumtype</w>
|
||||
<w>enumval</w>
|
||||
<w>envhash</w>
|
||||
<w>epath</w>
|
||||
<w>epicfail</w>
|
||||
@ -613,6 +616,7 @@
|
||||
<w>functxt</w>
|
||||
<w>funtionality</w>
|
||||
<w>futimens</w>
|
||||
<w>fval</w>
|
||||
<w>gameactivity</w>
|
||||
<w>gamebutton</w>
|
||||
<w>gameclass</w>
|
||||
@ -794,10 +798,12 @@
|
||||
<w>iserverget</w>
|
||||
<w>iserverput</w>
|
||||
<w>ispunch</w>
|
||||
<w>isubval</w>
|
||||
<w>isysroot</w>
|
||||
<w>itms</w>
|
||||
<w>itmsp</w>
|
||||
<w>itunes</w>
|
||||
<w>ival</w>
|
||||
<w>jackmorgan</w>
|
||||
<w>janktastic</w>
|
||||
<w>janky</w>
|
||||
@ -1442,6 +1448,7 @@
|
||||
<w>sitebuiltins</w>
|
||||
<w>skey</w>
|
||||
<w>sline</w>
|
||||
<w>slval</w>
|
||||
<w>smlh</w>
|
||||
<w>smtpd</w>
|
||||
<w>smtplib</w>
|
||||
@ -1546,6 +1553,7 @@
|
||||
<w>svalin</w>
|
||||
<w>sver</w>
|
||||
<w>svne</w>
|
||||
<w>svvv</w>
|
||||
<w>swip</w>
|
||||
<w>swipsound</w>
|
||||
<w>symlinked</w>
|
||||
@ -1576,6 +1584,7 @@
|
||||
<w>tchar</w>
|
||||
<w>tcombine</w>
|
||||
<w>tdelay</w>
|
||||
<w>tdval</w>
|
||||
<w>teambasesession</w>
|
||||
<w>teamgame</w>
|
||||
<w>teamnamescolors</w>
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"astroid",
|
||||
"bs_mapdefs_bridgit",
|
||||
"pylint.lint",
|
||||
"pytest",
|
||||
"bs_mapdefs_zig_zag",
|
||||
"bs_mapdefs_the_pad",
|
||||
"bs_mapdefs_step_right_up",
|
||||
|
||||
@ -18,6 +18,9 @@ ignore_errors = True
|
||||
[mypy-astroid.*]
|
||||
ignore_missing_imports = True
|
||||
|
||||
[mypy-pytest.*]
|
||||
ignore_missing_imports = True
|
||||
|
||||
[mypy-efrotools.pylintplugins]
|
||||
disallow_any_unimported = False
|
||||
|
||||
|
||||
@ -22,30 +22,94 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, List, Sequence
|
||||
from typing import TYPE_CHECKING
|
||||
from enum import Enum, unique
|
||||
|
||||
import pytest
|
||||
|
||||
from bafoundation import entity
|
||||
from efrotools.statictest import static_type_equals
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
|
||||
def inc(x: int) -> int:
|
||||
"""Testing inc."""
|
||||
return x + 1
|
||||
# A smattering of enum value types...
|
||||
@unique
|
||||
class EnumTest(Enum):
|
||||
"""Testing..."""
|
||||
FIRST = 0
|
||||
SECOND = 1
|
||||
|
||||
|
||||
def test_answer() -> None:
|
||||
"""Testing answer."""
|
||||
fooval: List[int] = [3, 4]
|
||||
assert static_type_equals(fooval[0], int)
|
||||
assert static_type_equals(fooval, List[int])
|
||||
somevar: Sequence[int] = []
|
||||
assert static_type_equals(somevar, Sequence[int])
|
||||
assert isinstance(fooval, list)
|
||||
assert inc(3) == 4
|
||||
class CompoundTest(entity.CompoundValue):
|
||||
"""Testing..."""
|
||||
isubval = entity.Field('i', entity.IntValue(default=34532))
|
||||
|
||||
|
||||
def test_answer2() -> None:
|
||||
"""Testing answer."""
|
||||
assert inc(3) == 4
|
||||
class CompoundTest2(CompoundTest):
|
||||
"""Testing..."""
|
||||
isubval2 = entity.Field('i2', entity.IntValue(default=3453))
|
||||
|
||||
|
||||
class EntityTest(entity.Entity):
|
||||
"""Testing..."""
|
||||
ival = entity.Field('i', entity.IntValue(default=345))
|
||||
sval = entity.Field('s', entity.StringValue(default='svvv'))
|
||||
bval = entity.Field('b', entity.BoolValue(default=True))
|
||||
fval = entity.Field('f', entity.FloatValue(default=1.0))
|
||||
grp = entity.CompoundField('g', CompoundTest2())
|
||||
grp2 = entity.CompoundField('g2', CompoundTest())
|
||||
enumval = entity.Field('e', entity.EnumValue(EnumTest, default=None))
|
||||
enumval2 = entity.Field(
|
||||
'e2', entity.OptionalEnumValue(EnumTest, default=EnumTest.SECOND))
|
||||
compoundlist = entity.CompoundListField('l', CompoundTest())
|
||||
slval = entity.ListField('sl', entity.StringValue())
|
||||
tval2 = entity.Field('t2', entity.DateTimeValue())
|
||||
str_int_dict = entity.DictField('sd', str, entity.IntValue())
|
||||
tdval = entity.CompoundDictField('td', str, CompoundTest())
|
||||
fval2 = entity.Field('f2', entity.Float3Value())
|
||||
|
||||
|
||||
class EntityTest2(entity.EntityMixin, CompoundTest2):
|
||||
"""test."""
|
||||
|
||||
|
||||
def test_entity_values() -> None:
|
||||
"""Test various entity assigns for value and type correctness."""
|
||||
ent = EntityTest()
|
||||
|
||||
# Simple int field.
|
||||
with pytest.raises(TypeError):
|
||||
# noinspection PyTypeHints
|
||||
ent.ival = 'strval' # type: ignore
|
||||
assert static_type_equals(ent.ival, int)
|
||||
assert isinstance(ent.ival, int)
|
||||
assert ent.ival == 345
|
||||
ent.ival = 346
|
||||
assert ent.ival == 346
|
||||
|
||||
# Simple str/int dict field.
|
||||
assert 'foo' not in ent.str_int_dict
|
||||
with pytest.raises(TypeError):
|
||||
# noinspection PyTypeHints
|
||||
ent.str_int_dict[0] = 123 # type: ignore
|
||||
with pytest.raises(TypeError):
|
||||
# noinspection PyTypeHints
|
||||
ent.str_int_dict['foo'] = 'bar' # type: ignore
|
||||
ent.str_int_dict['foo'] = 123
|
||||
assert static_type_equals(ent.str_int_dict['foo'], int)
|
||||
assert ent.str_int_dict['foo'] == 123
|
||||
|
||||
# Compound list field.
|
||||
with pytest.raises(IndexError):
|
||||
print(ent.compoundlist[0])
|
||||
with pytest.raises(TypeError):
|
||||
# noinspection PyTypeHints
|
||||
ent.compoundlist[0] = 123 # type: ignore
|
||||
assert len(ent.compoundlist) == 0
|
||||
assert not ent.compoundlist
|
||||
ent.compoundlist.append()
|
||||
assert ent.compoundlist
|
||||
assert len(ent.compoundlist) == 1
|
||||
assert static_type_equals(ent.compoundlist[0], CompoundTest)
|
||||
|
||||
@ -52,6 +52,8 @@ class StaticTestFile:
|
||||
from efrotools import PYTHON_BIN
|
||||
|
||||
self._filename = filename
|
||||
self.modulename = f'temp{_nextfilenum}'
|
||||
_nextfilenum += 1
|
||||
|
||||
# Types we *want* for lines
|
||||
self.linetypes_wanted: Dict[int, str] = {}
|
||||
@ -71,26 +73,32 @@ class StaticTestFile:
|
||||
# (so that we can recycle our mypy cache).
|
||||
if _tempdir is None:
|
||||
_tempdir = tempfile.TemporaryDirectory()
|
||||
# print(f"Created temp dir at {_tempdir.name}")
|
||||
|
||||
# Copy our file into the temp dir with a unique name, find all
|
||||
# instances of static_type_equals(), and run mypy type checks
|
||||
# in those places to get static types.
|
||||
tempfilepath = os.path.join(_tempdir.name, f'temp{_nextfilenum}.py')
|
||||
_nextfilenum += 1
|
||||
tempfilepath = os.path.join(_tempdir.name, self.modulename + '.py')
|
||||
with open(tempfilepath, 'w') as outfile:
|
||||
outfile.write(self.filter_file_contents(fdata))
|
||||
results = subprocess.run([
|
||||
PYTHON_BIN, '-m', 'mypy', '--no-error-summary', '--config-file',
|
||||
'.mypy.ini', '--cache-dir', _tempdir.name, tempfilepath
|
||||
],
|
||||
capture_output=True,
|
||||
check=False)
|
||||
# HMM; it seems we get an errored return code due to reveal_type()s.
|
||||
# So I guess we just have to ignore other errors, which is unforunate.
|
||||
# (though if the run fails, we'll probably error when attempting to
|
||||
# look up a revealed type that we don't have anyway)
|
||||
results = subprocess.run(
|
||||
[
|
||||
PYTHON_BIN, '-m', 'mypy', '--no-error-summary',
|
||||
'--config-file', '.mypy.ini', '--cache-dir',
|
||||
os.path.join(_tempdir.name, '.mypy_cache'), tempfilepath
|
||||
],
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
|
||||
# HMM; it seems we always get an errored return code due to
|
||||
# our use of reveal_type() so we can't look at that.
|
||||
# However we can look for error notices in the output and fail there.
|
||||
lines = results.stdout.decode().splitlines()
|
||||
for line in lines:
|
||||
if ': error: ' in line:
|
||||
print("Full mypy output:\n", results.stdout.decode())
|
||||
raise RuntimeError('Errors detected in mypy output.')
|
||||
if 'Revealed type is ' in line:
|
||||
finfo = line.split(' ')[0]
|
||||
fparts = finfo.split(':')
|
||||
@ -172,17 +180,22 @@ def static_type_equals(value: Any, statictype: Type) -> bool:
|
||||
|
||||
if filename not in _statictestfiles:
|
||||
_statictestfiles[filename] = StaticTestFile(filename)
|
||||
testfile = _statictestfiles[filename]
|
||||
|
||||
wanttype = _statictestfiles[filename].linetypes_wanted[linenumber]
|
||||
mypytype = _statictestfiles[filename].linetypes_mypy[linenumber]
|
||||
wanttype = testfile.linetypes_wanted[linenumber]
|
||||
mypytype = testfile.linetypes_mypy[linenumber]
|
||||
|
||||
# Do some filtering of Mypy types to simple python ones.
|
||||
# (ie: 'builtins.list[builtins.int*]' -> int)
|
||||
mypytype = mypytype.replace('builtins.int*', 'int')
|
||||
mypytype = mypytype.replace('*', '')
|
||||
mypytype = mypytype.replace('?', '')
|
||||
mypytype = mypytype.replace('builtins.int', 'int')
|
||||
mypytype = mypytype.replace('builtins.list', 'List')
|
||||
mypytype = mypytype.replace('typing.Sequence', 'Sequence')
|
||||
|
||||
# temp3.FooClass -> FooClass
|
||||
mypytype = mypytype.replace(testfile.modulename + '.', '')
|
||||
|
||||
if wanttype != mypytype:
|
||||
print(f'Mypy type "{mypytype}" does not match '
|
||||
f'the desired type "{wanttype}" on line {linenumber}.')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user