mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-05 23:13:46 +08:00
Added checks for storage name clashes to dataclassio
This commit is contained in:
parent
7f1458304d
commit
f2c0067ee1
1
.idea/dictionaries/ericf.xml
generated
1
.idea/dictionaries/ericf.xml
generated
@ -1649,6 +1649,7 @@
|
|||||||
<w>positionadjusted</w>
|
<w>positionadjusted</w>
|
||||||
<w>posixpath</w>
|
<w>posixpath</w>
|
||||||
<w>posixsubprocess</w>
|
<w>posixsubprocess</w>
|
||||||
|
<w>posonlyargs</w>
|
||||||
<w>postinit</w>
|
<w>postinit</w>
|
||||||
<w>postinited</w>
|
<w>postinited</w>
|
||||||
<w>postrun</w>
|
<w>postrun</w>
|
||||||
|
|||||||
@ -738,6 +738,7 @@
|
|||||||
<w>positivex</w>
|
<w>positivex</w>
|
||||||
<w>positivey</w>
|
<w>positivey</w>
|
||||||
<w>positivez</w>
|
<w>positivez</w>
|
||||||
|
<w>posonlyargs</w>
|
||||||
<w>postinit</w>
|
<w>postinit</w>
|
||||||
<w>postrun</w>
|
<w>postrun</w>
|
||||||
<w>powerup</w>
|
<w>powerup</w>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||||
<h4><em>last updated on 2021-05-25 for Ballistica version 1.6.4 build 20369</em></h4>
|
<h4><em>last updated on 2021-05-26 for Ballistica version 1.6.4 build 20369</em></h4>
|
||||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|||||||
@ -623,3 +623,31 @@ def test_dict() -> None:
|
|||||||
obj4.dval = {_GoodEnum.VAL1: 999} # type: ignore
|
obj4.dval = {_GoodEnum.VAL1: 999} # type: ignore
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
dataclass_to_dict(obj4)
|
dataclass_to_dict(obj4)
|
||||||
|
|
||||||
|
|
||||||
|
def test_name_clashes() -> None:
|
||||||
|
"""Make sure we catch name clashes since we can remap attr names."""
|
||||||
|
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
|
||||||
|
@ioprepped
|
||||||
|
@dataclass
|
||||||
|
class _TestClass:
|
||||||
|
ival: Annotated[int, IOAttrs('i')] = 4
|
||||||
|
ival2: Annotated[int, IOAttrs('i')] = 5
|
||||||
|
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
|
||||||
|
@ioprepped
|
||||||
|
@dataclass
|
||||||
|
class _TestClass2:
|
||||||
|
ival: int = 4
|
||||||
|
ival2: Annotated[int, IOAttrs('ival')] = 5
|
||||||
|
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
|
||||||
|
@ioprepped
|
||||||
|
@dataclass
|
||||||
|
class _TestClass3:
|
||||||
|
ival: Annotated[int, IOAttrs(store_default=False)] = 4
|
||||||
|
ival2: Annotated[int, IOAttrs('ival')] = 5
|
||||||
|
|||||||
@ -38,7 +38,7 @@ except ModuleNotFoundError:
|
|||||||
_pytz_utc = None # pylint: disable=invalid-name
|
_pytz_utc = None # pylint: disable=invalid-name
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Dict, Type, Tuple, Optional, List
|
from typing import Any, Dict, Type, Tuple, Optional, List, Set
|
||||||
|
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
|
|
||||||
@ -58,8 +58,14 @@ EXTRA_ATTRS_ATTR = '_DCIOEXATTRS'
|
|||||||
|
|
||||||
|
|
||||||
class Codec(Enum):
|
class Codec(Enum):
|
||||||
"""Influences format used for input/output."""
|
"""Specifies expected data format exported to or imported from."""
|
||||||
|
|
||||||
|
# Use only types that will translate cleanly to/from json: lists,
|
||||||
|
# dicts with str keys, bools, ints, floats, and None.
|
||||||
JSON = 'json'
|
JSON = 'json'
|
||||||
|
|
||||||
|
# Mostly like JSON but passes bytes and datetime objects through
|
||||||
|
# as-is instead of converting them to json-friendly types.
|
||||||
FIRESTORE = 'firestore'
|
FIRESTORE = 'firestore'
|
||||||
|
|
||||||
|
|
||||||
@ -267,8 +273,8 @@ class PrepSession:
|
|||||||
'efro.dataclassio: implicitly prepping dataclass: %s.'
|
'efro.dataclassio: implicitly prepping dataclass: %s.'
|
||||||
' It is highly recommended to explicitly prep dataclasses'
|
' It is highly recommended to explicitly prep dataclasses'
|
||||||
' as soon as possible after definition (via'
|
' as soon as possible after definition (via'
|
||||||
' efro.dataclassio.dataclass_prep() or the'
|
' efro.dataclassio.ioprep() or the'
|
||||||
' @efro.dataclassio.prepped decorator).', cls)
|
' @efro.dataclassio.ioprepped decorator).', cls)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# NOTE: perhaps we want to expose the globalns/localns args
|
# NOTE: perhaps we want to expose the globalns/localns args
|
||||||
@ -287,6 +293,7 @@ class PrepSession:
|
|||||||
fields = dataclasses.fields(cls)
|
fields = dataclasses.fields(cls)
|
||||||
fields_by_name = {f.name: f for f in fields}
|
fields_by_name = {f.name: f for f in fields}
|
||||||
|
|
||||||
|
all_storage_names: Set[str] = set()
|
||||||
storage_names_to_attr_names: Dict[str, str] = {}
|
storage_names_to_attr_names: Dict[str, str] = {}
|
||||||
|
|
||||||
# Ok; we've resolved actual types for this dataclass.
|
# Ok; we've resolved actual types for this dataclass.
|
||||||
@ -301,7 +308,18 @@ class PrepSession:
|
|||||||
if ioattrs is not None:
|
if ioattrs is not None:
|
||||||
ioattrs.validate_for_field(cls, fields_by_name[attrname])
|
ioattrs.validate_for_field(cls, fields_by_name[attrname])
|
||||||
if ioattrs.storagename is not None:
|
if ioattrs.storagename is not None:
|
||||||
|
storagename = ioattrs.storagename
|
||||||
storage_names_to_attr_names[ioattrs.storagename] = attrname
|
storage_names_to_attr_names[ioattrs.storagename] = attrname
|
||||||
|
else:
|
||||||
|
storagename = attrname
|
||||||
|
else:
|
||||||
|
storagename = attrname
|
||||||
|
|
||||||
|
# Make sure we don't have any clashes in our storage names.
|
||||||
|
if storagename in all_storage_names:
|
||||||
|
raise TypeError(f'Multiple attrs on {cls} are using'
|
||||||
|
f' storage-name \'{storagename}\'')
|
||||||
|
all_storage_names.add(storagename)
|
||||||
|
|
||||||
self.prep_type(cls,
|
self.prep_type(cls,
|
||||||
attrname,
|
attrname,
|
||||||
|
|||||||
@ -140,6 +140,7 @@ def func_annotations_filter(node: nc.NodeNG) -> nc.NodeNG:
|
|||||||
node.args.varargannotation = None
|
node.args.varargannotation = None
|
||||||
node.args.kwargannotation = None
|
node.args.kwargannotation = None
|
||||||
node.args.kwonlyargs_annotations = [None for _ in node.args.kwonlyargs]
|
node.args.kwonlyargs_annotations = [None for _ in node.args.kwonlyargs]
|
||||||
|
node.args.posonlyargs_annotations = [None for _ in node.args.kwonlyargs]
|
||||||
|
|
||||||
# Wipe out return-value annotation.
|
# Wipe out return-value annotation.
|
||||||
if node.returns is not None:
|
if node.returns is not None:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user