Skip to content

Commit a76a88f

Browse files
committed
refact: improve typing
1 parent b7f0d36 commit a76a88f

5 files changed

Lines changed: 60 additions & 47 deletions

File tree

src/api/constants.py

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
import enum
1111
import os
12-
from typing import Optional, Union
12+
from enum import StrEnum
13+
from typing import Final, Optional, Union
1314

1415
from .decorator import classproperty
1516

@@ -29,7 +30,7 @@
2930

3031

3132
@enum.unique
32-
class CLASS(str, enum.Enum):
33+
class CLASS(StrEnum):
3334
"""Enums class constants"""
3435

3536
unknown = "unknown" # 0
@@ -80,10 +81,12 @@ class TYPE(enum.IntEnum):
8081
fixed = 7
8182
float = 8
8283
string = 9
84+
boolean = 10
8385

8486
@classmethod
85-
def type_size(cls, type_: "TYPE"):
87+
def type_size(cls, type_: "TYPE") -> int:
8688
type_sizes = {
89+
cls.boolean: 1,
8790
cls.byte: 1,
8891
cls.ubyte: 1,
8992
cls.integer: 2,
@@ -98,59 +101,66 @@ def type_size(cls, type_: "TYPE"):
98101
return type_sizes[type_]
99102

100103
@classproperty
101-
def types(cls):
104+
def types(cls) -> set["TYPE"]:
102105
return set(TYPE)
103106

104107
@classmethod
105-
def size(cls, type_: "TYPE"):
108+
def size(cls, type_: "TYPE") -> int:
106109
return cls.type_size(type_)
107110

108111
@classproperty
109-
def integral(cls):
110-
return {cls.byte, cls.ubyte, cls.integer, cls.uinteger, cls.long, cls.ulong}
112+
def integral(cls) -> set["TYPE"]:
113+
return {cls.boolean, cls.byte, cls.ubyte, cls.integer, cls.uinteger, cls.long, cls.ulong}
111114

112115
@classproperty
113-
def signed(cls):
116+
def signed(cls) -> set["TYPE"]:
114117
return {cls.byte, cls.integer, cls.long, cls.fixed, cls.float}
115118

116119
@classproperty
117-
def unsigned(cls):
118-
return {cls.ubyte, cls.uinteger, cls.ulong}
120+
def unsigned(cls) -> set["TYPE"]:
121+
return {cls.boolean, cls.ubyte, cls.uinteger, cls.ulong}
119122

120123
@classproperty
121-
def decimals(cls):
124+
def decimals(cls) -> set["TYPE"]:
122125
return {cls.fixed, cls.float}
123126

124127
@classproperty
125-
def numbers(cls):
126-
return set(cls.integral) | set(cls.decimals)
128+
def numbers(cls) -> set["TYPE"]:
129+
return cls.integral | cls.decimals
127130

128131
@classmethod
129-
def is_valid(cls, type_: "TYPE"):
132+
def is_valid(cls, type_: "TYPE") -> bool:
130133
"""Whether the given type is
131134
valid or not.
132135
"""
133136
return type_ in cls.types
134137

135138
@classmethod
136-
def is_signed(cls, type_: "TYPE"):
139+
def is_signed(cls, type_: "TYPE") -> bool:
137140
return type_ in cls.signed
138141

139142
@classmethod
140-
def is_unsigned(cls, type_: "TYPE"):
143+
def is_unsigned(cls, type_: "TYPE") -> bool:
141144
return type_ in cls.unsigned
142145

143146
@classmethod
144-
def to_signed(cls, type_: "TYPE"):
147+
def to_signed(cls, type_: "TYPE") -> "TYPE":
145148
"""Return signed type or equivalent"""
146149
if type_ in cls.unsigned:
147-
return {TYPE.ubyte: TYPE.byte, TYPE.uinteger: TYPE.integer, TYPE.ulong: TYPE.long}[type_]
150+
return {
151+
TYPE.boolean: TYPE.boolean,
152+
TYPE.ubyte: TYPE.byte,
153+
TYPE.uinteger: TYPE.integer,
154+
TYPE.ulong: TYPE.long,
155+
}[type_]
156+
148157
if type_ in cls.decimals or type_ in cls.signed:
149158
return type_
159+
150160
return cls.unknown
151161

152162
@staticmethod
153-
def to_string(type_: "TYPE"):
163+
def to_string(type_: "TYPE") -> str:
154164
"""Return ID representation (string) of a type"""
155165
return type_.name
156166

@@ -173,11 +183,11 @@ class SCOPE(str, enum.Enum):
173183
parameter = "parameter"
174184

175185
@staticmethod
176-
def is_valid(scope: Union[str, "SCOPE"]):
186+
def is_valid(scope: Union[str, "SCOPE"]) -> bool:
177187
return scope in set(SCOPE)
178188

179189
@staticmethod
180-
def to_string(scope: "SCOPE"):
190+
def to_string(scope: "SCOPE") -> str:
181191
assert SCOPE.is_valid(scope)
182192
return scope.value
183193

@@ -208,7 +218,7 @@ class LoopType(str, enum.Enum):
208218
# ----------------------------------------------------------------------
209219
# Deprecated suffixes for variable names, such as "a$"
210220
# ----------------------------------------------------------------------
211-
DEPRECATED_SUFFIXES = ("$", "%", "&")
221+
DEPRECATED_SUFFIXES: Final[frozenset[str]] = frozenset(("$", "%", "&"))
212222

213223
# ----------------------------------------------------------------------
214224
# Identifier type

src/symbols/type_.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ def __bool__(self):
108108

109109

110110
class SymbolBASICTYPE(SymbolTYPE):
111-
"""Defines a basic type (Ubyte, Byte, etc..)
112-
Basic (default) types are defined upon start and are case insensitive.
111+
"""Defines a basic type (Ubyte, Byte, etc.)
112+
Basic (default) types are defined upon start and are case-insensitive.
113113
If name is None or '', default typename from TYPES.to_string will be used.
114114
"""
115115

@@ -237,73 +237,74 @@ class Type:
237237
fixed = SymbolBASICTYPE(TYPE.fixed)
238238
float_ = SymbolBASICTYPE(TYPE.float)
239239
string = SymbolBASICTYPE(TYPE.string)
240+
boolean = SymbolBASICTYPE(TYPE.boolean)
240241

241-
types = [unknown, ubyte, byte_, uinteger, integer, ulong, long_, fixed, float_, string]
242+
types = unknown, ubyte, byte_, uinteger, integer, ulong, long_, fixed, float_, string, boolean
242243

243244
_by_name = {x.name: x for x in types}
244245

245246
@staticmethod
246-
def size(t: SymbolTYPE):
247+
def size(t: SymbolTYPE) -> int:
247248
assert isinstance(t, SymbolTYPE)
248249
return t.size
249250

250251
@staticmethod
251-
def to_string(t: SymbolTYPE):
252+
def to_string(t: SymbolTYPE) -> str:
252253
assert isinstance(t, SymbolTYPE)
253254
return t.name
254255

255256
@classmethod
256-
def by_name(cls, typename):
257+
def by_name(cls, typename) -> SymbolBASICTYPE | None:
257258
"""Converts a given typename to Type"""
258259
return cls._by_name.get(typename, None)
259260

260261
@classproperty
261-
def integrals(cls):
262-
return (cls.byte_, cls.ubyte, cls.integer, cls.uinteger, cls.long_, cls.ulong)
262+
def integrals(cls) -> set[SymbolBASICTYPE]:
263+
return {cls.boolean, cls.byte_, cls.ubyte, cls.integer, cls.uinteger, cls.long_, cls.ulong}
263264

264265
@classproperty
265-
def signed(cls):
266-
return cls.byte_, cls.integer, cls.long_, cls.fixed, cls.float_
266+
def signed(cls) -> set[SymbolBASICTYPE]:
267+
return {cls.byte_, cls.integer, cls.long_, cls.fixed, cls.float_}
267268

268269
@classproperty
269-
def unsigned(cls):
270-
return cls.ubyte, cls.uinteger, cls.ulong
270+
def unsigned(cls) -> set[SymbolBASICTYPE]:
271+
return {cls.boolean, cls.ubyte, cls.uinteger, cls.ulong}
271272

272273
@classproperty
273-
def decimals(cls):
274-
return cls.fixed, cls.float_
274+
def decimals(cls) -> set[SymbolBASICTYPE]:
275+
return {cls.fixed, cls.float_}
275276

276277
@classproperty
277-
def numbers(cls):
278-
return tuple(list(cls.integrals) + list(cls.decimals))
278+
def numbers(cls) -> set[SymbolBASICTYPE]:
279+
return cls.integrals | cls.decimals
279280

280281
@classmethod
281-
def is_numeric(cls, t: SymbolTYPE):
282+
def is_numeric(cls, t: SymbolTYPE) -> bool:
282283
assert isinstance(t, SymbolTYPE)
283284
return t.final in cls.numbers
284285

285286
@classmethod
286-
def is_signed(cls, t: SymbolTYPE):
287+
def is_signed(cls, t: SymbolTYPE) -> bool:
287288
assert isinstance(t, SymbolTYPE)
288289
return t.final in cls.signed
289290

290291
@classmethod
291-
def is_unsigned(cls, t: SymbolTYPE):
292+
def is_unsigned(cls, t: SymbolTYPE) -> bool:
292293
assert isinstance(t, SymbolTYPE)
293294
return t.final in cls.unsigned
294295

295296
@classmethod
296-
def is_integral(cls, t: SymbolTYPE):
297+
def is_integral(cls, t: SymbolTYPE) -> bool:
297298
assert isinstance(t, SymbolTYPE)
298299
return t.final in cls.integrals
299300

300301
@classmethod
301-
def is_decimal(cls, t: SymbolTYPE):
302+
def is_decimal(cls, t: SymbolTYPE) -> bool:
302303
assert isinstance(t, SymbolTYPE)
303304
return t.final in cls.decimals
304305

305306
@classmethod
306-
def is_string(cls, t: SymbolTYPE):
307+
def is_string(cls, t: SymbolTYPE) -> bool:
307308
assert isinstance(t, SymbolTYPE)
308309
return t.final == cls.string
309310

tests/runtime/check_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import signal
44
import sys
55

6-
import zx
6+
import zx # type: ignore[import-untyped]
77

88

99
def signal_handler(sig, frame):

tests/runtime/update_test.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import sys
77

8-
import zx
8+
import zx # type: ignore[import-untyped]
99

1010

1111
class Stop(Exception):
@@ -46,6 +46,7 @@ def run_test(self, filename):
4646
def main():
4747
with TakeSnapshot() as t:
4848
t.run_test(sys.argv[1])
49+
4950
print("OK")
5051

5152

tests/symbols/test_symbolBASICTYPE.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ def test__ne__(self):
4545

4646
def test_to_signed(self):
4747
for type_ in TYPE.types:
48-
if type_ is TYPE.unknown or type_ == TYPE.string:
48+
if type_ in {TYPE.unknown, TYPE.string, TYPE.boolean}:
4949
continue
50+
5051
t = SymbolBASICTYPE(type_)
5152
q = t.to_signed()
5253
self.assertTrue(q.is_signed)

0 commit comments

Comments
 (0)