Skip to content

Commit 98de669

Browse files
committed
Don't ignore imports when running mypy
This allows for more strict type checking across dependencies boundaries. To be able to check types in a more strict way, we need to use packages (-p) to avoid errors about having the same file in 2 packages (src.frequenz.sdk and frequenz.sdk), so we need to translate directory to package when running on `src`. Also we need to check individual files separately. A few type errors had to be fixed, most of them by adding type: ignore because `grpc.aio` is missing stubs. Some other ignores were added to tests for old data handling code that will probably be gone soon. All ignores are in tests though, so it shouldn't be that bad. Signed-off-by: Leandro Lucarella <[email protected]>
1 parent 9db55fd commit 98de669

File tree

5 files changed

+127
-61
lines changed

5 files changed

+127
-61
lines changed

noxfile.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
FMT_DEPS = ["black", "isort"]
1515
DOCSTRING_DEPS = ["pydocstyle", "darglint"]
1616
PYTEST_DEPS = ["pytest", "pytest-cov", "pytest-mock", "pytest-asyncio", "time-machine"]
17+
MYPY_DEPS = ["mypy", "pandas-stubs", "grpc-stubs"]
1718

1819

1920
def _source_file_paths(session: nox.Session) -> List[str]:
@@ -64,7 +65,7 @@ def ci_checks_max(session: nox.Session) -> None:
6465
session: the nox session.
6566
"""
6667
session.install(
67-
".[docs]", "mypy", "pylint", "nox", *PYTEST_DEPS, *FMT_DEPS, *DOCSTRING_DEPS
68+
".[docs]", "pylint", "nox", *PYTEST_DEPS, *FMT_DEPS, *DOCSTRING_DEPS, *MYPY_DEPS
6869
)
6970

7071
formatting(session, False)
@@ -101,35 +102,38 @@ def mypy(session: nox.Session, install_deps: bool = True) -> None:
101102
if install_deps:
102103
# install the package itself as editable, so that it is possible to do
103104
# fast local tests with `nox -R -e mypy`.
104-
session.install("-e", ".[docs]", "mypy", "nox", *PYTEST_DEPS)
105+
session.install("-e", ".[docs]", "nox", *MYPY_DEPS, *PYTEST_DEPS)
105106

106-
mypy_cmd = [
107-
"mypy",
108-
"--ignore-missing-imports",
107+
common_args = [
109108
"--install-types",
110109
"--namespace-packages",
111110
"--non-interactive",
112111
"--explicit-package-bases",
113-
"--follow-imports=silent",
114112
"--strict",
115113
]
116114

117115
# If we have session arguments, we just use those...
118116
if session.posargs:
119-
session.run(*mypy_cmd, *session.posargs)
117+
session.run("mypy", *common_args, *session.posargs)
120118
return
121119

122-
# Runs on the installed package
123-
session.run(*mypy_cmd, "-p", "frequenz.sdk")
124-
125-
# Runs on the rest of the source folders
126-
# Since we use other packages in the frequenz namespace, we need to run the
127-
# checks for frequenz.sdk from the installed package instead of the src
128-
# directory.
129-
mypy_paths = [
130-
path for path in _source_file_paths(session) if not path.startswith("src")
120+
check_paths = _source_file_paths(session)
121+
pkg_paths = [
122+
path
123+
for path in check_paths
124+
if not path.startswith("src") and not path.endswith(".py")
131125
]
132-
session.run(*mypy_cmd, *mypy_paths)
126+
file_paths = [path for path in check_paths if path.endswith(".py")]
127+
128+
pkg_args = []
129+
for pkg in pkg_paths:
130+
if pkg == "src":
131+
pkg = "frequenz.channels"
132+
pkg_args.append("-p")
133+
pkg_args.append(pkg)
134+
135+
session.run("mypy", *common_args, *pkg_args)
136+
session.run("mypy", *common_args, *file_paths)
133137

134138

135139
@nox.session

pyproject.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,11 @@ src_paths = ["src", "examples", "tests"]
9999
[tool.pytest.ini_options]
100100
asyncio_mode = "auto"
101101
required_plugins = [ "pytest-asyncio", "pytest-mock" ]
102+
103+
[[tools.mypy.overrides]]
104+
[[tool.mypy.overrides]]
105+
module = [
106+
"grpc.aio",
107+
"grpc.aio.*"
108+
]
109+
ignore_missing_imports = true

tests/test_data_handling/test_formula.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,10 @@ def test_Formula() -> None:
8787
assert f7.symbols == set(["s1", "s2", "s3"])
8888

8989
expected = pd.Series(index=df.index, data=[-2.0, -1.0, 0.0])
90-
assert (
91-
f7(**df.to_dict(orient="series")) == expected # pylint: disable=not-a-mapping
92-
).all()
90+
# We need to convert the keys as strings because they are some weird pandas
91+
# type
92+
symbols = {str(k): v for k, v in df.to_dict(orient="series").items()}
93+
assert (f7(**symbols) == expected).all()
9394

9495

9596
def test_formula_with_broken_meter() -> None:

tests/test_data_handling/test_handle_historic_data.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def mock_load_hd_read(
4545
for feature_generator in load_hd_settings.feature_generators:
4646
feature = feature_generator.feature
4747
assert isinstance(feature, str)
48-
data.update({feature: np.full(len(timestamps), len(feature))})
48+
data.update(feature=np.full(len(timestamps), len(feature))) # type: ignore
4949

5050
df_hist = pd.DataFrame(data)
5151
df_hist["timestamp"] = pd.to_datetime(df_hist.timestamp)
@@ -67,7 +67,7 @@ def test_load_compute_formula(mocker: MockerFixture) -> None:
6767
"ac_connection.total_power_active.power_supply.now",
6868
"ac_connection.total_power_active.power_consumption.now",
6969
],
70-
get_active_power,
70+
get_active_power, # type: ignore
7171
"power",
7272
)
7373
data_sampling_rate = 1.0

tests/test_microgrid/test_mock_api.py

Lines changed: 92 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,68 +18,99 @@
1818
)
1919
from frequenz.api.microgrid.microgrid_pb2_grpc import MicrogridStub
2020
from google.protobuf.empty_pb2 import Empty
21+
from unittest.mock import Mock
2122

2223
from . import mock_api
2324

2425

2526
def test_MockMicrogridServicer() -> None:
2627
api = mock_api.MockMicrogridServicer()
27-
assert list(api.ListComponents(ComponentFilter(), None).components) == []
28-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == []
28+
service_context_mock = Mock(spec=grpc.ServicerContext)
29+
assert (
30+
list(api.ListComponents(ComponentFilter(), service_context_mock).components)
31+
== []
32+
)
33+
assert (
34+
list(api.ListConnections(ConnectionFilter(), service_context_mock).connections)
35+
== []
36+
)
2937

3038
# adding new components just appends them to the list:
3139
# duplicates are not prevented, as this may be wanted
3240
# behaviour of the mock
3341
api.add_component(0, ComponentCategory.COMPONENT_CATEGORY_METER)
34-
assert list(api.ListComponents(ComponentFilter(), None).components) == [
35-
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER)
36-
]
37-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == []
42+
assert list(
43+
api.ListComponents(ComponentFilter(), service_context_mock).components
44+
) == [Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER)]
45+
assert (
46+
list(api.ListConnections(ConnectionFilter(), service_context_mock).connections)
47+
== []
48+
)
3849

3950
api.add_component(0, ComponentCategory.COMPONENT_CATEGORY_BATTERY)
40-
assert list(api.ListComponents(ComponentFilter(), None).components) == [
51+
assert list(
52+
api.ListComponents(ComponentFilter(), service_context_mock).components
53+
) == [
4154
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
4255
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_BATTERY),
4356
]
44-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == []
57+
assert (
58+
list(api.ListConnections(ConnectionFilter(), service_context_mock).connections)
59+
== []
60+
)
4561

4662
api.add_component(0, ComponentCategory.COMPONENT_CATEGORY_METER)
47-
assert list(api.ListComponents(ComponentFilter(), None).components) == [
63+
assert list(
64+
api.ListComponents(ComponentFilter(), service_context_mock).components
65+
) == [
4866
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
4967
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_BATTERY),
5068
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
5169
]
52-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == []
70+
assert (
71+
list(api.ListConnections(ConnectionFilter(), service_context_mock).connections)
72+
== []
73+
)
5374

5475
# similarly, duplicates are allowed when adding new connections
5576
api.add_connection(0, 0)
56-
assert list(api.ListComponents(ComponentFilter(), None).components) == [
77+
assert list(
78+
api.ListComponents(ComponentFilter(), service_context_mock).components
79+
) == [
5780
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
5881
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_BATTERY),
5982
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
6083
]
61-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == [
62-
Connection(start=0, end=0)
63-
]
84+
assert list(
85+
api.ListConnections(ConnectionFilter(), service_context_mock).connections
86+
) == [Connection(start=0, end=0)]
6487

6588
api.add_connection(7, 9)
66-
assert list(api.ListComponents(ComponentFilter(), None).components) == [
89+
assert list(
90+
api.ListComponents(ComponentFilter(), service_context_mock).components
91+
) == [
6792
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
6893
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_BATTERY),
6994
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
7095
]
71-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == [
96+
assert list(
97+
api.ListConnections(ConnectionFilter(), service_context_mock).connections
98+
) == [
7299
Connection(start=0, end=0),
73100
Connection(start=7, end=9),
74101
]
75102

76103
api.add_connection(0, 0)
77-
assert list(api.ListComponents(ComponentFilter(), None).components) == [
104+
assert list(
105+
api.ListComponents(ComponentFilter(), service_context_mock).components
106+
) == [
78107
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
79108
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_BATTERY),
80109
Component(id=0, category=ComponentCategory.COMPONENT_CATEGORY_METER),
81110
]
82-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == [
111+
assert list(
112+
api.ListConnections(ConnectionFilter(), service_context_mock).connections
113+
) == [
83114
Connection(start=0, end=0),
84115
Connection(start=7, end=9),
85116
Connection(start=0, end=0),
@@ -94,25 +125,33 @@ def test_MockMicrogridServicer() -> None:
94125
(999, ComponentCategory.COMPONENT_CATEGORY_BATTERY),
95126
]
96127
)
97-
assert list(api.ListComponents(ComponentFilter(), None).components) == [
128+
assert list(
129+
api.ListComponents(ComponentFilter(), service_context_mock).components
130+
) == [
98131
Component(id=9, category=ComponentCategory.COMPONENT_CATEGORY_METER),
99132
Component(id=99, category=ComponentCategory.COMPONENT_CATEGORY_INVERTER),
100133
Component(id=999, category=ComponentCategory.COMPONENT_CATEGORY_BATTERY),
101134
]
102-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == [
135+
assert list(
136+
api.ListConnections(ConnectionFilter(), service_context_mock).connections
137+
) == [
103138
Connection(start=0, end=0),
104139
Connection(start=7, end=9),
105140
Connection(start=0, end=0),
106141
]
107142

108143
# similarly `set_connections` overrides all the existing connections
109144
api.set_connections([(999, 9), (99, 19), (909, 101), (99, 91)])
110-
assert list(api.ListComponents(ComponentFilter(), None).components) == [
145+
assert list(
146+
api.ListComponents(ComponentFilter(), service_context_mock).components
147+
) == [
111148
Component(id=9, category=ComponentCategory.COMPONENT_CATEGORY_METER),
112149
Component(id=99, category=ComponentCategory.COMPONENT_CATEGORY_INVERTER),
113150
Component(id=999, category=ComponentCategory.COMPONENT_CATEGORY_BATTERY),
114151
]
115-
assert list(api.ListConnections(ConnectionFilter(), None).connections) == [
152+
assert list(
153+
api.ListConnections(ConnectionFilter(), service_context_mock).connections
154+
) == [
116155
Connection(start=999, end=9),
117156
Connection(start=99, end=19),
118157
Connection(start=909, end=101),
@@ -121,20 +160,28 @@ def test_MockMicrogridServicer() -> None:
121160

122161
# connection requests can be filtered
123162
assert list(
124-
api.ListConnections(ConnectionFilter(starts=[999]), None).connections
163+
api.ListConnections(
164+
ConnectionFilter(starts=[999]), service_context_mock
165+
).connections
125166
) == [Connection(start=999, end=9)]
126167
assert list(
127-
api.ListConnections(ConnectionFilter(starts=[99]), None).connections
168+
api.ListConnections(
169+
ConnectionFilter(starts=[99]), service_context_mock
170+
).connections
128171
) == [Connection(start=99, end=19), Connection(start=99, end=91)]
129-
assert list(api.ListConnections(ConnectionFilter(ends=[19]), None).connections) == [
130-
Connection(start=99, end=19)
131-
]
132172
assert list(
133-
api.ListConnections(ConnectionFilter(ends=[101]), None).connections
173+
api.ListConnections(
174+
ConnectionFilter(ends=[19]), service_context_mock
175+
).connections
176+
) == [Connection(start=99, end=19)]
177+
assert list(
178+
api.ListConnections(
179+
ConnectionFilter(ends=[101]), service_context_mock
180+
).connections
134181
) == [Connection(start=909, end=101)]
135182
assert list(
136183
api.ListConnections(
137-
ConnectionFilter(starts=[99, 999], ends=[9, 19]), None
184+
ConnectionFilter(starts=[99, 999], ends=[9, 19]), service_context_mock
138185
).connections
139186
) == [Connection(start=999, end=9), Connection(start=99, end=19)]
140187

@@ -148,11 +195,17 @@ def test_MockMicrogridServicer() -> None:
148195
],
149196
connections=[(7, 8), (8, 9)],
150197
)
151-
assert list(api_prealloc.ListComponents(ComponentFilter(), None).components) == [
198+
assert list(
199+
api_prealloc.ListComponents(ComponentFilter(), service_context_mock).components
200+
) == [
152201
Component(id=7, category=ComponentCategory.COMPONENT_CATEGORY_GRID),
153202
Component(id=9, category=ComponentCategory.COMPONENT_CATEGORY_LOAD),
154203
]
155-
assert list(api_prealloc.ListConnections(ConnectionFilter(), None).connections) == [
204+
assert list(
205+
api_prealloc.ListConnections(
206+
ConnectionFilter(), service_context_mock
207+
).connections
208+
) == [
156209
Connection(start=7, end=8),
157210
Connection(start=8, end=9),
158211
]
@@ -170,16 +223,16 @@ async def test_MockGrpcServer() -> None:
170223
server1 = mock_api.MockGrpcServer(servicer1, port=57809)
171224
await server1.start()
172225

173-
client = MicrogridStub(grpc.aio.insecure_channel("[::]:57809"))
226+
client = MicrogridStub(grpc.aio.insecure_channel("[::]:57809")) # type: ignore
174227

175-
components1 = await client.ListComponents(Empty())
228+
components1 = await client.ListComponents(Empty()) # type: ignore
176229
assert list(components1.components) == [
177230
Component(id=1, category=ComponentCategory.COMPONENT_CATEGORY_GRID),
178231
Component(id=2, category=ComponentCategory.COMPONENT_CATEGORY_METER),
179232
Component(id=3, category=ComponentCategory.COMPONENT_CATEGORY_LOAD),
180233
]
181234

182-
connections1 = await client.ListConnections(ConnectionFilter())
235+
connections1 = await client.ListConnections(ConnectionFilter()) # type: ignore
183236
assert list(connections1.connections) == [
184237
Connection(start=1, end=2),
185238
Connection(start=2, end=3),
@@ -199,33 +252,33 @@ async def test_MockGrpcServer() -> None:
199252
server2 = mock_api.MockGrpcServer(servicer2, port=57809)
200253
await server2.start()
201254

202-
components2 = await client.ListComponents(Empty())
255+
components2 = await client.ListComponents(Empty()) # type: ignore
203256
assert list(components2.components) == [
204257
Component(id=6, category=ComponentCategory.COMPONENT_CATEGORY_GRID),
205258
Component(id=77, category=ComponentCategory.COMPONENT_CATEGORY_METER),
206259
Component(id=888, category=ComponentCategory.COMPONENT_CATEGORY_EV_CHARGER),
207260
Component(id=9999, category=ComponentCategory.COMPONENT_CATEGORY_LOAD),
208261
]
209262

210-
connections2 = await client.ListConnections(ConnectionFilter())
263+
connections2 = await client.ListConnections(ConnectionFilter()) # type: ignore
211264
assert list(connections2.connections) == [
212265
Connection(start=6, end=77),
213266
Connection(start=6, end=888),
214267
Connection(start=77, end=9999),
215268
]
216269

217-
connections2b = await client.ListConnections(ConnectionFilter(starts=[6]))
270+
connections2b = await client.ListConnections(ConnectionFilter(starts=[6])) # type: ignore
218271
assert list(connections2b.connections) == [
219272
Connection(start=6, end=77),
220273
Connection(start=6, end=888),
221274
]
222275

223-
connections2c = await client.ListConnections(ConnectionFilter(ends=[9999]))
276+
connections2c = await client.ListConnections(ConnectionFilter(ends=[9999])) # type: ignore
224277
assert list(connections2c.connections) == [Connection(start=77, end=9999)]
225278

226279
connections2d = await client.ListConnections(
227280
ConnectionFilter(starts=[6, 77], ends=[888, 9999])
228-
)
281+
) # type: ignore
229282
assert list(connections2d.connections) == [
230283
Connection(start=6, end=888),
231284
Connection(start=77, end=9999),

0 commit comments

Comments
 (0)