@@ -273,7 +273,7 @@ def kernel_auth_kwargs(
273273 "auth_type" : "oauth-u2m" ,
274274 "client_id" : client_id or PYSQL_OAUTH_CLIENT_ID ,
275275 "redirect_port" : (
276- int (redirect_port )
276+ _coerce_redirect_port (redirect_port )
277277 if client_id and redirect_port is not None
278278 else PYSQL_OAUTH_REDIRECT_PORT_RANGE [0 ]
279279 ),
@@ -312,6 +312,23 @@ def kernel_auth_kwargs(
312312 )
313313
314314
315+ def _coerce_redirect_port (redirect_port : Any ) -> int :
316+ """Coerce an ``oauth_redirect_port`` value (which may arrive as a string,
317+ e.g. from a DSN) to an int.
318+
319+ A non-numeric value is a caller error; surface it as a PEP 249
320+ ``ProgrammingError`` (as ``_normalize_scopes`` does for malformed
321+ ``oauth_scopes``) rather than a bare ``ValueError``, so callers get a
322+ consistent, actionable exception type for garbled input."""
323+ try :
324+ return int (redirect_port )
325+ except (TypeError , ValueError ):
326+ raise ProgrammingError (
327+ f"oauth_redirect_port must be an integer (or a string parseable as "
328+ f"one), got { redirect_port !r} ."
329+ )
330+
331+
315332def _normalize_scopes (scopes : Any ) -> Optional [list ]:
316333 """Normalise an ``oauth_scopes`` value to a list of strings, or
317334 ``None`` to let the kernel apply its defaults.
0 commit comments