fix(gateway): address SonarQube PR-mode findings on F2/F3 code

- data_sink.py: _IDENTIFIER_RE uses \w+/re.ASCII instead of the
  equivalent-but-verbose [A-Za-z0-9_]+ character class (verified same
  match behavior). NOSONAR on update_write_status's 'async with no
  await inside' - deliberate, per the ponytail comment already in the
  method body (uniform async interface across DataSink, no async pg driver).
- test_grpc_server.py: move make_request() out of the pytest.raises
  block so exactly one call can raise the expected exception.
- sonar-project.properties: exclude ingestor/proto/ (generated grpc
  code) from analysis - its ReadTag/etc. names are dictated by
  grpcio-tools, not a style choice, and renaming them breaks the wire.
This commit is contained in:
PedroHMCosme
2026-09-22 16:57:29 -03:00
parent 54408d6160
commit ff9339d408
3 changed files with 8 additions and 3 deletions

View File

@@ -6,7 +6,7 @@ import ingestor.metrics as metrics
# fullmatch (no ^/$ anchors) so a trailing newline can't slip through — `$` would # fullmatch (no ^/$ anchors) so a trailing newline can't slip through — `$` would
# match before a trailing '\n', which is not what we want for a SQL identifier. # match before a trailing '\n', which is not what we want for a SQL identifier.
_IDENTIFIER_RE = re.compile(r'[A-Za-z0-9_]+') _IDENTIFIER_RE = re.compile(r'\w+', re.ASCII)
class DataSink: class DataSink:
@@ -42,7 +42,7 @@ class DataSink:
}, },
) )
async def update_write_status(self, cmd: dict, result) -> None: async def update_write_status(self, cmd: dict, result) -> None: # NOSONAR
"""UPDATE the per-model prediction row's write_status (C3), by timestamp+model_id. """UPDATE the per-model prediction row's write_status (C3), by timestamp+model_id.
schema/table_name are per-model SQL identifiers, not values — they can't be schema/table_name are per-model SQL identifiers, not values — they can't be

View File

@@ -8,3 +8,7 @@ sonar.python.coverage.reportPaths=coverage.xml
sonar.python.xunit.reportPath=pytest.xml sonar.python.xunit.reportPath=pytest.xml
sonar.python.version=3.11 sonar.python.version=3.11
sonar.coverage.exclusions=ingestor/app.py sonar.coverage.exclusions=ingestor/app.py
# Generated protoc/grpcio-tools output - not hand-maintained; renaming its
# ReadTag/etc. methods to satisfy naming-convention rules would break gRPC
# wire compatibility (grpcio-tools dictates these names, not style choice).
sonar.exclusions=ingestor/proto/**

View File

@@ -60,8 +60,9 @@ async def test_read_tag_aborts_with_internal_on_engine_failure():
context = AsyncMock() context = AsyncMock()
context.abort.side_effect = grpc.RpcError('aborted') context.abort.side_effect = grpc.RpcError('aborted')
request = make_request()
with pytest.raises(grpc.RpcError): with pytest.raises(grpc.RpcError):
await servicer.ReadTag(make_request(), context) await servicer.ReadTag(request, context)
context.abort.assert_awaited_once() context.abort.assert_awaited_once()
args = context.abort.call_args.args args = context.abort.call_args.args